无效数字总是降到0
invalid numbers always fall to 0?
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表达式中是错误的,但0仍然是一个数字。如何检查输入是否真的像"%234"一样无效??
您需要检查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;
}
上面的代码是,仅用于说明。如果您需要更高级的解析,请查看BoostSpirit.
此外,显然这并不能保证每次都有效。使用:
auto inputEnd = ss.tellg();
ss.seekg(0, std::ios::end);
if (inputEnd == ss.tellg()) {
检查ss
是否为空可能有助于解决此问题。
我认为您不了解流是如何工作的。请允许我解决您的误解:
如果正在评估的数据不符合类型的格式化要求,则流不会尝试将任何值提取到number
中。提取的工作方式是流逐个迭代字符序列中的每个字符,并将每个字符作为提取目标类型的可行数据进行测试。如果字符不可行,提取将停止(这就是为什么您在输入类似"2342fdsf"
的字符时看到成功的原因;流将继续提取,直到找到无效字符。"2342"
是整数的有效字符,而"f"
不是)
如果流发现一个无效字符,则不对变量(在本例中为number
)执行任何进一步操作。事实上,它是由实现定义的,如果提取无法生成任何字符,那么未初始化的变量的值是多少。考虑到这一点,检查操作数的值以确定I/O是否失败是潜在的危险。这就是检查流状态的作用:
std::istringstream iss(streamStr); if (iss >> number) { std::cout << "Extraction produced: " << number << 'n'; }
如果提取失败,流将设置适当的位。然后,流将使用operator bool()
隐式地转换为布尔值(或operator void*()
在C++11之前,随后将进行转换为布尔型)。布尔函数将使用!this->fail()
检查流状态(同时检查badbit
和failbit
),如果函数返回true,则将执行if
主体。
如果流不是处于良好状态(!this->fail()
返回false),则意味着提取无法生成值,并且if
语句体将不求值。
通过在条件检查中封装提取,而不是试图提取到的东西的值。
假设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库参考
为了测试number
,我建议您创建一个布尔类型的函数,以便它一次测试所有可能的输入错误。
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 检查输入是否不是整数或数字
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 无法访问嵌套类.类的使用无效
- 如何用数字处理log(0)
- 最高有效数字侧的第N位
- 如何获取一个数字的前3位
- 查找最接近的大于当前数字的数字的索引
- 找到两对数字,使它们的乘积的绝对差最小化
- 使用 std::locale 格式化法语数字时无效的 UTF-8 数据
- 用户输入逻辑运算符符号或数字,如果输入字符或字符串则无效
- 为什么此 DirectX 10 "D3DXVec3Lerp" 函数返回无效数字?
- 带有 cl 的 cmake:无效的数字参数 '/Wno-uninitialized'
- 无效数字总是降到0
- 错误 D8021:无效的数字参数'/wdtrue'
- 数组中的无效八进制数字是否有解决方法
- 在 pthread_t 为数字的平台上,0 保证为无效值
- 使用nmake编译Qt给出命令行错误D8021:无效的数字参数' /FS '