反转无符号的int数导致溢出

时间:2017-03-15 13:14:37

标签: c return-type

输入一个unsigned int,反转它并查看它是否仍然在范围内,如果是,则打印相反的数字,如果没有,打印你的数字超出范围

#include <stdio.h>
#include <stdlib.h> 
#include <limits.h>

int main() {
    unsigned int a = UINT_MAX; // 0xffff
    printf("max unsigned int = %u\n\n", a);

    unsigned int x = 0;
    printf("please enter any unsigned int,\nit will show the reverse number if it's in range\n(enter 10 digit only)\n\n");
    while (scanf("%u", &x) != EOF) {
        //printf("x =  %u\n", x); 
        // above %d will print each UINT's binary oder, ex: enter 4294967292, x = -1 
        // if change %u, it will print entered number, ex: enter 4294967292, x = 4294967292 
        unsigned int temp = x, result = 0;
        int m = 0;
        while (temp > 0) {
            unsigned int digit = temp % 10;
            if (result > 429496729) {
                m++; //if reversed 9digits is already bigger 429496729, 
                //then 'result =  result * 10 + digit', it will have over flow problem.
            }
            result = result * 10 + digit;
            temp /= 10;
            if (temp == 0) break;
        }
        printf("m=%d\n", m);
        if (m >= 1)
            printf("out of range\n");
        else
            printf("result is %u\n", result);

        printf("\n");       
    }
    return 0;
}

3 个答案:

答案 0 :(得分:1)

你永远不会返回反转的数字,你返回的只是最后(最右边)的数字。

你的函数不会“返回”,它会返回调用自身的结果,这是不一样的。

答案 1 :(得分:0)

您的溢出测试不正确,因为您将unsigned int result与大于此类型范围的值进行比较,因此测试始终失败。

有两种方法可以检查溢出:

  • 利用无符号算术,你可以比较的结果是小于之前的结果。

  • 或者,您可以比较result是否大于UINT_MAX / 10,或者它是否相等,如果数字大于UINT_MAX % 10。此方法适用于所有整数类型,无符号和有符号。

以下是修改后的代码:

#include <stdio.h>
#include <limits.h>

int main(void) {
    unsigned int x;

    printf("max unsigned int = %u\n\n", UINT_MAX);
    printf("please enter any unsigned int,\n"
           "it will show the reverse number if it is in range\n"
            "(enter 10 digit only)\n\n");

    while (scanf("%u", &x) == 1) {
        unsigned int temp = x, result = 0;
        int overflow = 0;
        while (temp > 0) {
            unsigned int digit = temp % 10;
            if (result > UINT_MAX / 10
            ||  (result == UINT_MAX / 10 && digit > UINT_MAX % 10)) {
                overflow++; // the result will not fit
                break;
            }
            result = result * 10 + digit;
            temp /= 10;
        }
        if (overflow)
            printf("out of range for unsigned int type\n\n");
        else
            printf("result is %u\n\n", result);
    }
    return 0;
}

答案 2 :(得分:0)

感谢您的回答,非常感谢! 1.关于&#34;比较结果是否大于UINT_MAX / 10或它是否相等,如果数字大于UINT_MAX%10。此方法适用于所有整数类型,无符号和有符号。&#34;

是(结果== UINT_MAX / 10&amp;&amp; digit&gt; UINT_MAX%10))是否必要? 我假设输入数字低于数字 (提醒:只在UINT_MAX中输入数字)

  • unsigned int 4294967295(10digit),反向将是592769492(4)/ out 范围
  • unsigned int 4294967294(10digit),反向将是492769492(4) / out range

  • unsigned int 4227694924(10digit),反向将是429496722(4)/ in 范围

  • unsigned int 927694924(9digit),反向将是429496729 / in 范围

  • 我能想到的最接近的输入是3927694924,它将适合(结果== UINT_MAX / 10&amp;&amp; digit&gt; UINT_MAX%10))/在范围内

但是,我已经为signed int做了同样的事情,请看下面的代码,但我不知道如何应用你的signed int方法:

#include <stdio.h>
#include <limits.h>

int main(void) {
    int x;

    printf("max int = %d\n", INT_MAX);
    printf("min int = %d\n\n", INT_MIN);

    printf("please enter any integer within -2,147,483,648 ~ 2,147,483,647,\n"
           "it will show the reverse number if it is in range\n"
            "(enter 10 digit or less)\n\n");

    while (scanf("%d", &x) == 1) {
        int temp = x, result = 0;
        int overflow = 0;
        while (temp >= INT_MIN || temp <= INT_MAX) {
            int digit = temp % 10;
            printf("temp is %u\n", temp);
            printf("result is %u\n", result);
            if (result > INT_MAX / 10 || (result == INT_MAX / 10 && digit > INT_MAX % 10)) {
                overflow++; // the result will not fit
                break;
            }
            if (result < INT_MIN / 10 || (result == INT_MIN / 10 && digit > INT_MIN % 10)) {
                overflow++; // the result will not fit
                break;
            }
            result = result * 10 + digit;
            temp /= 10;
            if(temp == 0) break;
        }
        if (overflow)
            printf("out of range for int type\n\n");
        else
            printf("result is %d\n\n", result);
    }
    return 0;
}