防止C++中的隐式转换

4

我要求用户输入一个整数,除非严格为整数,否则不执行代码。

int x;
if(cin >> x)

例如,如果用户输入一个double类型的值,if语句将会使用隐式转换成为整型来执行。但是我不想让代码执行。
我该如何防止这种情况发生?

1
将其作为字符串读取并根据解析内容失败。你知道这就是 << 为你做的事情,对吧?你想要更多的控制……那就自己动手吧。 - Steven Lu
虽然它不是特别适用于C++,但stdlib [strtol]函数将让您知道转换是否在字符串结束之前终止。 - sfstewman
@StevenLu。你能再详细解释一下吗? - Mars
检查你所写的代码行为... - David Rodríguez - dribeas
@NeilKirk:我不 passively aggressive,但他正在问如何避免他的代码中不会发生的事情。我只是建议他检查他所写的行为。 - David Rodríguez - dribeas
显示剩余7条评论
2个回答

10

这里没有转换。如果用户输入的是分数(不是 double),那么 >> 提取会在小数点处停止。

http://ideone.com/azdOrO

int main() {
    int x;
    std::cin >> x;
    std::cout << std::cin.rdbuf();
}

 input:

123.456

output:

.456
如果你想将十进制小数点的存在视为错误,你需要做一些操作来从cin中提取它并进行检测。
使用C++流的一个很好的解析策略是将要处理的内容用getline提取到一个istringstream中,命名为s,然后在完成时检查s.peek() == std::char_traits<char>::eof()。如果您不使用getline来提取单个数字,则peek可以检查下一个字符是否为空格(使用std::isspace),而不会将该字符从流中消耗掉。
虽然有些奇特,但可能是最清晰的检查输入是否结束的方法是使用std::istream::sentry
if ( ! ( std::cin >> x ) || std::istream::sentry( std::cin ) ) {
    std::cerr << "Invalid or excessive input.\n";
}

这会消耗输入末尾的空格。 sentry 还提供了一个 noskipws 选项来避免消耗空格。

if ( ! ( std::cin >> x ) || std::istream::sentry( std::cin, true ) ) {
    std::cerr << "Invalid or excessive input. (No space allowed at end!)\n";
}

检查 rdbuf() 是否包含额外的非空格内容(默认情况下为空将是可以接受的)是一个绝妙的解决方法。+1 - WhozCraig

0

这似乎有效。它忽略空格,我不知道你是否满意。

string s;
cin >> s;
stringstream ss(s);
int x;
if (! (ss >> x))
{
    cerr << "You didn't enter an integer." << endl;
    return -1;
}
string temp;
ss >> temp;
if (! temp.empty())
{
    cerr << "You didn't enter an integer." << endl;
    return -1;
}

1
如果使用if (! (ss >> x) || ss.peek() != stringstream::traits::eof() ),可以实现我的建议,并且更加DRY。 - Potatoswatter
@Potatoswatter 你所说的DRY是什么意思? - Neil Kirk
“不要重复自己”是一种编程原则。 - Potatoswatter
不,|| 按顺序处理其操作数。左侧的所有副作用在右侧开始之前已经完成。除非它被重载了,否则这只会是一种恶劣的做法。(但这里不可能适用于重载。) - Potatoswatter
@LokiAstari 在这个例子中,不能有多余的尾随空格,因为stringstream是由std::string提取器初始化的。另一种不需要虚拟临时变量并允许空格的策略是|| std::istream::sentry( ss )。这可能更清晰,因为你还可以传递(ss, true)不容忍空格。 - Potatoswatter
显示剩余2条评论

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