1

I have recently started tinkering with C++, and I'm trying to figure out how to read from a file. I have a file that begins with:

   1 !NTITLE
solvent mask generated by cctbx
      64       0      64      72       0      72      96       0      96
 3.91500E+01 4.46750E+01 6.10130E+01 7.26100E+01 7.17200E+01 7.53500E+01

(theres a blank line above the first line)

I am trying to read this word by word and printing the word mask as follows:

string myString;
ifstream xplorFile("mask.xplor");

if(!xplorFile){
    cout << "error opening file" <<endl;
    return -1;
}

while (!xplorFile.eof()) {
    getline(xplorFile, myString, ' ');
    if (myString == "mask") {
        cout << myString << endl;
    }
}

which outputs mask, as expected. However, if I try to print solvent instead by changing the if statement to

if (myString == "solvent") {
        cout << myString << endl;
}

I get no output. Similarly, if I try !NTITLE I get no output. Why isn't the comparison not working?

sodiumnitrate
  • 2,899
  • 6
  • 30
  • 49
  • 2
    [`while (!xplorFile.eof()) {` almost never works](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). TL;DR version it tests for end of file before reading for end of file.. This leaves `getline(xplorFile, myString, ' ');` exposed to failure by hitting the end of the file and failing. Instead use `while (getline(xplorFile, myString, ' ')){ or as Gread suggests below, use `while(xplorFile >> mystring){` since you don't care about the presence of the linefeed. – user4581301 Oct 29 '15 at 02:12

2 Answers2

1

change

while (!xplorFile.eof()) {
    getline(xplorFile, myString, ' ');

to

while (xplorFile >> mystring) {

My guess is that since solvent is at the beginning of the line not preceded by a space, then the getline function with delimiter ' ' produces !NTITLE\nsolvent. Using the >> operator will resolve that because it tokenizes on all whitespace.

GreatAndPowerfulOz
  • 1,767
  • 13
  • 19
  • 1
    Better reword that closer. It's not skipping over solvent. '\n' is not ' ', so the token read will be !NTITLE\nsolvent. Also worth adding to the answer that `xplorFile >> mystring;` will work because it tokenizes on all whitespace, including '\n' – user4581301 Oct 29 '15 at 02:20
  • Is it possible to know the line number of the word that I'm reading? Specifically, I want to skip the line that begins with `solvent` and read in the numbers in the following line to an integer array. – sodiumnitrate Oct 29 '15 at 13:22
  • @sodiumnitrate, you can use `xploreFile.peek() == '\n'` to detect a newline. `peek()` lets you look at the next character without extracting it from the stream. – GreatAndPowerfulOz Oct 29 '15 at 14:13
1

easy way to get file contents word by word is like this

while (xplorFile >> myString) {
    if (myString == "mask") {
        cout << myString << endl;
    }
}
MORTAL
  • 383
  • 2
  • 10
  • 1
    True, but it would be a good thing to explain why this is different and better than OP's version so that some learning is done. – user4581301 Oct 29 '15 at 02:21