views:

318

answers:

3

I've been attempting to use the C++ stringstream class to do some relatively simple string manipulations, but I'm having a problem with the get() method. For some reason whenever I extract the output character by character it appends a second copy of the final letter.

#include <iostream>
#include <sstream>
#include <string>
using namespace std;

int main() {
   stringstream ss("hello");
   char c;

   while(!ss.eof()) {
      ss.get(c);
      cout << "char: " << c << endl;
   }
   return 0;
}

The output from the program is:

char: h
char: e
char: l
char: l
char: o
char: o

Any help you can give me on this would be appreciated.

+1  A: 

its because of the order of the loop. Your reading the \0 and EOF.

reorder your code like this

int main() {
   stringstream ss("hello");
   char c;

   ss.get(c);
   while(!ss.eof()) {
      cout << "char: " << c << endl;
      ss.get(c);
   }
   return 0;
}
Andrew Keith
where did you see \n?
leiz
oooops .. typo .. i was thinking \0 and typed \n..
Andrew Keith
+7  A: 

At the end of the stream ss.eof() doesn't know yet that the end of the stream will be reached soon, but the following extraction of a character fails. Since the extraction failed because the end of the stream was reached, c is not changed. Your program doesn't recognize that ss.get(c) failed and prints that old value of c again.

A better way to check if there still is a character that can be read from the stream would be a loop like this:

while (ss.get(c)) {
   cout << "char: " << c << endl;
}
sth
and here you rely on the convenience of standard streams having operator bool() defined.
wilhelmtell
Thank you so much for your quick response and detailed explanation.
Chris
+1  A: 

The EOF flag is only set if you attempt to read PAST the end of the file. The following code fixes the problem by testing for EOF after the get() instead of before it:

#include <iostream>
#include <sstream>
#include <string>
using namespace std;

int main() {
   stringstream ss("hello");
   char c;

   while(1) {
      ss.get(c);
      if(ss.eof())
          break;

      cout << "char: " << c << endl;
   }
   return 0;
}
Adam Pierce