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

Posted

技术标签:

【中文标题】C++ 从 istream 读取 int,检测溢出【英文标题】:C++ Read int from istream, detect overflow 【发布时间】:2013-06-14 20:22:39 【问题描述】:

如果我使用 >> 运算符从 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;

在意识形态上正确的做法是什么?

【问题讨论】:

解决方法:使用long long 声明,有效输入最大为2147483646,而不是2147483647 :)(2147483647 是您平台上的 MAX_INT) 在使用 C++ 时,您应该更喜欢 &lt;limits&gt; 而不是 &lt;climits&gt;INT_MAX 替换为 std::numeric_limits&lt;int&gt;::max() @Lol4t0,因为这是 C 源代码文件扫描程序的一部分,我认为这不会起作用。好主意@H2CO3,不能保证工作(尽管我不知道long longint 大小相同的系统,但标准确实允许这样做)。 可能重复:***.com/questions/4442658/c-parse-int-from-string 【参考方案1】:

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

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

在 C++11 之前,无法使用此方法专门检查上溢或下溢。但是在 C++11 中,如果解析的值对于该类型来说太大或太小,结果将被设置为该类型可以容纳的最大值(std::numeric_limits&lt;Type&gt;::max()std::numeric_limits&lt;Type&gt;::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;
    

【讨论】:

正是我想要的!【参考方案2】:

最好的方法是将值作为字符串读取,然后将其转换为整数。在转换过程中,您可以了解该值是否在您要转换的类型的范围内。

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

【讨论】:

如果我要先将其读入字符串,那么我可以将字符串与最大值进行比较。

以上是关于C++ 从 istream 读取 int,检测溢出的主要内容,如果未能解决你的问题,请参考以下文章

C++中文件的读取操作,如何读取多行数据,如何一个一个的读取数据

调用'get'和'peek'时阻止c ++ istream锁定

如何将 istream 传递给 c++ 中的函数?

C++面试题

将字节数组从 C# 传递到 C++ DLL 作为 char*

C++ Primer 0x08 练习题解