0

I am learning C++ Primer 4th edition now and playing with IO stream. When I tried to run the code in the book (Page 289):

#include <iostream>
#include <string>
using namespace std;
int main()
{
    int ival;
    // read cin and test only for EOF; loop is executed even if there are
    // other IO failures
    while (cin >> ival, !cin.eof()){
        if (cin.bad())  // input stream is corrupted; bail out
            throw runtime_error("IO stream corrupted");
        if (cin.fail()){
            cerr << "bad data, try again\n";
            cin.clear(istream::failbit);
            continue;
        }
        //ok to process ival
    }
}

I met an infinite loop after typing a string (say "as"). So what is wrong with this code?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Guojun Zhang
  • 111
  • 1
  • 9

2 Answers2

0

When you enter a string, extraction into ival fails and the failbit is set. You then dutifully attempt to clear the bit and continue. But that string is still in the buffer! So the act repeats forever.

Furthermore, you didn't actually clear the bit; you just set the stream state to failbit.

You'll need to call just std::cin.clear(), then pull out the unexpected data from the buffer before you continue.

Also, while (cin >> ival, !cin.eof()) is odd; I haven't checked the behaviour or precedence but I guess you'd just write while ((cin >> ival) && !cin.eof()).

In conclusion, if this is really the code in the book, you need a much better book because the code is wrong in several serious ways. If you're really programming C++14, you need a more up-to-date book anyway since Lippman's C++ Primer wasn't even updated for C++11 until the 5th edition.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0

Finally made it work by adding cin.ignore(INT_MAX, '\n'). This line is necessary because cin.clear() only removes the error flag while the data remains in the buffer. In order to clear the buffer cin.ignore is needed.

#include <iostream>
#include <string>
using namespace std;
int main()
{
    int ival;
    // read cin and test only for EOF; loop is executed even if there are
    // other IO failures
    while (cin >> ival, (!cin.eof())){
        if (cin.bad())  // input stream is corrupted; bail out
            throw runtime_error("IO stream corrupted");
        if (cin.fail()){
            cerr << "bad data, try again" << endl;
            cin.clear();
            cin.ignore(INT_MAX, '\n');
        }
        //ok to process ival
    }
}
Guojun Zhang
  • 111
  • 1
  • 9