我正在做一个控制台应用程序,我正在将一个整数传递给应用程序并且工作正常,但如果我传递一封信,那就太疯狂了,
int opt=0;
std::cout<<"Pick lang:"<<'\n';
std::cout<<"1.[es-ES]:"<<'\n';
std::cout<<"2.[en-US]:"<<'\n';
std::cin >> opt;
while(opt<1 || opt>2)
{
std::cout<<"\nERROR!"<<'\n';
std::cout<<"Pick lang again:"<<'\n';
std::cout<<"1.[es-ES]:"<<'\n';
std::cout<<"2.[en-US]:"<<'\n';
std::cin >> opt;
}
我尝试使用isdigit()但我得到了相同的结果。谢谢
答案 0 :(得分:7)
执行cin&gt;&gt;之后提取,你想检查cin流是否仍然是好的。如果你希望cin提取一个数字,但它会得到其他东西,例如。就像一封信,然后流将被设置为一个糟糕的状态,这就是为什么你看到它“变得疯狂”。
你要做的就是在输入之后,检查cin是否还是好的。如果它处于错误状态,则需要清除其标志,然后删除流中的任何垃圾数据。如果不这样做,那么后续使用cin将无法正常运行。
以您的代码段为例,您可以将其更改为以下内容:
int opt = 0;
bool inputGood = false;
do
{
std::cout << "Pick lang again:" << '\n';
std::cout << "1.[es-ES]:" << '\n';
std::cout << "2.[en-US]:" << '\n';
inputGood = std::cin >> opt;
if(!inputGood)
{
std::cout << "\nERROR! Invalid choice." << '\n';
cin.clear();
while( cin.get() != '\n' );
}
}while(!inputGood || opt < 1 || opt > 2);
编辑:在cin错误处理中发出轻微错误。已更正,现在应该正常工作。 :)
答案 1 :(得分:2)
问题是调用std::cin >> opt
无法解析字符并立即返回(不使用缓冲区),然后它找到相同的内容并失败....
您应该检查操作的结果并对其作出反应。一种可能性是检查失败位(std::cin.fail()
)并使整个操作失败或消耗部分缓冲区(可能是单个字符,可能更多,具体取决于您希望应用程序的行为方式)。
最简单的事情可能不是读取数字,而是读取字符,然后与预期字符进行比较:
char opt = 0;
do {
// prompt user for input
if (! (std::cin >> opt) ) {
// io error, report and bail out
break;
}
} while ( opt != '0' && opt != '1' );
答案 2 :(得分:1)
当您插入一封信时会发生这种情况:
operator>>
从流中提取字符并尝试将其转换为数字; ios::failbit
并返回; opt
可能没有被触及(标准将这些东西委托给语言环境库,这是一个我从未真正理解的C ++区域 - 对于勇敢的,它是在§22.2.2.1.2); opt
保持原样,循环继续; std::cin >> opt;
时,operator>>
看到状态仍为ios::failbit
,因此它甚至不会尝试提取任何内容; 要解决此问题,您应该清除错误状态并从输入缓冲区中删除“错误”字符。由于您可能不希望将所有代码添加到每个cin>>
,因此创建一个处理此常见问题的函数非常有用;就个人而言,我创建了这个经常被证明有用的小标题(AcquireInput.hpp
):
#ifndef ACQUIREINPUT_HPP_INCLUDED
#define ACQUIREINPUT_HPP_INCLUDED
#include <iosfwd>
#include <limits>
#include <string>
template<typename InType> void AcquireInput(std::ostream & Os, std::istream & Is, const std::string & Prompt, const std::string & FailString, InType & Result)
{
do
{
Os<<Prompt.c_str();
if(Is.fail())
{
Is.clear();
Is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
Is>>Result;
if(Is.fail())
Os<<FailString.c_str();
} while(Is.fail());
}
template<typename InType> InType AcquireInput(std::ostream & Os, std::istream & Is, const std::string & Prompt, const std::string & FailString)
{
InType temp;
AcquireInput(Os,Is,Prompt,FailString,temp);
return temp;
}
/* Usage example:
//1st overload
int AnInteger;
AcquireInput(cout,cin,"Please insert an integer: ","Invalid value.\n",AnInteger);
//2nd overload (more convenient, in this case)
int AnInteger=AcquireInput(cout,cin, "Please insert an integer: ","Invalid value.\n");
*/
#endif
答案 3 :(得分:1)
直接读数是 问题
如果std :: cin输入了它 无法处理,std :: cin进入了 “失败”状态输入它不能 进程留在输入流上。
std :: cin将忽略所有输入 直到“失败”状态被清除: std :: cin.clear()
阅读的例程 一个数字直接应该:
阅读 编号
检查输入 流仍然有效
- 醇>
如果输入 流不好(!std :: cin)
- 呼叫 std :: cin.clear()取流 走出“失败”状态。
- 从中移除 流引起的输入 问题:std :: cin.ignore(...)
- 获取 如果适当,再次输入或 否则处理错误
此处有更多信息:http://www.augustcouncil.com/~tgibson/tutorial/iotips.html