【问题标题】:What does cin do when there is an error出现错误时cin怎么办
【发布时间】:2012-09-06 16:38:53
【问题描述】:
#include<iostream>;

int main()
{
    int a = 1;
    int b = 2;
    std::cin >> a >> b;
    std::cout << a << "+" << b << "=" << a+b << std::endl;
    return 0;
}

当我输入3 4 时,输出将是3+4=7,嗯,很奇怪; 但是当我输入a b时,输出是0+0=0(为什么是0和0?); 最迷惑的,a 4,会是0+0=0(为什么不是'0+4=4'??????); 然后我再写一个prog。

#include<iostream>;

int main()
{
    int a = 1;
    int b = 2;
    std::cin >> a;
    std::cin.clear();
    std::cin >> b;
    std::cout << a << "+" << b << "=" << a+b << std::endl;
    return 0;
}

当我输入a 4时,为什么还是0+0=0?不应该是0+4=4吗?

感谢所有的热心人!!

我写prog3,测试不写int a=1;int b=2会发生什么;

2

#include <iostream>
using namespace std;
int main()
{  
    int a,b;
    cin >> a  ;
    cin >> b;
    cout<< a << "+"<< b <<"="<< a+b << endl;
    return 0;
}

当a b再次时,它输出0+-1218170892=-1218170892(为什么不是0+0=0??)

【问题讨论】:

  • 输入应该是一个整数,而不是一个字符。输入“a”、“3.141”或“whatever”根本无效。如果您的输入是“a”,则程序不知道您已将“a”用作变量并且您想使用默认值。
  • 很明显是C++11,否则就是1和2,而不是0。
  • 回答您的编辑:您尚未从输入中删除 a。您需要cin.clear(); cin.ignore(1);,以便第二次提取成功。
  • @Drise 你能帮我谈谈 prog3 吗?
  • a 和 b 未初始化。它们具有来自分配给它们的内存的垃圾值。这是毫无意义的信息。始终使用 int a = 0;以确保您将获得可用数据。

标签: c++ error-handling cin


【解决方案1】:

像所有istreams 一样,std::cin 有错误位。发生错误时设置这些位。例如,您可以使用good()、bad()、eof() 等函数查找错误位的值。如果您读取错误输入(fail() 返回true),请使用clear() 清除旗帜。您可能还需要ignore(1); 来删除违规字符。

有关详细信息,请参阅State functions 部分。 http://en.cppreference.com/w/cpp/io/basic_ios

【讨论】:

  • 谢谢。但我仍然想知道为什么 a 和 b 的值都变成 0
  • 如果你读到错误的输入,bad() 仍然会返回 false; fail() 将返回 true。而且您引用的页面被误导性地简化了,并且对于good() 来说是错误的(即使没有发生错误也可能返回false)。扔掉它,找到更好的东西。
  • 您似乎在使用 C++11:如果提取失败,则将零写入 value 并设置 failbit。 (C++11 起).
  • 好的,现在我知道了;再次感谢:)
  • @user1668903 如果两者都为0,则为执行错误。 C++11要求第一个变为0,第二个不变。该标准的早期版本要求两者都保持不变。
【解决方案2】:

根据 C++11,在出现错误时将值设置为零:如果提取失败,则将零写入值并设置故障位。

在 'a 4' 示例中,两个值都是 0,因为缓冲区尚未被刷新/清除,因此第二次 cin 读取仍在读取错误,并且还接收到 0 值。

【讨论】:

    【解决方案3】:

    std::cin 是一个 istream 实例,因此它在读取无效内容时保持其错误状态。

    为了“治愈”它,你必须同时清除它的标志

    std::cin.clear();
    

    并刷新其缓冲区。

    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    

    更令人惊讶的是,当您输入无效字符时,它不会返回 1 + 2 = 3,因为我希望失败的 cin 流对其尝试更新的内容没有副作用。

    【讨论】:

    • OP 正在使用 C++11:如果提取失败,则将零写入值并设置故障位。 (C++11 起)
    • 这只是整数的情况,还是用户类型的一般规则,如果流式输入失败,对象应该恢复到其默认状态?我一直认为流入一个对象是有缺陷的逻辑。工厂使用从流中读取的数据创建对象,对象不会被流式传输到..
    • "流入对象是有缺陷的逻辑。工厂使用从流中读取的数据创建对象,对象不会流入" - 使用operator&lt;&lt; 流入必然会流入预先存在的对象(给定 by-reference 参数),尽管创建新对象的工厂通常是可取的,但有时它不会(例如,当您想要对象已经拥有的缓冲区和其他资源时)用于下一个值)以及“工厂”如何在堆栈上创建对象(非常需要,除非对象是运行时多态的,需要延长生命周期等)?
    • 我倾向于使用非侵入性的类,并且序列化数据的方法不止一种。当然,在图书馆获得了更多经验后,我现在知道有一个方面这样的东西,但它很复杂。无论如何,近年来我发现我更倾向于创建包含所有公共数据成员的简单“结构”对象,然后让一个“类”通过包含它的私有实例来包装该结构。然后,您可以“流式传输”到结构中而无需交任何朋友,并保持实例成员仍然无法访问的封装。
    猜你喜欢
    • 1970-01-01
    • 2012-07-13
    • 1970-01-01
    • 2022-12-10
    • 2021-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-13
    相关资源
    最近更新 更多