简体   繁体   中英

I do not understand std::string from std::stream

Even though I am afraid to appear really stupid, I would like to ask why this program:

#include <iostream>
#include <fstream>

int main(int argc, char * argv[]) {

  std::ifstream fitData("./fitData.txt");

  int line=1;
  while (true) {
    std::string compType;
    bool isRS;
    int dRecMode;
    double mass;
    fitData >> compType >> isRS >> dRecMode >> mass;
    if ( fitData.eof() ) break;
    std::cout << "at line: " << line << ":" << compType << " " << isRS << " " << dRecMode << " " << mass << std::endl;

    line++;

    if ( line > 20 ) break;
  }

  std::cout << line << std::endl;
}

when run on this file:

prompt> cat fitData.txt 
TT: 1 7 2.26455
TT: 1 7 2.45204
TT: 1 1 2.05438
TT: 1 -5 2.36097
TT: 1 -5 2.34911
TT: 1 7 2.43344
TT: 1 3 2.5
TT: 1 1 2.34866
TT: 1 2 2.24831
TT: 1 -3 2.31099
LC: 0 99 2.27828
LC: 1 99 2.29757
LC: 2 99 2.27512
LC: 3 99 2.31149
LC: 4 99 2.31205
LC: 5 99 2.31091

goes into an endless loop:

at line: 1:TT: 1 7 2.26455
at line: 2:TT: 1 7 2.45204
at line: 3:TT: 1 1 2.05438
at line: 4:TT: 1 -5 2.36097
at line: 5:TT: 1 -5 2.34911
at line: 6:TT: 1 7 2.43344
at line: 7:TT: 1 3 2.5
at line: 8:TT: 1 1 2.34866
at line: 9:TT: 1 2 2.24831
at line: 10:TT: 1 -3 2.31099
at line: 11:LC: 0 99 2.27828
at line: 12:LC: 1 99 2.29757
at line: 13:LC: 1 99 2.29757
at line: 14: 1 99 2.29757
at line: 15: 1 99 2.29757
at line: 16: 1 99 2.29757
at line: 17: 1 99 2.29757
at line: 18: 1 99 2.29757
at line: 19: 1 99 2.29757
at line: 20: 1 99 2.29757
21

It happens on every machine I have been able to reach: WSL2 on MSWin10(64bit), cygwin on Win7(32bit) and finally pure-Linux (Xubuntu-64bit). At the 2nd run thru, something goes wrong, and the std::string looks empty.

Thank you really a lot for insight: even with exhortations to do something else than computing! :-)

It appears that the reading of line 13 (or LC: 2 99 2.27512 ) fails on the second value where you are trying to read 2 into a bool .

You can get ifstream to throw an exception in such cases by setting an exceptions mask, and then catch the exception after trying to read.

#include <iostream>
#include <fstream>

int main(int argc, char * argv[]) {
  std::ifstream fitData("./fitData.txt");
  fitData.exceptions(std::ifstream::failbit | std::ifstream::badbit);
  int line=0;
  if (fitData.is_open()) {
    while (line < 20) {
      std::string compType;
      bool isRS;
      int dRecMode;
      double mass;
      try {
        fitData >> compType >> isRS >> dRecMode >> mass;
      } catch (std::system_error& e) {
        std::cout << e.what() << std::endl;
        break;
      }
      line++;
      std::cout << "at line: " << line << ":" << compType << " " << isRS << " " << dRecMode << " " << mass << std::endl;
    }
  }

  std::cout << line << std::endl;
}

Output:

at line: 1:TT: 1 7 2.26455
at line: 2:TT: 1 7 2.45204
at line: 3:TT: 1 1 2.05438
at line: 4:TT: 1 -5 2.36097
at line: 5:TT: 1 -5 2.34911
at line: 6:TT: 1 7 2.43344
at line: 7:TT: 1 3 2.5
at line: 8:TT: 1 1 2.34866
at line: 9:TT: 1 2 2.24831
at line: 10:TT: 1 -3 2.31099
at line: 11:LC: 0 99 2.27828
at line: 12:LC: 1 99 2.29757
basic_ios::clear: iostream error
12

Try it online!

Alternatively, you can just check if the stream is still good() after reading.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM