I'm trying to split a string using stringstream :
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int main(){
ifstream fp;
string name;
fp.open("in.txt");
while (fp){
string line;
getline(fp, line);
cout << line << endl;
istringstream line_stream(line);
while (line_stream){
line_stream >> name;
cout << name << " ";
}
}
return 0;
}
Here's in.txt :
cat bat rat sat
Here's the output I'm getting :
cat bat rat sat
cat bat rat sat sat
The line retrieved from getline()
function is right, but in the process of splitting I'm getting the last word twice. I'm not sure why is this happening.
You are using the results of getline
without checking whether
it succeeded. This is the first error (and probably results in
an extra empty line with the code you show). Similarly, you use
the results of line_stream >> name
without checking whether it
succeeded; in this case (because name
is not newly constructed
each time through), you may end up with the previously read
value (but in both cases, the contents of the string are
unspecified).
You must never use the results of input without first testing whether it succeeded. The most common way of doing this (but certainly not the only way) is to do the input in the condition of the loop:
while ( std::getline( fp, line ) ) ...
and
while ( line_stream >> name ) ...
If you still want to limit the scope of the variable to the loop, you'd have to write:
while ( fp ) {
std::string line;
if ( std::getline( fp, line ) ) {
// rest of loop
}
}
If you have (understandably) something against modifying global state in a condition, you'd have to write:
std::getline( fp, line );
while ( fp ) {
// ...
std::getline( fp, line );
}
While I think that there are strong arguments in favor of this,
the while ( std::getline( fp, line ) )
idiom is ubiquitous, to
the point where anything else will cause the reader to wonder
why.
Instead of saying:
while (fp){
string line;
getline(fp, line);
...
You should say:
string line;
while(getline(fp, line)) { ...
This is because when fp gets into eof state, getline fails (and sets fp to eof state). You do not check the result of the getline so for the last step you use the previously read value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With