C ++从istream中读取int,检测溢出

时间:2013-06-14 20:22:39

标签: c++ stream

如果我使用>>读取istream中的整数运算符,以及大于INT_MAX的表示整数,则操作只返回INT_MAX。

我目前正在对INT_MAX进行比较以检测溢出,但如果操作输入“2147483647”,那么它将返回错误,而实际上没有,结果有效。

示例:http://ideone.com/4bXyGd

#include <iostream>
#include <sstream>
#include <climits>

int main() {
    std::istringstream st("1234567890123"); // Try with 2147483647
    int result;

    st >> result;

    if (result == INT_MAX)
        std::cout << "Overflow!" << std::endl;
    else
        std::cout << result << std::endl;

    return 0;
}

这种做法的正确方法是什么?

2 个答案:

答案 0 :(得分:9)

对于一般解析失败(包括数字太大或太小),您只需检查已设置的字符串流的fail bit。最简单的方法是:

if (!st) {
    std::cout << "Could not parse number" << std::endl;
}

在C ++ 11之前,无法使用此方法专门检查溢出或下溢。但是在C ++ 11中,如果解析后的值对于类型来说太大或太小,则结果将设置为类型可以容纳的最大值(std::numeric_limits<Type>::max()std::numeric_limits<Type>::min()),除了设置失败位之外。

所以在C ++ 11中检查值是太大还是小,你可以这样做:

if (!st) {
    if (result == std::numeric_limits<int>::max()) {
        std::cout << "Overflow!" << std::endl;
    } else if (result == std::numeric_limits<int>::min()) {
        std::cout << "Underflow!" << std::endl;
    } else {
        std::cout << "Some other parse error" << std::endl;
    }
}

答案 1 :(得分:1)

执行此操作的最佳方法是将值读取为字符串,然后将其转换为整数。在转换过程中,您可以捕获该值是否符合您要转换为的类型范围。

boost::lexical_cast是一个很好的图书馆。如果值不适合目标类型,它将抛出异常。