read words from line in C++ - c++

I was wondering if there was a way to read all of the "words" from a line of text.
the line will look like this: R,4567890,Dwyer,Barb,CSCE 423,CSCE 486
Is there a way to use the comma as a delimiter to parse this line into an array or something?

Yes, use std::getline and stringstreams.
std::string str = "R,4567890,Dwyer,Barb,CSCE 423,CSCE 486";
std::istringstream iss(str);
std::vector<std::string> words;
while (std::getline(iss, str, ','))
words.push_back(str);

//#include sstream with angular braces in header files
std::string str = "R,4567890,Dwyer,Barb,CSCE 423,CSCE 486";
std::istringstream iss(str,istringstream:in);
vector<std::string> words;
while (std::getline(iss, str, ','))
words.push_back(str);

Related

How to read string with spaces, until a '\r'?

I want to read a long string, and split it into smaller ones, where each new row of the big string is an entry for the smaller ones. However, I only want it to break at '\r', and not at spaces.
This is a sample code of what I'm doing right now:
std::vector<std::string> m_list;
std::ifstream input("data.txt");
std::string str;
std::getline(input, str);
std::istringstream iss(str);
std::string temp;
while (iss >> temp)
{
m_list.push_back(temp);
}
However, this code breaks the string upon encountering spaces, as well.
You where definitely on the right path, you actually just need to skip the direct string stream operation. This should work fine:
std::vector<std::string> m_list;
std::ifstream input("data.txt");
std::string str;
while (std::getline(input, str, '\r'))
{
m_list.push_back(str);
}

Custom istream end iterator

I want to read one line of text from an istream and split it into words. My current code is
vector<string>((istream_iterator<string>(f)),
istream_iterator<string>());
where f is an ifstream object. However, this reads to the end of the file, and I want to stop it from reading when it reaches a newline. Is there any way to do something like istream_iterator<string>("\n") so the vector constructor will stop pushing back when it reaches a newline?
Use std::getline() to read a single line, and then use std::istringstream to read words from that line, eg:
std::string line;
std::getline(f, line);
std::istringstream iss(line);
std::vector<std::string> words(
std::istream_iterator<std::string>(iss),
std::istream_iterator<std::string>()
);
Use std::getline to read each line and push them to your result container
std::vector<std::string> lines;
for (std::string line; std::getline(f, line); lines.push_back(line));
Edit: Remy Lebeau already answered to OP's question, I want to clarify my code:
Normaly, to read lines in a file we would write something like
while (f.good())
{
std::string line;
std::getline(f, line);
lines.push_back(line);
}
Since std::istream can be converted to boolean, we can rewrite it as:
while (f)
{
std::string line;
std::getline(f, line);
lines.push_back(line);
}
And since std::getline return the input stream itself, we can use it as the loop condition:
std::string line;
while (std::getline(f, line))
{
lines.push_back(line);
} // `line` still can be used after this line, outside its scope
But we have to pull the temporary variable line outside of its scope. To avoid doing so we use for instead of while loop and declare line inside for loop:
for (std::string line; std::getline(f, line); )
{
lines.push_back(line);
}
Finally, since the body of the loop contains only 1 line, we can put it inside for loop too:
for (std::string line; std::getline(f, line); lines.push_back(line));

Tokenize stringstream

I need cut string stream according custom separator. Current code cuts just acording to several standart separators. How to define and cut stringstream to string line according to custom delimiter?
std::istringstream input;
input.str("1\n2\n3\n4\n5\n6\n7\n");
int sum = 0;
for (std::string line; std::getline(input, line); )
{
cout<<line;
}
If you have one delimiter you want to use and it's a single character, you can just pass it to the 3-parameter overload of std::getline():
std::istringstream input;
input.str("1;2;3;4;5;6;7;");
int sum = 0;
for (std::string field; std::getline(input, field, ';'); )
{
std::cout<<field;
}
Live example
For other situations (multi-character delimiter, multiple delimiters), you might want to consider using Boost.Tokenizer.
Use third argument of overloaded std::getline
for (std::string line; std::getline(input, line, delimiter ); )
{
std::cout<< line <<'\n';
}

C++ getline() jumped over empty strings

I'm reading with my c++ program csv file:
abc;def;ghi
10;;10
by this code:
while(getline(in, str, '\n')){
stringstream ss;
while(getline(ss, str, ';')){
line.add(str);
}
}
Where in is input file, str is string variable and line is my collection (like vector). But getline jumped over the empty string in csv file.
Can anyone help me to reading empty string, too?
Thanks :)
You've never initialized your stream!
Try this:
#include <string> // for std::string and std::getline
#include <sstream> // for std::istringstream
for (std::string jimbob; std::getline(in, jimbob); )
{
std::istringstream marysue(jimbob); // !
for (std::string charlie; std::getline(marysue, charlie, ';'); )
{
line.add(charlie);
}
}

How do I access individual words after splitting a string?

std::string token, line("This is a sentence.");
std::istringstream iss(line);
getline(iss, token, ' ');
std::cout << token[0] << "\n";
This is printing individual letters. How do I get the complete words?
Updated to add:
I need to access them as words for doing something like this...
if (word[0] == "something")
do_this();
else
do_that();
std::string token, line("This is a sentence.");
std::istringstream iss(line);
getline(iss, token, ' ');
std::cout << token << "\n";
To store all the tokens:
std::vector<std::string> tokens;
while (getline(iss, token, ' '))
tokens.push_back(token);
or just:
std::vector<std::string> tokens;
while (iss >> token)
tokens.push_back(token);
Now tokens[i] is the ith token.
You would first have to define what makes a word.
If it's whitespace, iss >> token is the default option:
std::string line("This is a sentence.");
std::istringstream iss(line);
std::vector<std::string> words.
std::string token;
while(iss >> token)
words.push_back(token);
This should find
This
is
a
sentence.
as words.
If it's anything more complicated than whitespace, you will have to write your own lexer.
Your token variable is a String, not an array of strings. By using the [0], you're asking for the first character of token, not the String itself.
Just print token, and do the getline again.
You've defined token to be a std::string, which uses the index operator [] to return an individual character. In order to output the entire string, avoid using the index operator.