istream reading after failure

浪子不回头ぞ 提交于 2019-12-31 07:03:47

问题


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.


回答1:


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;
}


来源:https://stackoverflow.com/questions/37151597/istream-reading-after-failure

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!