String into vector - c++

I have a string which i then want to store in a vector
string a = "N\nT\n";
after each new line to be in a different cell.
std::string ss (".V/\n.F/\n.R/\n");
for(int i = 0; i< ss.size(); i++)
{
test1.push_back(ss);
}
I want to store the string in vector test1
is this the best way?

Your code won't work; it'll store the string ss.size() times in the vector.
You might want to use a string stream to split the string:
std::stringstream stream(ss);
std::string line;
while (std::getline(stream, line)) {
test1.push_back(line);
}
Note that the newline character will be discarded. If you want to keep it, push_back(line + "\n");.

Boost::split will do this for you. See usage details here:
http://www.boost.org/doc/libs/1_49_0/doc/html/string_algo/usage.html#id3184031

If the newline can be discarded then you could use std::copy():
#include <iostream>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <string>
#include <vector>
int main()
{
std::string ss(".V/\n.F/\n.R/\n");
std::istringstream in(ss);
std::vector<std::string> test1;
std::copy(std::istream_iterator<std::string>(in),
std::istream_iterator<std::string>(),
std::back_inserter(test1));
std::for_each(test1.begin(),
test1.end(),
[](const std::string& s)
{
std::cout << s << "\n";
});
return 0;
}
Output:
.V/
.F/
.R/

This certainly isn't the best way, because it doesn't work. This just pushes ss.size() instances of the std::string in the vector.
You can use the find and substr methods to partition the string and push them in the array. (not gonna write the actual code though, might be a good exercise).

Related

Is there a simple way for splitting one line of input separated by a space character into integers in C++?

I am a C++ beginner, and I have been working on a project in which you have to input some integers separated by a space and the program will have to output all possible arrangements of the integers. I know that in python, this could be done using [int(item) for item in input().split()], but I don't know how to do the same in C++. I want to use a easy method built-in in C++. Can anyone provide some opinion? Any help will be appreciated.
You see, you create a vector of integers from the string and then simply permute the vector:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <sstream>
#include <string>
#include <vector>
int main() {
std::string str;
std::getline(std::cin, str);
std::istringstream iss(str);
std::vector<int> vec;
int temp = 0;
while (iss >> temp) {
vec.push_back(temp);
}
//you now have a vector of integers
std::sort(vec.begin(), vec.end()); //this is a must as `std::permutations()` stops when the container is lexicographically sorted
do {
std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>{std::cout, " "});
std::cout << "\n";
} while (std::next_permutation(vec.begin(), vec.end()));
return 0;
}
To know how to output all permutations of all possible lengths, take a look at
How to create a permutation in c++ using STL for number of places lower than the total length

C++ Parsing a CSV file into vector of vectors: Loosing string 1st character

I am reading a CSV file into vector of string vectors. I have written code below.
#include<iostream>
#include<fstream>
#include<string>
#include <vector>
#include <fstream>
#include <cmath>
#include <sstream>
using namespace std;
int main()
{
ifstream mesh;
mesh.open("mesh_reference.csv");
vector<vector<string> > point_coordinates;
string line, word;
while (getline(mesh,line))
{
stringstream ss(line);
vector<string> row;
while (getline(ss, word, ','))
{
row.push_back(word);
}
point_coordinates.push_back(row);
}
for(int i=0; i<point_coordinates.size(); i++)
{
for(int j=0; j<3; j++)
cout<<point_coordinates[i][j]<<" ";
cout<<endl;
}
return 0;
}
When I print out the vector of vectors, I see that I am loosing the first character of Element at 0 position in the vector row. Basically, point_coordinates[0][0] is displaying 0.0001 while the string is supposed to be -0.0001. I am not able to understand the reason for the same. Kindly help.
A typical output line is
.0131 -0.019430324 0.051801
Whereas the CSV data is
0.0131,-0.019430324,0.051801
SAMPLE CSV DATA FROM FILE
NODES__X,NODES__Y,NODES__Z
0.0131,-0.019430324,0.051801
0.0131,-0.019430324,0.06699588
0.0131,-0.018630324,0.06699588
0.0131,-0.018630324,0.051801
0.0131,-0.017630324,0.050801
0.0131,-0.017630324,0.050001
0.0149,-0.017630324,0.050001
0.0149,-0.019430324,0.051801
Although the problem is already solved, I would like to show you a solution using some modern C++ algorithms and eliminating minor issues.
Do not use using namespace std;. You should not do this
Ne need for a separate file.open. The std::ifstream constructor will open the file for you. And the destructor will close it
Check if the file could be opened. The ifstreams ! operator is overloaded. So you can do a boolean check
Do not use int in for loops where you compare against .size(). Use ````size_t instead
Always initialize all variables, even if there is an assignement in the next line
For tokenizing you should use std::sregex_token_iterator. It has exactly been designed for this purpose
In modern C++ you are encouraged to use algorithms
Please see an improved version of your code below:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <iterator>
#include <regex>
const std::regex comma(",");
int main()
{
// Open source file.
std::ifstream mesh("r:\\mesh_reference.csv");
// Here we will store the result
std::vector<std::vector<std::string>> point_coordinates;
// We want to read all lines of the file
std::string line{};
while (mesh && getline(mesh, line)) {
// Tokenize the line and store result in vector. Use range constructor of std::vector
std::vector<std::string> row{ std::sregex_token_iterator(line.begin(),line.end(),comma,-1), std::sregex_token_iterator() };
point_coordinates.push_back(row);
}
// Print result. Go through all lines and then copy line elements to std::cout
std::for_each(point_coordinates.begin(), point_coordinates.end(), [](std::vector<std::string> & vs) {
std::copy(vs.begin(), vs.end(), std::ostream_iterator<std::string>(std::cout, " ")); std::cout << "\n"; });
return 0;
}
Please consider, if you may want to use such an approach in the future

Trouble with parsing text file based on commas (C++)

I am working on creating a program that is supposed to read a text file (ex. dog, buddy,,125,,,cat,,,etc...) line by line and parse it based on commas. This is what I have so far but when I run it, nothing happens. I am not entirely sure what i'm doing wrong and I am fairly new to the higher level concepts.
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <cstdlib>
#include <sstream>
#include <vector>
using namespace std;
int main()
{
std::ifstream file_("file.txt"); //open file
std::string line_; //declare line_ as a string
std::stringstream ss(line_); //using line as stringstream
vector<string> result; //declaring vector result
while (file_.is_open() && ss.good())
{ //while the file is open and stringstream is good
std::string substr; //declares substr as a string
getline( ss, substr, ',' ); //getting the stringstream line_ and substr and parsing
result.push_back(substr);
}
return 0;
}
Did you forget to add a line like std::getline(file_, line_);? file_ was not read from at all and line_ was put into ss right after it was declared when it was empty.
I'm not sure why you checked if file_ is open in your loop condition since it will always be open unless you close it.
As far as I know, using good() as a loop condition is not a good idea. The flags will only be set the first time an attempt is made to read past the end of the file (it won't be set if you read to exactly the end of the file when hitting the delimiter), so if there was a comma at the end of the file the loop will run one extra time. Instead, you should somehow put the flag check after the extraction and before you use the result of the extraction. A simple way is to just use the getline() call as your loop condition since the function returns the stream itself, which when cast into a bool is equivalent to !ss.fail(). That way, the loop will not execute if the end of the file is reached without extracting any characters.
By the way, comments like //declaring vector result is pretty much useless since it gives no useful information that you can't easily see from the code.
My code:
#include <iostream>
#include <fstream>
#include <vector>
#include <sstream>
int main()
{
std::ifstream file("input.txt");
std::string line, word;
std::vector<std::vector<string>> result; //result[i][j] = the jth word in the input of the ith line
while(std::getline(file, line))
{
std::stringstream ss(line);
result.emplace_back();
while(std::getline(ss, word, ','))
{
result.back().push_back(word);
}
}
//printing results
for(auto &i : result)
{
for(auto &j : i)
{
std::cout << j << ' ';
}
std::cout << '\n';
}
}

Ignore spaces in vector C++

I'm trying to split a string in individual words using vector in C++. So I would like to know how to ignore spaces in vector, if user put more than one space between words in string.
How would I do that?
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main(){
cout<<"Sentence: ";
string sentence;
getline(cin,sentence);
vector<string> my;
int start=0;
unsigned int end=sentence.size();
unsigned int temp=0;
while(temp<end){
int te=sentence.find(" ",start);
temp=te;
my.push_back(sentence.substr(start, temp-start));
start=temp+1;
}
unsigned int i;
for(i=0 ; i<my.size() ; i++){
cout<<my[i]<<endl;
}
return 0;
}
Four things:
When reading input from a stream into astring using the overloaded >> operator, then it automatically separates on white-space. I.e. it reads "words".
There exists an input stream that uses a string as the input, std::istringstream.
You can use iterators with streams, like e.g. std::istream_iterator.
std::vector have a constructor taking a pair of iterators.
That means your code could simply be
std::string line;
std::getline(std::cin, line);
std::istringstream istr(line);
std::vector<std::string> words(std::istream_iterator<std::string>(istr),
std::istream_iterator<std::string>());
After this, the vector words will contain all the "words" from the input line.
You can easily print the "words" using std::ostream_iterator and std::copy:
std::copy(begin(words), end(words),
std::ostream_iterator<std::string>(std::cout, "\n"));
The easiest way is to use a std::istringstream like follows:
std::string sentence;
std::getline(std::cin,sentence);
std::istringstream iss(sentence);
std::vector<std::string> my;
std::string word;
while(iss >> word) {
my.push_back(word);
}
Any whitespaces will be ignored and skipped automatically.
You can create the vector directly using the std::istream_iterator which skips white spaces:
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <iterator>
int main() {
std::string str = "Hello World Lorem Ipsum The Quick Brown Fox";
std::istringstream iss(str);
std::vector<std::string> vec {std::istream_iterator<std::string>(iss),
std::istream_iterator<std::string>() };
for (const auto& el : vec) {
std::cout << el << '\n';
}
}
Here is a function which divides given sentence into words.
#include <string>
#include <vector>
#include <sstream>
#include <utility>
std::vector<std::string> divideSentence(const std::string& sentence) {
std::stringstream stream(sentence);
std::vector<std::string> words;
std::string word;
while(stream >> word) {
words.push_back(std::move(word));
}
return words;
}
Reducing double, triple etc. spaces in string is a problem you'll encounter again and again. I've always used the following very simple algorithm:
Pseudocode:
while " " in string:
string.replace(" ", " ")
After the while loop, you know your string only has single spaces since multiple consecutive spaces were compressed to singles.
Most languages allow you to search for a substring in a string and most languages have the ability to run string.replace() so it's a useful trick.

C++: Grab every character of a file ignoring newlines and whitespace

So this seems like such a simple problem but i am struggling with it. I have a big file that i want to just go through and put every char in the file into a char array. My problem is i dont know how to deal with the newlines and any whitespace. is there a way to just go through the file and grab all of the chars, skip over newlines, and put them in an array?
Yes, i have searched around on google but with no luck.
Here is how it would be trivially done in C. I am sure it can be done using the C++ interface as well, but the C library is part of C++ too.
#include <stdio.h>
#include <ctype.h>
FILE *f = fopen ("filename", "r");
if (!f)
error ...
char array [BIGENOUGH];
int index = 0;
while (!feof (f))
{
char c = fgetc (f);
if (!isspace (c))
array [index++] = c;
}
fclose (f):
The preferred method would be to use the standard library string. Example of removing whitespace from a string here. How to read from a file line-by-line here.
Example code:
fstream file;
file.open("test.txt",ios::in);
while ( !file.eof() ) {
string str;
file >> str;
remove_if(str.begin(), str.end(), isspace);
str.erase(remove_if(str.begin(), str.end(), isspace), str.end());
//save str here
}
file.close();
remove_if sample implementation:
template<typename T, typename P>
T remove_if(T beg, T end, P pred)
{
T dest = beg;
for (T itr = beg;itr != end; ++itr)
if (!pred(*itr))
*(dest++) = *itr;
return dest;
}
This code is untested.
The key to doing what you want in C++ is to take advantage of the formatted input operations. You want to ignore whitespace; the formatted input methods do exactly that.
Here is one way, using the canonical C++ input loop:
#include <fstream>
#include <iostream>
int main () {
std::ifstream inFile("input.txt");
char c;
std::string result;
while(inFile >> c)
result.push_back(c);
std::cout << result;
}
I prefer standard algorithms to hand-crafted loops. Here is one way to do it in C++, using std::copy. Note that this way and the first way are nearly identical.
#include <vector>
#include <fstream>
#include <iostream>
#include <iterator>
#include <algorithm>
int main () {
std::ifstream inFile("input.txt");
std::string result;
std::copy(std::istream_iterator<char>(inFile),
std::istream_iterator<char>(),
std::back_inserter(result));
std::cout << result;
}
Another way, this time with std::accumulate. std::accumulate uses operator+ instead of push_back, so we can read the file in a string at a time.
#include <vector>
#include <fstream>
#include <numeric>
#include <iostream>
#include <iterator>
#include <algorithm>
int main () {
std::ifstream inFile("input.txt");
std::string result =
std::accumulate(
std::istream_iterator<std::string>(inFile),
std::istream_iterator<std::string>(),
std::string());
std::cout << result;
}
fgets allows you to read until a newline (notice that the newline still exists in the destination buffer, so make sure to overwrite it with '\0').
Read the file line by line, and each time concatenate your output with the previous output.