parsing an sstream

WhitAngl Source

I am parsing a file which contains both strings and numerical values. I'd like to process the file field by field, each delimited by a space or an end-of-line character. The ifstream::getline() operation only allows a single delimiting character. What I currently do is thus a getline with the character ' ' as a delimiter, and then manually go back to the previous position in the stream if a '\n' has been encountered :

 ifstream ifs ( filename , ifstream::in );
 streampos pos;
 while (ifs.good())
 {  
  char curField[255];  

  pos = ifs.tellg();
  ifs.getline(curField, 255, ' '); 
  string s(curField);
  if (s.find("\n")!=string::npos) 
  {   
   ifs.seekg(pos); 
   ifs.getline(curField, 255, '\n'); 
   s = string(curField);
  }

 // process the field contained in the string s...
 }

However, the "seekg" seems to position the stream one character too late (I thus miss the first character of each field before each line break). I know there are other ways to code such a parser, by scanning line by line etc.., but I'd really like to understand why this particular piece of code fails...

Thank you very much!

c++parsingsstream

Answers

answered 8 years ago David R Tribble #1

There may be a look-ahead/push-back character in the input stream. IIRC, the seek/tell functions are not aware of this.

answered 8 years ago JoshD #2

As Loadmaster said, there may be unaccounted for characters, or this could just be an off-by-one error.

But this just has to be said... you can replace this:

 ifstream ifs ( filename , ifstream::in );
 streampos pos;
 while (ifs.good())
 {  
  char curField[255];  

  pos = ifs.tellg();
  ifs.getline(curField, 255, ' '); 
  string s(curField);
  if (s.find("\n")!=string::npos) 
  {   
   ifs.seekg(pos); 
   ifs.getline(curField, 255, '\n'); 
   s = string(curField);
  }

 // process the field contained in the string s...
 }

With this:

 ifstream ifs ( filename , ifstream::in );
 streampos pos;
 string s;
 while (ifs.good())
 {  
   ifs >> s;
   // process the field contained in the string s...
 }

To get the behavior you want.

comments powered by Disqus