为什么在 cin>>(int) 失败后,cin 停止工作?

3
当调用 cin>>(int) 和 cin>>(string) 时,如果第一个输入不是整数,则似乎即使第二个输入是正确的字符串,cin>>(string) 仍然无法检索到第二个输入。
源代码很简单:
cout<<"Please enter count and name"<<endl;;
int count;
cin>>count;     // >> reads an integer into count
string name;
cin>>name;      // >> reades a string into name

cout<<"count: "<<count<<endl;
cout<<"name: "<<name<<endl;

测试用例如下:

案例1:输入无法转换为整数的字符和字符

请输入数量和名称

ad st

数量:0

名称:

案例2:输入数字和字符

请输入数量和名称

30 ad

数量:30

名称:ad

案例3:输入数字和可视作字符串的数字

请输入数量和名称

20 33

数量:20

名称:33


2
std::cin有一个状态,您可以通过std::cin.good()进行检查。输入可能会失败,而且通常会失败,因此您需要采取一些措施来解决它。 - 463035818_is_not_a_number
第一次使用cin的状态/结果如何影响第二次使用cin?或者这是否意味着在每次使用cin之前需要检查或清除cin的状态?我从未在代码中看到过对cin状态的预处理。谢谢。 - lst
@lst 1) "第一次使用cin的状态/结果如何影响第二次使用cin?" 如果cin处于无效状态,则任何进一步操作都是无意义的。2) "还是说在每次使用cin之前,需要检查或清除cin的状态?" 是的,一个人需要养成检查操作是否成功的习惯,而不是假设它们已经成功的习惯。3) "我从未在代码中看到过对cin状态的预处理" if (cin>>count) {/* 操作成功 */} - Algirdas Preidžius
2个回答

6

流(Stream)具有一个内部错误标志,一旦设置,直到您明确清除它为止,该标志将保持设置状态。当读取失败时(例如,因为输入无法转换为所需的类型),错误标志将被设置,并且只要您不清除此标志,任何后续读取操作甚至都不会尝试:

int main() {

    stringstream ss("john 123");

    int testInt;
    string testString;

    ss >> testInt;
    if (ss) {
        cout << "good!" << testInt << endl;
    } else {
        cout << "bad!" << endl;
    }

    ss >> testString;
    if (ss) {
        cout << "good!" << testString << endl;
    } else {
        cout << "bad!" << endl;
    }

    ss.clear();
    ss >> testString;
    if (ss) {
        cout << "good:" << testString << endl;
    } else {
        cout << "bad!";
    }
}

输出:

bad!
bad!
good:john

只需找到另一个与此问题类似的线程:https://dev59.com/o-_0s4cB2Jgan1znJWne#39282970 - lst
它提到了cin.clear()和cin.ignore()。这是否意味着在某些情况下,例如如果流中有多个错误输入,我们必须调用cin.ignore(streamsize, delim)来清除cin缓冲区? - lst
我已经尝试了cin.clear()和cin.ignore(),还找到了另一个链接讨论如何处理。 - lst
我已经尝试了cin.clear()和cin.ignore(),并找到另一个链接,讨论如何处理最大数量的字符以提取并提供分隔符。[链接] https://dev59.com/RHVC5IYBdhLWcg3wjx1d 以下代码似乎有效:int id;cout << "请输入您的ID整数\n";if (!(cin >> id)) { cin.clear(); cin.ignore(numeric_limits<streamsize>::max(), '\n'); } - lst

0

您可以使用

cin.good() 方法

来检查输入语句是否成功。如果输入语句失败,则返回 false,否则返回 true。以下是一个小例子:

#include <iostream>
#include <cstdlib>

using namespace std;

int main()
{
  int x; 

  // prompt the user for input 
  cout << "Enter an integer: " << "\n"; 
  cout << "cin.good() value: " << cin.good() << "\n";
  // get input 
  cin >> x; 
  cout << "cin.good() value: " << cin.good() << "\n";
  // check and see if the input statement succeeded 
  if (!cin) { 
    cout << "That was not an integer." << endl; 
    return EXIT_FAILURE; 
  } 

  // print the value we got from the user 
  cout << x << endl; 
  return EXIT_SUCCESS; 
}

输出:

Enter an integer: 
cin.good() value: 1
asd
cin.good() value: 0
That was not an integer.

1
如果 (cin.good() == false) 的写法有些冗长,可以用 if (!cin) 代替。测试流状态的通常惯用法是使用布尔转换:if (cin) 检查它是否良好,if (!cin) 检查它是否不良。 - Pete Becker
1
顺便提一下,-1 不一定是从 main 函数中返回的有意义的值。你可以返回 EXIT_SUCCESS 或者 0 来表示成功,或者返回 EXIT_FAILURE 来表示失败。这些宏定义在 <cstdlib> 中。任何其他值的含义都是由实现定义的。 - Pete Becker
@PeteBecker 感谢您的解释。由于cin状态可能是好的或坏的,是否在使用cin之前和之后始终检查cin状态会更安全?似乎人们通常只是直接调用cin>>而没有任何检查。这是因为它只是玩具程序吗?在真正的工业级软件/系统中,输入流是否总是被检查并在出现故障时重置为好的状态? - lst
@lst - 这取决于你的程序要做什么。坏状态是黏性的,因此如果你正在进行一堆输入,可以在最后检查它以查看是否有失败的情况。另一方面,重复输入通常是在循环中完成的:while (std::cin >> i) { /* 对i进行操作 */ } - Pete Becker
2
@TiborFekete 我猜为了解决cin的错误状态以及刷新错误读入的数据,代码cin.clear();和cin.ignore(numeric_limits<streamsize>::max(), '\n');似乎是有效的。我参考了这个[链接] https://dev59.com/RHVC5IYBdhLWcg3wjx1d - lst
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接