带有 + 的 Cin 输入导致下一个输入为字符串
Cin input with a + causes next input to be a string
所以我是 C++ 的新手,我正在为我的 class 做作业。我 运行 在尝试检查输入是字符串还是 double/int 时遇到问题。所以我做了一个基本程序来测试它
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
string hi;
double hello;
cin >> hello;
if (!cin)
{
//Strings go here
cin.clear();
cin >> hi;
cout << hi << endl;
}
else
{
cout << hello << endl;
}
cout << "Done!" << endl;
}
所以它基本上在输入字母(例如"j"或"a")或数字时有效,但在输入“+”或“-”时它会等待下一个输入然后强制它通过字符串块,即使它是一个数字。但是“*”或“/”被读取为字符串并且不会导致该问题(我假设因为它们不是明确的运算符)
我想我可能遗漏了一些东西。谢谢
编辑:我一次测试单一类型(例如 123、1、d、+)而不混合类型,因此不会有任何具有双精度和字符串的输入
根据 user4581301 的建议,我将放入一些示例输入和输出
输入:输出
"Hello":"Hello"
123:123
"/":"/"
"+" (在: 2之后输入):"2"
问题
您的程序没有完全按预期运行,因为它没有考虑可能消耗但丢失的字符。
以下是按预期工作的不同案例:
abc
:读取的第一个字符不是数字,因此不会被消耗并且 cin 很快失败。第二次读取读取作为字符串存在的每个字符。
123abc456
:读取第一个123
。当遇到 a
时,它不会被消耗,因为它不是有效的数字。进一步阅读停止,但可以读取数值。
/123
:读取的第一个字符不是数字,所以它没有被消耗,cin 失败。第二次读取读取作为字符串存在的每个字符。
-123
或+123
:第一个字符被认为是有效的数字字符并被读取,然后读取其余部分,仍然是一个数值。如果您认为可以对 double 或 int 进行签名,则按预期工作。根据输出格式,+ 可能不会出现在您的输出中。
以下是不起作用的情况:如果第一个字符是 +
或 -
但它后面没有有效的数字字符。在这种情况下,第一个字符被消耗,但下一个字符使数字输入失败。然后将剩余的字符作为字符串读取(除了已经消耗并丢失的第一个符号)。示例:
++123
+ 123
(space 结束提取失败的 double,余数作为字符串读取)。
解决方案
最简单的解决方案是将输入读取为字符串,然后尝试转换该字符串。
例如:
size_t processed;
string hi;
double hello;
cin >> hi;
try {
hello = stod(hi,&processed);
cout<<"number:" <<hello;
if (processed<hi.size())
cout << " (followed by something)";
cout <<endl;
}
catch (...) // should be more precise in catching, but it's for the proof of concept
{
cout <<"string: "<< hi << endl;
}
如果您想将 + 和 - 视为字母数字,则在尝试进行转换之前检查 hi
是否为非空以及 hi[0] 是否为数字会很容易。
或者,您也可以对字符串进行 regex 检查,看它是否与数字格式匹配。
所以我是 C++ 的新手,我正在为我的 class 做作业。我 运行 在尝试检查输入是字符串还是 double/int 时遇到问题。所以我做了一个基本程序来测试它
#include <iostream>
#include <string>
using namespace std;
int main(int argc, char *argv[])
{
string hi;
double hello;
cin >> hello;
if (!cin)
{
//Strings go here
cin.clear();
cin >> hi;
cout << hi << endl;
}
else
{
cout << hello << endl;
}
cout << "Done!" << endl;
}
所以它基本上在输入字母(例如"j"或"a")或数字时有效,但在输入“+”或“-”时它会等待下一个输入然后强制它通过字符串块,即使它是一个数字。但是“*”或“/”被读取为字符串并且不会导致该问题(我假设因为它们不是明确的运算符) 我想我可能遗漏了一些东西。谢谢
编辑:我一次测试单一类型(例如 123、1、d、+)而不混合类型,因此不会有任何具有双精度和字符串的输入
根据 user4581301 的建议,我将放入一些示例输入和输出
输入:输出
"Hello":"Hello"
123:123
"/":"/"
"+" (在: 2之后输入):"2"
问题
您的程序没有完全按预期运行,因为它没有考虑可能消耗但丢失的字符。
以下是按预期工作的不同案例:
abc
:读取的第一个字符不是数字,因此不会被消耗并且 cin 很快失败。第二次读取读取作为字符串存在的每个字符。123abc456
:读取第一个123
。当遇到a
时,它不会被消耗,因为它不是有效的数字。进一步阅读停止,但可以读取数值。/123
:读取的第一个字符不是数字,所以它没有被消耗,cin 失败。第二次读取读取作为字符串存在的每个字符。-123
或+123
:第一个字符被认为是有效的数字字符并被读取,然后读取其余部分,仍然是一个数值。如果您认为可以对 double 或 int 进行签名,则按预期工作。根据输出格式,+ 可能不会出现在您的输出中。
以下是不起作用的情况:如果第一个字符是 +
或 -
但它后面没有有效的数字字符。在这种情况下,第一个字符被消耗,但下一个字符使数字输入失败。然后将剩余的字符作为字符串读取(除了已经消耗并丢失的第一个符号)。示例:
++123
+ 123
(space 结束提取失败的 double,余数作为字符串读取)。
解决方案
最简单的解决方案是将输入读取为字符串,然后尝试转换该字符串。
例如:
size_t processed;
string hi;
double hello;
cin >> hi;
try {
hello = stod(hi,&processed);
cout<<"number:" <<hello;
if (processed<hi.size())
cout << " (followed by something)";
cout <<endl;
}
catch (...) // should be more precise in catching, but it's for the proof of concept
{
cout <<"string: "<< hi << endl;
}
如果您想将 + 和 - 视为字母数字,则在尝试进行转换之前检查 hi
是否为非空以及 hi[0] 是否为数字会很容易。
或者,您也可以对字符串进行 regex 检查,看它是否与数字格式匹配。