| 
 | 
 
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册  
 
x
 
题目是模拟atoi函数,进行提取字符串里第一段数字。在进阶题目里,小甲鱼要求对于溢出int的数值报错。网上很多帖子给出两种判断方式: 
(1)你的如何短时间计算出2^ 31?(2)因为x是int型,即使x溢出,由于存储的限制,那么x的值也必然在这个区间范围内(这里不考虑类型升级)。 
 
 针对(1)如何快速计算2^ 31次方:简单粗暴的用16进制表示出来(),或者利用位运算。将最大值最小值记作int_max 和int_min。 
 
 针对(2)我们可以先比较x/10与int_max/10的大小, 再比较最后一位,即可避免上面的尴尬之处。 
 
两种方式在说明什么,我没有看懂。答案里,小甲鱼利用了第一种方式,也就是牺牲时间来计算int的最大值和最小值,然后计算。说真的,我也没看懂。 
现在说一下我的思路: 
  出现溢出,必然是在计算过程中。当一个数值(我们这个题目里只考虑正数,没有把符号计入要提取的范围)接近溢出的时候,已经很大了。溢出刚刚发生的时候,得到的数字会很小。那么我利用临时变量,对提取前后的数值进行了比较,如果数值突然变小,就认为是溢出了。 
  我感觉这个方法虽然只针对了本题,但是会比小甲鱼的思路要简洁一点。 
  [b][b]请各位大佬指正我这思路的不妥之处(除了只能针对本题外)[/b][/b]。 
小甲鱼的程序: 
#include <stdio.h> 
#include <math.h> 
 
int main() 
{ 
        int ch; 
        long long num = 0; 
        long long temp; // 临时变量,用于测试是否超出范围 
        int is_overflow = 0; 
 
        const int max_int = pow(2, sizeof(int) * 8) / 2 - 1; 
        const int min_int = pow(2, sizeof(int) * 8) / 2 * (-1); 
 
        printf("请输入待转换的字符串:"); 
 
        do 
        { 
                ch = getchar(); 
 
                if (ch >= '0' && ch <= '9') 
                { 
                        temp = 10 * num + (ch - '0'); 
                        if (temp > max_int || temp < min_int) 
                        { 
                                is_overflow = 1; 
                                break; 
                        } 
                        else 
                        { 
                                num = temp; 
                        } 
                } 
                else 
                { 
                        if (num) 
                        { 
                                break; // 如果已有数字,则退出循环 
                        } 
                } 
 
        } 
        while (ch != '\n'); 
 
        if (is_overflow) 
        { 
                printf("数值超出范围,结果未定义!\n"); 
        } 
        else 
        { 
                if (!num) 
                { 
                        printf("并未找到任何数值!\n"); 
                } 
                else 
                { 
                        printf("结果是:%d\n", num); 
                } 
        } 
 
        return 0; 
} 
 
 
我写的程序: 
#include<stdio.h> 
 
int main() 
{ 
   int ch,num=0,num0;//ch为输入的字符,num存储结果用的整形数值 
   printf("请输入待转换的字符串:"); 
do 
  { 
    ch=getchar(); 
    
 
        if(ch>='0'&&ch<='9') 
        { 
        num0=num;//临时存储,用于比较是否溢出 
        num=10*num+(ch-'0');//按照10进制记录已读入的值 
                if(num<num0)break;  //溢出了,跳出循环,不再读取字符。 
        } 
        else if(num)   break;  //不是数字,则跳出循环。 
            
   } 
 
    
   while ((ch!='\n')); 
   if(num<num0)         //溢出时打印结果 
         
        printf("数值超出范围,结果未定义!\n"); 
         
   else  if(num!=0)     //正常时打印结果 
        printf("结果是:%d\n",num);  
   else 
        printf("并未找到任何数值!\n");     //没有数字时打印结果 
 
 
 
return 0; 
}
确实奇怪,为什么会没有人帮你呢? 
我帮你看了看,你的思路是对的 
但是这么写不是很好,我的调试器检查出了这个溢出 
还是强制转换一下unsigned类型吧
 - $ cat main.c
 
 - #include <stdio.h>
 
  
- int main() {
 
 -     int ch, num = 0, num0; // ch为输入的字符,num存储结果用的整形数值
 
 -     printf("请输入待转换的字符串:");
 
 -     do {
 
 -         ch = getchar();
 
 -         if(ch >= '0' && ch <= '9') {
 
 -             num0 = num; //临时存储,用于比较是否溢出
 
 - #if 1
 
 -             num = 10 * num + (ch - '0'); //按照10进制记录已读入的值
 
 - #else
 
 -             num = (unsigned)10 * num + (ch - '0'); //按照10进制记录已读入的值
 
 - #endif
 
 -             if(num < num0)
 
 -                 break; //溢出了,跳出循环,不再读取字符。
 
 -         } else if(num) break; //不是数字,则跳出循环。
 
 -     } while((ch != '\n'));
 
  
-     if(num < num0) //溢出时打印结果
 
 -         printf("数值超出范围,结果未定义!\n");
 
 -     else if(num != 0) //正常时打印结果
 
 -         printf("结果是:%d\n", num);
 
 -     else
 
 -         printf("并未找到任何数值!\n"); //没有数字时打印结果
 
  
-     return 0;
 
 - }
 
 - $ gcc-debug -o main main.c
 
 - $ ./main
 
 - 请输入待转换的字符串:2147483647
 
 - 结果是:2147483647
 
 - $ ./main
 
 - 请输入待转换的字符串:2147483648
 
 - main.c:11:17: runtime error: signed integer overflow: 2147483640 + 8 cannot be represented in type 'int'
 
 - 数值超出范围,结果未定义!
 
 - $
 
 - $
 
 - $
 
 - $ vim main.c
 
 - $ cat main.c
 
 - #include <stdio.h>
 
  
- int main() {
 
 -     int ch, num = 0, num0; // ch为输入的字符,num存储结果用的整形数值
 
 -     printf("请输入待转换的字符串:");
 
 -     do {
 
 -         ch = getchar();
 
 -         if(ch >= '0' && ch <= '9') {
 
 -             num0 = num; //临时存储,用于比较是否溢出
 
 - #if 0
 
 -             num = 10 * num + (ch - '0'); //按照10进制记录已读入的值
 
 - #else
 
 -             num = (unsigned)10 * num + (ch - '0'); //按照10进制记录已读入的值
 
 - #endif
 
 -             if(num < num0)
 
 -                 break; //溢出了,跳出循环,不再读取字符。
 
 -         } else if(num) break; //不是数字,则跳出循环。
 
 -     } while((ch != '\n'));
 
  
-     if(num < num0) //溢出时打印结果
 
 -         printf("数值超出范围,结果未定义!\n");
 
 -     else if(num != 0) //正常时打印结果
 
 -         printf("结果是:%d\n", num);
 
 -     else
 
 -         printf("并未找到任何数值!\n"); //没有数字时打印结果
 
  
-     return 0;
 
 - }
 
 - $ gcc-debug -o main main.c
 
 - $ ./main
 
 - 请输入待转换的字符串:2147483648
 
 - 数值超出范围,结果未定义!
 
 - $
 
  复制代码 
如果不考虑负数的话,可以直接作为无符数来计算 
超过了0x80000000就是溢出(包括这个数)
 - $ cat main.c
 
 - #include <stdio.h>
 
  
- int main() {
 
 -     //int ch, num = 0, num0; // ch为输入的字符,num存储结果用的整形数值
 
 -     int ch;
 
 -     unsigned int num = 0;
 
 -     printf("请输入待转换的字符串:");
 
 -     do {
 
 -         ch = getchar();
 
 -         if(ch >= '0' && ch <= '9') {
 
 -             num = num * 10 + (ch - '0');
 
  
-             if(num >= 0x80000000) break; //溢出了,跳出循环,不再读取字符。
 
  
-         } else if(num) break; //不是数字,则跳出循环。
 
 -     } while((ch != '\n'));
 
  
-     if(num >= 0x80000000) //溢出时打印结果
 
 -         printf("数值超出范围,结果未定义!\n");
 
 -     else if(num != 0) //正常时打印结果
 
 -         printf("结果是:%d\n", num);
 
 -     else
 
 -         printf("并未找到任何数值!\n"); //没有数字时打印结果
 
  
-     return 0;
 
 - }
 
 - $ gcc-debug -o main main.c
 
 - $ ./main
 
 - 请输入待转换的字符串:2147483648
 
 - 数值超出范围,结果未定义!
 
 - $ ./main
 
 - 请输入待转换的字符串:2147483647
 
 - 结果是:2147483647
 
 - $
 
  复制代码 
你的这个程序还有一个bug 
0是不是数字,0是数字 
但是
 - $ cat main.c
 
 - #include <stdio.h>
 
  
- int main() {
 
 -     int ch, num = 0, num0; // ch为输入的字符,num存储结果用的整形数值
 
 -     printf("请输入待转换的字符串:");
 
 -     do {
 
 -         ch = getchar();
 
 -         if(ch >= '0' && ch <= '9') {
 
 -             num0 = num; //临时存储,用于比较是否溢出
 
 - #if 1
 
 -             num = 10 * num + (ch - '0'); //按照10进制记录已读入的值
 
 - #else
 
 -             num = (unsigned)10 * num + (ch - '0'); //按照10进制记录已读入的值
 
 - #endif
 
 -             if(num < num0)
 
 -                 break; //溢出了,跳出循环,不再读取字符。
 
 -         } else if(num) break; //不是数字,则跳出循环。
 
 -     } while((ch != '\n'));
 
  
-     if(num < num0) //溢出时打印结果
 
 -         printf("数值超出范围,结果未定义!\n");
 
 -     else if(num != 0) //正常时打印结果
 
 -         printf("结果是:%d\n", num);
 
 -     else
 
 -         printf("并未找到任何数值!\n"); //没有数字时打印结果
 
  
-     return 0;
 
 - }
 
 - $ gcc-debug -o main main.c
 
 - $ ./main
 
 - 请输入待转换的字符串:0
 
 - 并未找到任何数值!
 
 - $ ./main
 
 - 请输入待转换的字符串:abcd1234
 
 - 结果是:1234
 
 - $ ./main
 
 - 请输入待转换的字符串:abcd0
 
 - 并未找到任何数值!
 
 - $ ./main
 
 - 请输入待转换的字符串:abcd0000
 
 - 并未找到任何数值!
 
 - $
 
  复制代码 
这个bug自己改吧
  
 
 
 |   
 
 
 
 |