StringStream failed

I am reading a text file with this format:

grrr, some text, 45.4321,54.22134

I only have my double score stored in a string variable.

Why does this only give me the first digit of the string?

If I start with one while loop and a text file of this new format:

21,34564

it works as it should.

The fact is that sLine has the same meaning as when it was first started. What is different are the three nested loops that are most likely causing the problem.

Here is the code that gets me what I want:

 #include <iostream> #include <fstream> #include <string> #include <vector> #include <iomanip> #include <cstdlib> #include <sstream> using namespace std; int main() { string usrFileStr, fileStr = "test.txt", // declaring an obj string literal sBuffer, sLine, str; double dValue ; int lineCount = 1; int nStart; istringstream issm; fstream inFile; // declaring a fstream obj // cout is the name of the output stream cout << "Enter a file: "; cin >> usrFileStr; inFile.open( usrFileStr.c_str(), ios::in ); // at this point the file is open and we may parse the contents of it while ( getline ( inFile, sBuffer ) && inFile.eof() ) { cout << "Original String From File: " << sBuffer << endl; cout << "Modified Str from File: " << fixed << setprecision(2) << dValue << endl; } fgetc( stdin ); return 0; } 

So, it works as it should. But I can't get it to work inside a for loop or when I have several feilds in a text file ...

 With this code, why is it taken off the decimal? #include <iostream> #include <fstream> #include <string> #include <vector> #include <iomanip> #include <cstdlib> #include <sstream> #include <errno.h> using namespace std; int main() { string usrFileStr, myFileStr = "myFile.txt", // declaring an obj string literal sBuffer, sLine = ""; istringstream inStream; int lineCount = 1; int nStart; double dValue = 0, dValue2 = 0; float fvalue; fstream inFile; // declaring a fstream obj // cout is the name of the output stream cout << "Enter a file: "; cin >> usrFileStr; inFile.open( usrFileStr.c_str(), ios::in ); // at this point the file is open and we may parse the contents of it if ( !inFile ) { cout << "Not Correct " << endl; } while ( getline ( inFile, sBuffer ) ) { nStart = -1 ; for ( int x = nStart + 1; x < sBuffer.length(); x++ ) { if ( sBuffer[ x ] == ',' ) { nStart = x; break; } cout << sBuffer[ x ]; } for ( int x = nStart + 1; x < sBuffer.length(); x++ ) { if ( sBuffer[ x ] == ',' ) { nStart = x; break; } cout << sBuffer[ x ]; } for ( int x = nStart + 1; x < sBuffer.length(); x++ ) { if ( sBuffer[ x ] == ',' ) { nStart = x; break; } sLine = sBuffer[ x ]; inStream.clear(); inStream.str( sLine ); if ( inStream >> dValue ) cout << setprecision(1) << dValue; } for ( int x = nStart + 1; x < sBuffer.length(); x++ ) { if ( sBuffer[ x ] == ',' ) { nStart = x; break; } sLine = sBuffer[ x ]; inStream.clear(); inStream.str( sLine ); if ( inStream >> dValue2 ) cout << setprecision(1) << dValue2; } cout << ") \n"; lineCount++; } cout << "There are a Total of: " << lineCount -1 << " line(s) in the file." << endl; inFile.clear(); // clear the file of any errors inFile.close(); // at this point we are done with the file and may close it fgetc( stdin ); return 0; } 

I don't have any other characters for the loop in the first code, because I'm just reading a small slight double value.

In my second code, I have many characters to get to what I want. But regardless, he is still isolated from other characters, and he is still in his own version. im to sick to understand what the problem is: / although I think this is for loops.

I also tried atof, but I get "0" where the decimal should be. and strtod is difficult because I need me not to read the data in const char * cPtr

+4
source share
3 answers

Using instream - > dvalue is of course the right way. But sometimes some right is not always easier or necessarily better.

We could do something like this:

 int main() { string s = "grrr,some text,45.4321,54.22134"; double a,b; ASSERT_IS( 2, sscanf( s.c_str(), "%*[^,],%*[^,],%lf,%lf", & a, & b ) ); cout << setprecision(8); SHOW(a); SHOW(b); } 

Or maybe something like this, although less effective, might be easier to understand ...

 int main() { string s = "grrr,some text,45.4321,54.22134"; vector<string> v; StringSplit( & v, s, "," ); cout << setprecision(8); SHOW(v); SHOW(atof( v[2].c_str())); SHOW(strtod(v[3].c_str(), (char**)NULL)); } 

Assuming that:

 #define SHOW(X) cout << # X " = " << (X) f << endl /* A quick & easy way to print out vectors... */ template<class TYPE> inline ostream & operator<< ( ostream & theOstream, const vector<TYPE> & theVector ) { theOstream << "Vector [" << theVector.size() << "] {" << (void*)(& theVector) << "}:" << endl; for ( size_t i = 0; i < theVector.size(); i ++ ) theOstream << " [" << i << "]: \"" << theVector[i] << "\"" << endl; return theOstream; } inline void StringSplit( vector<string> * theStringVector, /* Altered/returned value */ const string & theString, const string & theDelimiter ) { UASSERT( theStringVector, !=, (vector<string> *) NULL ); UASSERT( theDelimiter.size(), >, 0 ); size_t start = 0, end = 0; while ( end != string::npos ) { end = theString.find( theDelimiter, start ); // If at end, use length=maxLength. Else use length=end-start. theStringVector -> push_back( theString.substr( start, (end == string::npos) ? string::npos : end - start ) ); // If at end, use start=maxSize. Else use start=end+delimiter. start = ( ( end > (string::npos - theDelimiter.size()) ) ? string::npos : end + theDelimiter.size() ); } } 
+1
source

Your code is a little hard to read. You probably want to think about encapsulation and break it down into functions.

In addition, I would try to avoid reading in single characters and use various functions and methods to read data in fields - you can read a floating-point integer or an integer using stream extractors >> .

Finally, using a debugger is a useful skill to learn. You can go through the code and check the values โ€‹โ€‹of the variables as you go.

However, your problem seems to be here:

  if ( sBuffer[ x ] == ',' ) { nStart = x; break; } **** sLine = sBuffer[ x ]; inStream.clear(); inStream.str( sLine ); if ( inStream >> dValue2 ) cout << setprecision(1) << dValue2; 

In a line labeled with a ****, you place exactly one character in a variable called sLine. By doing this, you convert this single character into a double-precision variable dValue2, and then output it. Obviously, why this character is converted to the first digit of the desired number.

+2
source

Two points:

  • You might want to use sBuffer.find(',')
  • You set sLine last character before the ",", does that mean it is? Thus, you correctly parse single-digit numbers.
0
source

All Articles