cout << "Enter a positive integer or zero: ";
getline(cin, streamStr);
stringstream(streamStr) >> number;
if (!number) {
cout << "invalid input detected or the input is too big.\n";
return 1;
}
像“%234”或“sdf2334”这样的输入总是会降为0,这在bool表达式中为false,但0仍然是一个数字。 如何检查输入是否真的无效,如“%234”??
答案 0 :(得分:5)
您需要检查operator>>
的返回值,该值与您正在读取的变量的值不同:
if (stringstream(streamStr) >> number) {
...
那么返回的值是什么呢?如果你检查文档,你会发现它本身就是一个流。它转到它的operator bool
(因为它在if
语句中使用),它反过来返回流的有效性,或者IOW,如果最后一个操作成功。
如果您想确保流不包含任何数字,请使用
if (sstream.rdbuf()->in_avail() > 0) {
// something is still there
如果你想允许的话,最后跳过空格:
sstream >> std::ws;
所以,总而言之......
template<typename T,
// those are optional
enable_if<is_default_constructible<T>::value>::type,
enable_if<is_input_streamable<T>::value>::type
>
optional<T> myRead(string input, bool allowTrailingWs = true) {
stringstream str(input);
T val;
// check parsing
if (!(str >> val))
return none;
// allow whitespace at the end
if (allowTrailingWs)
str >> std::ws;
// check if there's any garbage left
if (str.rdbuf()->in_avail() > 0)
return none;
return val;
}
上面的代码仅用于说明目的。如果你需要更高级的解析,请查看Boost.Spirit。
此外,apparently this isn't guaranteed to work every time。使用:
auto inputEnd = ss.tellg();
ss.seekg(0, std::ios::end);
if (inputEnd == ss.tellg()) {
检查ss
是否为空可以帮助解决问题。
答案 1 :(得分:4)
我认为您不了解流的工作原理。请允许我解决你的误解:
如果要评估的数据与该类型的格式要求不对应,则流不会尝试将任何值提取到number
。提取工作通过流逐个迭代字符序列中的每个字符,并测试每个字符作为提取所针对的类型的可行数据。如果角色不可行,则提取停止(这就是您在输入"2342fdsf"
之类的内容时看到成功的原因;流将一直提取,直到找到无效字符。"2342"
是整数的有效字符虽然"f"
不是)
如果流找到无效字符,则不对该变量做任何进一步处理(在本例中为number
)。实际上,它是实现定义的,如果提取无法生成任何字符,则未初始化变量具有什么值。考虑到这一点,检查操作数的值以确定I / O是否失败是有潜在危险的。这是检查流状态的地方:
std::istringstream iss(streamStr); if (iss >> number) { std::cout << "Extraction produced: " << number << '\n'; }
如果提取失败,则流将设置适当的位。然后,流将使用operator bool()
(或operator void*()
pre-C ++ 11隐式转换为布尔值,随后将转换为布尔值)。布尔函数将使用!this->fail()
检查流状态(检查badbit
和failbit
),如果函数返回true,则执行if
正文。
如果流不处于良好状态(!this->fail()
返回false),则表示提取未能生成值,if
语句体未被评估。
答案 2 :(得分:1)
通过在条件检查中包含提取,而不是您尝试提取的内容的值。
答案 3 :(得分:0)
假设number
必须是char值,请尝试使用有助于处理字符串的cctype库。它具有诸如
isdigit(Char_Exp) //Returns true if the value is a digit
和
isctrl(Char_Exp) //Returns true if the value is a control character like %(modulus)
以下是C ++ cctype库引用的链接:cctype library reference
要测试number
我建议你创建一个Boolean类型的函数,以便它一次测试所有可能的输入错误。