istream reading after failure

2019-03-06 05:56发布

I have a small piece of code to read user data, like below:

#include<iostream>
#include<vector>
#include<algorithm>
#include<ios>
#include<iomanip>
#include<string>

using namespace std;

istream& read_dt(istream& in, vector<int>& nmbr) {
if(in) {
 nmbr.clear();

 int x;
  while(in >> x) {
   nmbr.push_back(x);
  }
  if(in.fail()) {
   string s;
   in >> s;
   in.clear();
  }
 }
 return in;
}

int main() {
 vector<int> data;
 cout << "Enter all the data: " << endl;
 read_dt(cin, data);
 cout << "Size: " << data.size() << endl;
}

When I compile and execute this above program using the following data: 1 2 3 4 r t 5 6 7

I seem to get a vector of size 4 instead of size 7. What I though, I implemented above is, that when a user gives invalid inputs as data (in this case 'r' and 't'), that data is discarded and the input is cleared (using in.clear()), and the remaining inputs are "pushed" into the vector data.

But that does not seem to be happening. What am I doing wrong? Can someone please help?

Thanks.

标签: c++ istream
1条回答
霸刀☆藐视天下
2楼-- · 2019-03-06 06:54

Once a failure occurs on a stream, the stream remains in a failed state (no reading can succeed) until you clear() the stream.

Right now, you're trying to read the bad data from the stream before you clear it, so that reading will never succeed. Furthermore, you don't provide any way to continue reading data from the stream after you've cleared out the bad data--you do the while loop, then when it exits, you clear the bad data (if any) from the stream, then return what you read.

For a case like this, you'll pretty much need to test separately from eof() on the stream, and continue reading until you reach eof()--either data is converted, or else it's ignored.

Given that you're trying to ignore bad data until the next white space, I'd use ignore instead of reading data into a string. No real point in reading data you don't care about into a string.

#include<iostream>
#include<vector>
#include<algorithm>
#include<ios>
#include<iomanip>

using namespace std;

istream& read_dt(istream& in, vector<int>& nmbr) {
    if (in) {
        nmbr.clear();

        int x;
        for(;;) { 
            in >> x;

            if (in.eof())
                break;

            if (in.fail()) {
                in.clear();
                in.ignore(100, ' ');
            }
            else
                nmbr.push_back(x);
        } 
        return in;
    }
}

int main() {
    vector<int> data;
    cout << "Enter all the data: " << endl;
    read_dt(cin, data);
    cout << "Size: " << data.size() << endl;
}
查看更多
登录 后发表回答