C++ istream 运算符>>坏数据处理 [英] C++ istream operator>> bad-data handling

查看:71
本文介绍了C++ istream 运算符>>坏数据处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

每次我在 SO 上问一个问题,结果都是一些非常愚蠢的错误(如果你不相信我,请查看我的历史),所以如果可以的话,请耐心等待.

感觉我的问题应该很受欢迎,但我找不到任何关于它的东西,而且我已经没有想法可以尝试了.

总之,事不宜迟:

<小时>

我正在尝试重载输入 operator>>.它应该一次从文件中读取一个整数跳过无效数据,例如 chars、floats 等.

当然,我正在检查 if(in >> inNum)get() 下一个令牌检查是否成功 get().
如果成功,那就没什么好说的了.
但是,如果它失败了,我假设发生了两件事之一:

  1. 它偶然发现了一个非整数
  2. 达到了eof

这是我尝试处理它的方法:

istream&运营商>>(istream& in, SortSetArray& setB) {bool eof = false;int inNum = -1;而(!eof){if(in >> inNum) {cout<<调试成功:inNum ="<<<输入数<<结束;setB.insert(inNum);}别的 {//检查 eof,使用 peek()//1. 清除所有标志,因为 peek() 返回 eof 不管什么//标志被提升,即使它不是 `eof`in.clear();cout<<调试失败:inNum ="<<输入数<<结束;//2. 然后用 peek() 检查 eofeof = (in.peek() == std::char_traits::eof());}}返回;}

文件包含[1 2 3 4 a 5 6 7],程序自然进入无限循环.好吧,很容易猜到,peek() 不消耗字符 'a',也许 in >>inNum 也未能以某种方式消耗它.没什么大不了的,我会尝试一些有用的东西.

这几乎就是我过去 2 小时去过的地方.我试过 istream::ignore()、istream::get()、ios::rdstate 来检查 eof、doublestring 而不是 char 在文件中,以防 char 被数字读取.

没有任何效果,我很绝望.

奇怪的是,上述方法适用于以前的程序,在该程序中,我必须读取以下格式的三元组数据条目:string int int
唯一的区别是我为那个使用了 ifstream 对象,而为这个使用了 istream 对象.

额外问题:出现打嗝时 inNum 的值为 0.我猜这是 istream::operator>> 所做的事情?

解决方案

实现说明

<块引用>

  1. 尝试读取 int
  2. 如果成功;

    1. 将读取值插入到setB
    2. 下一次迭代

  3. 其他;

    1. 清除错误标志
    2. 检查以确保我们还没有到达文件末尾
    3. 还有更多数据?下一次迭代.

以上是你的函数的逻辑描述,但还缺少一些东西......

如果我们尝试读取值但失败,std::istream 会通过设置适当的错误标志来处理这些情况,但不会丢弃任何数据.

您的实现的问题在于,在尝试读取无效数据时,您只会尝试再次读取相同的无效数据......一遍又一遍,inf.

<小时>

解决方案

清除错误标志后,您可以使用std::istream::ignore 丢弃流中的任何数据.

该函数的 1st 参数是要忽略的潜在 char 的最大数量,2nd 是如果你点击这个 char,不要再忽略*.

让我们忽略最大字符数,或者直到我们点击' '(空格):

#include //std::numeric_limitsin.ignore (std::numeric_limits::max(), ' ');

Every time I ask a question here on SO, it turns out to be some very dumb mistake (check my history if you don't believe me), so bear with me if you can here.

It feels like my question should be very popular, but I couldn't find anything about it and I've run out of ideas to try.

Anyway, without further ado:


I'm trying to overload the input operator>>. It's supposed to read one integer at a time from a file, skipping invalid data such as chars, floats, etc.

Naturally, I'm checking if(in >> inNum) to both get() the next token and check for successful get().
If successful, not much to say there.
If it fails, however, I assume that one of two things happened:

  1. It stumbled upon a non-integer
  2. It reached the eof

Here's how I tried to deal with it:

istream& operator>> (istream& in, SortSetArray& setB) {
    bool eof = false;
    int inNum = -1;
    while(!eof) {
        if(in >> inNum) {
            cout << "DEBUG SUCCESS: inNum = " << inNum << endl;
            setB.insert(inNum);
        }
        else {
            // check eof, using peek()
            // 1. clear all flags since peek() returns eof regardless of what
            //    flag is raised, even if it's not `eof`
            in.clear();
            cout << "DEBUG FAIL: inNum = " << inNum << endl;
            // 2. then check eof with peek()
            eof = (in.peek() == std::char_traits<char>::eof());
        }
    }
    return in;
}

The file contains [1 2 3 4 a 5 6 7], and the program naturally goes into infinite loop. Okay, easy guess, peek() doesn't consume the char 'a', and maybe in >> inNum also failed to consume it somehow. No biggie, I'll just try something that does.

And that's pretty much where I've been for the last 2 hours. I tried istream::ignore(), istream::get(), ios::rdstate to check eof, double and string instead of char in the file, just in case char is read numerically.

Nothing works and I'm desperate.

Weirdly enough, the approach above worked for a previous program where I had to read a triplet of data entries on a line of the format: string int int
The only difference is I used an ifstream object for that one, and an istream object for this one.

Bonus Question: inNum has the value of 0 when the hiccup occurs. I'm guessing it's something that istream::operator>> does?

解决方案

Implementation description

  1. try to read an int
  2. if successful;

    1. insert the read value to setB
    2. next iteration

  3. else;

    1. clear error flags
    2. check so that we haven't reached the end of the file
    3. still more data? next iteration.

The above is the logic description of your function, but there's something missing...

In case we try to read a value, but fail, std::istream's handle these cases by setting the approriate error flags, but it will not discard any data.

The problem with your implementation is that upon trying to read invalid data, you will just try to read the same invalid data again.. over, and over, and over, inf.


Solution

After clearing the error flags you can use std::istream::ignore to discard any data from the stream.

The function's 1st argument is the max number of potential chars to ignore, and the 2nd is the "if you hit this char, don't ignore any more*.

Let's ignore the maximum amount of characters, or until we hit ' ' (space):

#include <limits> // std::numeric_limits

in.ignore (std::numeric_limits<std::streamsize>::max(), ' ');

这篇关于C++ istream 运算符&gt;&gt;坏数据处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆