zoukankan      html  css  js  c++  java
  • atoi函数的实现(考虑不同进制、溢出)

     2013-07-08 16:21:15

     atio就是将ASCII码表示的字符为int型数据,看似简单的问题,实际上需要考虑的很多。对于简单的问题,考虑是否全面就显得特别重要。

    小结:

    对于该函数的实现要考虑一下几个方面:

    1. 输入字符串为NULL;
    2. 输入开始是否包含符号'+'、'-'
    3. 输入的字符是否合法(对十进制'0' ~'9'为合法的输入);
    4. 计算出的 数值必须为unsigned Int,才能判断溢出;
    5. 数据溢出的处理(上溢出时,返回最大正数;下溢出时,返回最大负数);
    6. 输入的字符包含前导的空格;
    7. 进制的考虑,考虑16进制以及8进制,通过开头的0或0x判断进制;
    8. 对于不同的进制判断的范围不同
      对16进制0123456789ABCDEF或0123456789abcdef
      对8进制01234567
      对10进制0123456789

    其中,前4点是最基本的功能,后面两点则算是功能的扩展,根据不同的要求还可以进行扩展,比如加上各种状态标志,表明是否溢出、输入是否合法,具体在函数_atoi_3中有体现。

    另外,在编写代码时,还有几点需要注意:

    判断是否溢出时,用到的最大数必须为unsigned long int,这样才能表示绝对值最大的负数。

    在考虑进制时,比较繁琐,按照下面步骤来做:

    根据首个非空字符判断符号:

    if (0 == sign)  //判断数值的符号
      {
       if ('+' == *str)
       {
        sign = 1;
        ++str;
       }
       else if('-' == *str)
       {
        sign = -1;
        ++str;
       }
       else if ( isdigit(*str) )
       {
        sign = 1;
       }
      }

    接下来,判断进制:

    if (0 == base) //判断数值的进制
        {
         if ( '0' == *str && ( 'x' == *(str + 1) || 'X' == *(str + 1) ) )
         {
          base = 16;
          str = str + 2;
         }
         else if ( '0' == *str && !( 'x' == *(str + 1) || 'X' == *(str + 1) ) )
         {
          base = 8;
          str = str + 1;
         }
         else
         {
          base = 10;   //不更新str
         }
        }

     计算出数据后,判断溢出:

    if (IsOverflow (IntNumber,sign) == 1)
         {
          return MaxPositive;
         }

         if (IsOverflow (IntNumber,sign) == -1)
         {
          return -( ( MaxPositive + 1) );
         }

    参考:http://blog.csdn.net/tianshuai11/article/details/7798698


    代码(测试暂无发现问题,如发现问题,欢迎指正!):

      1 #include <iostream>
      2 #include <cmath>
      3 using namespace std;
      4 
      5 #define SIZE 100
      6 
      7 //没有区别输入0与
      8 //只能对十进制数进行转换
      9 //没有处理溢出
     10 int _atoi_1(char *str)
     11 {
     12     if (NULL == str)    //输入合法性检查
     13     {
     14         cout<<"NULL input"<<endl;
     15         exit(0);
     16     }
     17 
     18     int sign = 0;
     19     int IntNumber = 0;
     20 
     21     while ( *str )
     22     {
     23         if (0 == sign)
     24         {
     25             if ('-' == *str)
     26             {
     27                 sign = -1;
     28                 ++str;
     29             }
     30             else if ('+' == *str)
     31             {
     32                 sign = 1;
     33                 ++str;
     34             }
     35             else if (*str >= '0' && *str <= '9')
     36             {
     37                 sign = 1;  //不更新str
     38             }
     39             else
     40             {
     41                 cout<<"invalid input!"<<endl;
     42                 exit(0);
     43             }    
     44         }
     45         else if (*str >= '0' && *str <= '9')
     46         {
     47             IntNumber = IntNumber*10 + *str - '0';
     48             ++str;
     49         }
     50         else
     51         {
     52             cout<<"invalid input!"<<endl;
     53             exit(0);
     54         }
     55     }
     56 
     57     return (sign * IntNumber);
     58 }
     59 
     60 //加上溢出处理
     61 //并可对10进制、16进制以及8进制转换
     62 //状态标志
     63 bool IsNotNULL = true;
     64 bool IsDigit = true;
     65 bool IsNotOverflow = true;
     66 
     67 int IsOverflow (unsigned long int IntNumber,int sign)
     68 {
     69     unsigned long int MaxPositive = (long int) pow( (float)2,(int)( 8*sizeof(long int) - 1 ) ) - 1; 
     70     
     71     if ( (sign == 1) && !(IntNumber >= 0 && IntNumber <= MaxPositive ) )   //判断是否溢出
     72     {
     73         IsNotOverflow = true;
     74         return 1;
     75     }
     76 
     77     if ( (sign == -1) && !(IntNumber > 0 && IntNumber <= (MaxPositive + 1) ) )   //判断是否溢出
     78     {
     79         IsNotOverflow = true;
     80         return -1;
     81     }
     82 
     83     return 0;
     84 }
     85 
     86 long int _atoi_2(char *str)
     87 {
     88     if (NULL == str)
     89     {
     90         IsNotNULL = false;
     91         return 0;
     92     }
     93 
     94     int sign = 0;
     95     unsigned long int MaxPositive = (long int) pow( (float)2,(int)( 8*sizeof(long int) - 1 ) ) - 1; 
     96     unsigned long int IntNumber = 0;   //要表示最小负数,须用unsigned long int,若用long int,其范围为-2^31到2^31 -1,不能表示2^31
     97     unsigned int base = 0;
     98 
     99     while ( *str )
    100     {
    101         while ( ' ' == *str || '	' == *str)     //忽略前导的空格或TAB
    102             ++str;
    103         
    104         if (0 == sign)  //判断数值的符号
    105         {
    106             if ('+' == *str)
    107             {
    108                 sign = 1;
    109                 ++str;
    110             }
    111             else if('-' == *str)
    112             {
    113                 sign = -1;
    114                 ++str;
    115             }
    116             else if ( isdigit(*str) )
    117             {
    118                 sign = 1;
    119             }
    120         }
    121         else
    122         {
    123             if ( isdigit(*str) )
    124             {
    125                 if (0 == base)    //判断数值的进制
    126                 {
    127                     if ( '0' == *str && ( 'x' == *(str + 1) || 'X' == *(str + 1) ) )
    128                     {
    129                         base = 16;
    130                         str = str + 2;
    131                     }
    132                     else if ( '0' == *str && !( 'x' == *(str + 1) || 'X' == *(str + 1) ) )
    133                     {
    134                         base = 8;
    135                         str = str + 1;
    136                     }
    137                     else
    138                     {
    139                         base = 10;   //不更新str
    140                     }
    141                 }
    142                 else
    143                 {
    144                     IntNumber = IntNumber * base + *str - '0';
    145 
    146                     if (IsOverflow (IntNumber,sign) == 1)
    147                     {
    148                         return MaxPositive;
    149                     }
    150 
    151                     if (IsOverflow (IntNumber,sign) == -1)
    152                     {
    153                         return -( ( MaxPositive + 1) );
    154                     }
    155 
    156                     ++str;
    157                 }
    158             }
    159             else
    160             {
    161                 IsDigit = false;
    162                 return 0;
    163             }
    164         }
    165     }
    166 
    167     return (sign * IntNumber);   //如果为空串,也即第一个字符即为,返回值为0
    168 }
    169 //对不同的进制,判断的范围不同
    170 //对16进制0123456789ABCDEF
    171 //对8进制01234567
    172 //对10进制0123456789
    173 long int _atoi_3(char *str)
    174 {
    175     if (NULL == str)    //输入合法性检查
    176     {
    177         IsNotNULL = false;
    178         return 0;
    179     }
    180 
    181     int sign = 0;
    182     unsigned long int IntNumber = 0;   //要表示最小负数,须用unsigned long int,若用long int,其范围为-2^31到2^31 -1,不能表示2^31
    183     unsigned long int MaxPositive = (long int) pow( (float)2,(int)( 8*sizeof(long int) - 1 ) ) - 1; 
    184     unsigned int base = 0;
    185 
    186     while ( *str )
    187     {
    188         while ( ' ' == *str || '	' == *str)     //忽略前导的空格或TAB
    189             ++str;
    190 
    191         if (0 == sign)  //判断数值的符号
    192         {
    193             if ('+' == *str)
    194             {
    195                 sign = 1;
    196                 ++str;
    197             }
    198             else if('-' == *str)
    199             {
    200                 sign = -1;
    201                 ++str;
    202             }
    203             else if ( isdigit(*str) )
    204             {
    205                 sign = 1;
    206             }
    207             else
    208             {
    209                 IsDigit = false;
    210                 return 0;
    211             }
    212         }
    213         else
    214         {    
    215             if (0 == base)    //判断数值的进制
    216             {
    217                 if ( '0' == *str && ( 'x' == *(str + 1) || 'X' == *(str + 1) ) )
    218                 {
    219                     base = 16;
    220                     str = str + 2;
    221                 }
    222                 else if ( '0' == *str && !( 'x' == *(str + 1) || 'X' == *(str + 1) ) )
    223                 {
    224                     base = 8;
    225                     str = str + 1;
    226                 }
    227                 else
    228                 {
    229                     base = 10;   //不更新str
    230                 }
    231             }
    232             else
    233             {
    234                 if (10 == base)
    235                 {
    236                     if ( isdigit(*str) )
    237                     {
    238                         IntNumber = IntNumber * base + *str - '0';
    239                         if (IsOverflow (IntNumber,sign) == 1)
    240                         {
    241                             return MaxPositive;
    242                         }
    243 
    244                         if (IsOverflow (IntNumber,sign) == -1)
    245                         {
    246                             return -( ( MaxPositive + 1) );
    247                         }
    248                         ++str;
    249                     }
    250                     else
    251                     {
    252                         IsDigit = false;
    253                         return 0;
    254                     }
    255                 }
    256                 else if (16 == base)
    257                 {
    258                     if ( isdigit(*str) || (*str >= 'a'&& *str <= 'f') || (*str >= 'A'&& *str <= 'F'))
    259                     {
    260                         if ( isdigit(*str))
    261                         {
    262                             IntNumber = IntNumber * base + *str - '0';
    263                         }
    264                         else if (*str >= 'a'&& *str <= 'f') 
    265                         {
    266                             IntNumber = IntNumber * base + *str - 'a' + 10;
    267                         }
    268                         else if (*str >= 'A'&& *str <= 'F')
    269                         {
    270                             IntNumber = IntNumber * base + *str - 'A' + 10;
    271                         }
    272 
    273                         if (IsOverflow (IntNumber,sign) == 1)
    274                         {
    275                             return MaxPositive;
    276                         }
    277 
    278                         if (IsOverflow (IntNumber,sign) == -1)
    279                         {
    280                             return -( ( MaxPositive + 1) );
    281                         }
    282                         ++str;
    283                     }
    284                     else
    285                     {
    286                         IsDigit = false;
    287                         return 0;
    288                     }
    289                 }
    290                 else
    291                 {
    292                     if ( *str>= '0' && *str <= '7')
    293                     {
    294                         IntNumber = IntNumber * base + *str - '0';
    295                         if (IsOverflow (IntNumber,sign) == 1)
    296                         {
    297                             return MaxPositive;
    298                         }
    299 
    300                         if (IsOverflow (IntNumber,sign) == -1)
    301                         {
    302                             return -( ( MaxPositive + 1) );
    303                         }
    304                         ++str;
    305                     }
    306                     else
    307                     {
    308                         IsDigit = false;
    309                         return 0;
    310                     }
    311                 }
    312             }    
    313         }
    314     }
    315 
    316     return (sign * IntNumber);   //如果为空串,也即第一个字符即为,返回值为0
    317 }
    318 
    319 //测试程序
    320 int main()
    321 {
    322     char str[SIZE];
    323 
    324     cout<<"size of type int is : "<<sizeof(int)<<endl;   //4
    325     cout<<"size of type long int is : "<<sizeof(long int)<<endl;    //4
    326     cout<<"size of type float is : "<<sizeof(float)<<endl;    //4
    327     cout<<"size of type long double is : "<<sizeof(long double)<<endl;    //8
    328     /*char str[SIZE] = "100278";
    329     char str[SIZE] = "+1267
    330     char str[SIZE] = "-12";
    331     char str[SIZE] = "+";
    332     char str[SIZE] = "-";
    333     char str[SIZE] = "";
    334     char str[SIZE] = "z98";
    335     char str[SIZE] = "-9s8";*/
    336 
    337     //test _atoi_1...
    338     cout<<"test _atoi_1..."<<endl;
    339     cout<<"please enter the string :"<<endl;
    340     while(cin>>str)
    341     {
    342         cout<<"the string is :"<<str<<endl;
    343         cout<<"the int number is : "<<_atoi_1(str)<<endl;
    344         cout<<"please enter the string :"<<endl;
    345     }
    346 
    347     cin.clear();
    348     cin.sync();
    349     cout<<endl;
    350 
    351     //test _atoi_2...
    352     cout<<"test _atoi_2..."<<endl;
    353     cout<<"please enter the string :"<<endl;
    354     while(cin>>str)
    355     {
    356         cout<<"the string is :"<<str<<endl;
    357         cout<<"the int number is : "<<_atoi_2(str)<<endl;
    358         cout<<"please enter the string :"<<endl;
    359     }
    360 
    361     cin.clear();
    362     cin.sync();
    363     cout<<endl;
    364 
    365     //test _atoi_3...
    366     cout<<"test _atoi_3..."<<endl;
    367     cout<<"please enter the string :"<<endl;
    368     while(cin>>str)
    369     {
    370         cout<<"the string is :"<<str<<endl;
    371         cout<<"the int number is : "<<_atoi_3(str)<<endl;
    372         cout<<"please enter the string :"<<endl;
    373     }
    374 
    375     return 0;
    376 }

     对代码的测试也要注意开头中提到的几点,运行结果:

    size of type int is : 4
    size of type long int is : 4
    size of type float is : 4
    size of type long double is : 8
    test _atoi_1...
    please enter the string :
    12
    the string is :12
    the int number is : 12
    please enter the string :
    +12
    the string is :+12
    the int number is : 12
    please enter the string :
    -12
    the string is :-12
    the int number is : -12
    please enter the string :
    2147483647
    the string is :2147483647
    the int number is : 2147483647
    please enter the string :
    2147483628
    the string is :2147483628
    the int number is : 2147483628
    please enter the string :
    2147483648
    the string is :2147483648
    the int number is : -2147483648
    please enter the string :
    -2147483649
    the string is :-2147483649
    the int number is : 2147483647
    please enter the string :
    ^Z
    
    test _atoi_2...
    please enter the string :
    2147483648
    the string is :2147483648
    the int number is : 2147483647
    please enter the string :
    -2147483648
    the string is :-2147483648
    the int number is : -2147483648
    please enter the string :
    -2147483649
    the string is :-2147483649
    the int number is : -2147483648
    please enter the string :
    0x1a
    the string is :0x1a
    the int number is : 0
    please enter the string :
    089
    the string is :089
    the int number is : 73
    please enter the string :
    0x89
    the string is :0x89
    the int number is : 137
    please enter the string :
    0xaa
    the string is :0xaa
    the int number is : 0
    please enter the string :
    ^Z
    
    test _atoi_3...
    please enter the string :
    2147483648
    the string is :2147483648
    the int number is : 2147483647
    please enter the string :
    -2147483649
    the string is :-2147483649
    the int number is : -2147483648
    please enter the string :
    0x1a
    the string is :0x1a
    the int number is : 26
    please enter the string :
    -0xaa
    the string is :-0xaa
    the int number is : -170
    please enter the string :
    089
    the string is :089
    the int number is : 0
    please enter the string :
    077
    the string is :077
    the int number is : 63
    please enter the string :
    ^Z
    请按任意键继续. . .
  • 相关阅读:
    剖析VC++函数调用约定转
    C++的坑真的多吗?转
    An Introduction to LockFree Programming转
    __cdecl __stdcall区别转
    学习PHP感谢帅哥分享O(∩_∩)O~
    28个Unix/Linux的命令行神器转
    C++ 对象的内存布局(上)转
    一个fork的面试题转
    20本最好的Linux免费书籍转
    谁说外国人都很文明
  • 原文地址:https://www.cnblogs.com/youngforever/p/3178379.html
Copyright © 2011-2022 走看看