手动将字符串转换为 int 并检查 C/C++ 中是不是发生溢出?

Posted

技术标签:

【中文标题】手动将字符串转换为 int 并检查 C/C++ 中是不是发生溢出?【英文标题】:Manually converting string to int and check if an overflow occured in C/C++?手动将字符串转换为 int 并检查 C/C++ 中是否发生溢出? 【发布时间】:2016-04-27 18:34:49 【问题描述】:

我有以下问题 - 我编写了一个函数,它接受一个字符串并将其转换为一个 int,但我不知道如何检查是否发生任何溢出。我想在发生溢出之前返回整数的最后一个可能值。 例如:如果我有一个“2147483648”的字符串表示,我想将 214748364 作为 int 返回,因为在下一次迭代中会发生溢出。你有什么想法可以解决这个问题吗?

我的代码是:

    int main () 
    string s = "2147483647";
    int num = 0, i = 0, buff = 0;
    bool isNegative = false;

    if (s[0] == '-') 
            isNegative = true;
            i++;
        
    while (i < s.length()) 
        if (num < (INT_MAX/10)) 
            num *= 10;
        

        if (num < INT_MAX - 10)
            num += s[i++] - '0';
        else
            break;

    

    if (isNegative)
        num = -num;

    cout << "\nthe number is: " << num;

    getch();
    return 0;

【问题讨论】:

你能告诉我你想要的多个输入和输出吗,或者更详细地解释你想要什么。似乎有一种更简单的方法可以做到这一点。 你可以检查num的值before乘以10。在溢出事件发生之前捕捉它。 我们可以假设不允许使用像 std::stoistrtol 这样的预先存在的函数吗? 请不要涉足发布的代码。这不是一个实时的编辑反馈网站。你也需要在第一个条件下打破循环。 if (num &lt; (INT_MAX/10)) num *= 10; if (num &lt; INT_MAX - 10) num += s[i++] - '0'; 不起作用。尝试"2147483640""2147483647" 最好将您的帖子恢复为@Weather Vane 评论的原始帖子 【参考方案1】:

为了应对int 溢出,代码必须防止它。 在尝试 num*10 + digit 之前简单测试 numdigit 是否太大

(num >= INT_MAX/10) && ((num > INT_MAX/10) || (digit > INT_MAX%10))

用法

overflow = false;
while (i < s.length()) 
  int digit = s[i++] - '0';

  // Will num*10 + digit overflow?
  if ((num >= INT_MAX/10) && ((num > INT_MAX/10) || (digit > INT_MAX%10))) 
    // or break per OP's coding goal
    num = INT_MAX;
    overflow = true;
   else 
    num *= 10;
    num += digit;
  

OP 的代码在INT_MIN 的文本版本上也存在问题。

Sample my_atoi() 正确返回[INT_MIN ... INT_MAX]

【讨论】:

【参考方案2】:

我看到了两种可能的解决方案:

1) 在将 num 乘以 10 之前检查是否 num

2) 将字符串转换为 int 后,使用 snprintf 将 int 打印回字符串并使用 strcmp 查看字符串是否相同。

【讨论】:

认为你的意思是 `INT_MAX / 10` 这里 `INT_MAX - 10` @user4581301 两者都有,但只有num&lt;(INT_MAX/10) 是必需的。加 9 就不能溢出INT_MAX 我试过if (num&lt; (INT_MAX/10)) num *= 10; if (num &lt; INT_MAX - 10 ) num += s[i++] - '0';,但它不起作用。 感谢@WeatherVane。无法理解上次测试的目的。 如果这是正确答案,知道我做错了什么吗?我正在检查num&lt;(INT_MAX/10) 然后num *= 10【参考方案3】:

最好的办法是使用stoi,而不是手工制作劣质的解决方案。

try 
    i = stoi(s);
 catch(const out_of_range& /*e*/) 
    i = numeric_limits<int>::max();

Live Example

【讨论】:

主题中有“手动”是有原因的。我不想为此解决方案使用函数。还是谢谢。 @Calihog 我不知道你为什么这么说?您为什么要尝试重新发明标准已经提供的内容?除非……这是作业吗?

以上是关于手动将字符串转换为 int 并检查 C/C++ 中是不是发生溢出?的主要内容,如果未能解决你的问题,请参考以下文章

将 C/C++ 无符号字符转换为 JAVA 时出现问题

c ++将void *转换为int错误

在将字符串转换为 int 之前检查字符串是不是不是数字 [重复]

是否有更直接的方法将float转换为int而不是添加0.5f并使用截断转换?

Arduino:将字符串十六进制“#FFFFFF”转换为 3 int

Java - char、int 转换