In chapter 8, an example is provided, which is very simple, that is, to read the user input and assign it to an int. Here, a judgment is provided, that is, if the user input is not an int, cin will become invalid, and there will be a condition state, so we can catch this state and clear, and then continue to read.
However, the example in the book has an error. The original program is as follows:
-
Code: select all
-
#include <iostream>
#include <stdexcept>
using namespace std;int main(int argc, char **argv)
{
int ival;
// cout << "Begin state is: " << cin.rdstate() << endl;
while (cin >> ival, !cin.eof()) {
// cout << "Current Enter loop state is: " << cin.rdstate() << endl;
if (cin.bad()) {
// no catch so the terminate will be called
throw runtime_error("IO Stream corrupted");
}
if (cin.fail()) {
cerr << "bad data, try again: ";
cin.clear(istream::failbit);
// cout << "Current state is: " << cin.rdstate() << endl;
continue;
}
// ok, print out this integer
cout << "Input correct, your number is: " << ival << endl;
}
}
There are two errors:
(1) in Linux and G ++, Cin. clear (istream: failbit) does not clear the Fail state of CIN, although it should be possible from the clear function documentation. No way. I changed it to CIN. Clear () and then OK.
(2) The sentence cin. Ignore is missing or the Code with the same effect is missing. This is because the Fail status of CIN has been eliminated, but the user input that is read this time is incorrect. For example, if the user inputs a string, it still exists in the buffer of CIN. In this way, the next cycle of CIN> ival still fails, so an endless loop is formed. Because there is always the error data entered by the user for the first time in the buffer of CIN, The while loop continues.
Then I added the following sentence: cin. Ignore (100000, '\ n'); then OK. You can refer to the ignore document. The code indicates all the characters in the ignore buffer from the beginning to the first \ n. The first parameter is intentionally large, this is because the first parameter of ignore represents the number of ignore characters. If it is too small, the cleanup in the buffer is not clean.
The modified code is as follows:
-
Code: select all
-
#include <iostream>
#include <stdexcept>
using namespace std;int main(int argc, char **argv)
{
int ival;
// cout << "Begin state is: " << cin.rdstate() << endl;
while (cin >> ival, !cin.eof()) {
// cout << "Current Enter loop state is: " << cin.rdstate() << endl;
if (cin.bad()) {
// no catch so the terminate will be called
throw runtime_error("IO Stream corrupted");
}
if (cin.fail()) {
cerr << "bad data, try again: ";
cin.clear();
// Here cin's error condition state cannot be removed unless
// we use cin.clear() directly
// cin.clear(istream::failbit);
// ignore current read wrong characters otherwise the loop
// will go infinitely
cin.ignore(11111111, '\n');
// cout << "Current state is: " << cin.rdstate() << endl;
continue;
}
// ok, print out this integer
cout << "Input correct, your number is: " << ival << endl;
}
}
By the way, I attached another exercise code in this chapter to print the text and use fstream:
-
Code: select all
-
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;int main()
{
ifstream input;
vector<string> filelist;
filelist.push_back("read.cc");
filelist.push_back("fread.cc");
filelist.push_back("dummy.cc");
vector<string>::const_iterator it = filelist.begin();
string s;
// loop begin
while (it != filelist.end()) {
input.open(it->c_str());
if (!input) {
cout << "Open file " << *it << " failed, quit..." << endl;
break;
}
cout << "Printing file " << *it << endl;
while (getline(input, s))
cout << s << endl;
input.close();
input.clear();
++it;
}
}