C++流中的无效输入

4
考虑以下代码,它接受一个整数输入,然后打印cin流状态:
#include <iostream>  
using namespace std;

int main()
{
    int number;
    cout<<"Enter a number \n";
    cin>>number;
    cout<<cin.rdstate()<<endl;
    return 0;
}

如果输入的数字是"zzzz",那么rdstate返回值为4。
如果输入的数字是"10zzzz",那么rdstate返回值为0,数字的值为10,输入流中包含"zzzz"。

我的问题是:
1. 为什么"10zzzz"这样的输入没有被视为无效输入(至少应该设置一个失败位)?
2. 如何优雅地检测和处理这种情况?

谢谢!
2个回答

2
首先,我想问一下您打算用以下内容做什么:
cout<<cin.rdstate()<<endl;

阅读此页面以了解rdstate()的正确使用方法http://www.cplusplus.com/reference/iostream/ios/rdstate/

第二点: 为了检查输入是字符串类型还是整数类型,您可能需要添加一些额外的内容,将输入字符串转换为整数数据,并在提供无效输入时响应错误消息。

因此,这将帮助您:

int main() {

 string input = "";

 // How to get a string/sentence with spaces
 cout << "Please enter a valid sentence (with spaces):\n>";
 getline(cin, input);
 cout << "You entered: " << input << endl << endl;

 // How to get a number.
 int myNumber = 0;

 while (true) {
   cout << "Please enter a valid number: ";
   getline(cin, input);

   // This code converts from string to number safely.
   stringstream myStream(input);
   if (myStream >> myNumber)
     break;
   cout << "Invalid number, please try again" << endl;
 }
 cout << "You entered: " << myNumber << endl << endl;

 // How to get a single char.
 char myChar  = {0};

 while (true) {
   cout << "Please enter 1 char: ";
   getline(cin, input);

   if (input.length() == 1) {
     myChar = input[0];
     break;
   }

   cout << "Invalid character, please try again" << endl;
 }
 cout << "You entered: " << myChar << endl << endl;

 cout << "All done. And without using the >> operator" << endl;

 return 0;
}

感谢您的回复。当我执行您的程序时,我得到了相同的结果。如果输入10z作为整数,则不会检测到错误。以下是我得到的输出: $ ./err_stream 请输入有效的句子(带空格):
你好世界 您输入的是:你好世界
请输入有效数字:10z 您输入的是:10请输入1个字符:2 您输入的是:2全部完成。而且没有使用>>运算符。
- Achint Mehta
此外,我只加入了“cout<<cin.rdstate()<<endl;”语句,以打印cin流的内部位的值,并查看特定输入是否被视为无效。 - Achint Mehta

0
如果输入的数字是"zzzz",则rdstate返回值为4。 如果输入的数字是"10zzzz",则rdstate返回值为0,数字的值为10,输入流中包含"zzzz"。
要理解这些现象,我们需要了解提取运算符(operator>>)的工作原理。以下是一些好的链接: std::cin和处理无效输入 std::istream::operator>> 还可以深入研究以下内容: operator>>(std::basic_istream) std::basic_istream::operator>>

std::num_get<CharT,InputIt> ::get,std::num_get<CharT,InputIt> ::do_get

简单来说,当写入算术类型时,只要字符序列可以准确解释为该类型的值,就会逐个字符分析输入。 当无法继续解释时,解析停止并使用到那时为止获得的有效值。

"zzzz"没有有效值,而 "10zzzz" 允许解析出 10

至于解决方案,Dennis所提供的基于字符串流的答案可以通过此处here进行改进以处理尾随字符。如果有尾随字符,则 !myStream.eof() 将返回 true。

此外,除了使用字符串流之外,还有其他选项,例如strtolstd::stoi

此外,在这种情况下使用输入字符串流而不是字符串流会更好。请参见 这里

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