函数实现-aoti-atol

1. 函数原型

    int atoi ( const char * str );
    long int atol ( const char * str );

2. 函数工作

    atoi是将字符串转化为整型,atol是将字符串转化为长整型,这两个函数的实现十分相似。工作步骤基本如下:
   ·跳过若干空格、制表符等
   ·如果有正号或者负号,进行识别
   ·将数字整合到结果中,直到字符串遍历完毕或者遇到数字以外的其他字符为止。
    C库中的atoi会尽可能的把更多的数字整合到结果中,不能发现数值溢出的问题。而且对于“整数+其他字符”这样的字符串识别出其中的“整数”,并不考虑后面的字符串中有没有非法字符。比如"1234abc",atoi的结果是1234,而不会认为"1234abc"本身是非法的。
    本文给出的aoti实现会考虑到如下几个方面:
    如果没有一个数字被整合到字符串中,抛出异常“没有数字存在”。
    如果数值溢出,抛出异常,“数值溢出”。
    对于"1234abc"这样的数字,保留原有atoi的处理形式,也识别出1234。

3. 函数设计

    为了更好的展示思路,这里我给出一个基于状态机的aoti实现。   

#include < iostream >
using   namespace  std;

int  my_atoi( const   char   * str) {
  
if (str  ==  NULL)
    
throw   " str == NULL! " ;
  
enum  STATE {STATE_SKIP_SPACE, STATE_RECOGNIZE_SIGN, STATE_RECOGNIZE_NUM,
    STATE_RECOGNIZE_LAST_NUM, STATE_RECOGNIZE_TAIL_CHAR};
  STATE state 
=  STATE_SKIP_SPACE;
  
int  max  =  INT_MAX;
  
int  min  =  INT_MIN;
  
int  bound  =  max  /   10 ;
  
int  sign  =   1 ;
  unsigned 
int  result  =   0 ;
  
bool  find_num  =   false ;
  
while ( true ) {
    
switch (state) {
      
case  STATE_SKIP_SPACE: // 跳过尽可能多的空格
        
if ( * str == '   ' ||* str == ' \t ' ||* str == ' \n ' ||* str == ' \f ' ||* str == ' \b ' ||* str == ' \r ' )
          str
++ ;
        
else  
          state 
=  STATE_RECOGNIZE_SIGN;
        
break ;
      
case  STATE_RECOGNIZE_SIGN: // 识别可能的正负符号
        
if ( * str  ==   ' - ' ) {
          str
++ ;
          sign 
=   - 1 ;          
        }
        
else   if ( * str  ==   ' + ' ) {
          str
++ ;
        }
        state 
=  STATE_RECOGNIZE_NUM;
        
break ;
      
case  STATE_RECOGNIZE_NUM: // 最多识别max/10的位数的数字 
        
if ( * str  < ' 0 '   ||   * str > ' 9 '   ||   * str == ' \0 ' //  当前字符不是数字,或者已经结束 
           if (find_num  ==   false //  一个数字都还没遇到过 
             throw    " no num found! " ;
          
else    //  已经遇到过数字了 
             return  result  *  sign;
        
else  {  //  当前字符是数字 
           if (find_num  ==   false )
            find_num 
=   true ;  
          result 
*=   10 ;
          result 
+=  ( * str - ' 0 ' );
          bound 
/=   10 ;
          
if (bound  == 0 ) {
            state 
=  STATE_RECOGNIZE_LAST_NUM;
          }
          str
++ ;
        }
        
break ;
      
case  STATE_RECOGNIZE_LAST_NUM: // 识别最后一个数字
        
if ( * str  < ' 0 '   ||   * str > ' 9 '   ||   * str == ' \0 ' //  当前字符不是数字,或者已经结束 
           return  result  *  sign;  //  能到这一步,肯定是已经遇到了很多数字 
         else  {  //  当前字符是数字
           if ((result  >  max / 10 ||  (sign == 1   &&  ( * str - ' 0 ' ) > (max % 10 ))  ||  (sign ==- 1   &&  ( * str - ' 0 ' ) > abs(min % 10 ))) {
            
throw   " over num limit ! " ;
          }
          
else  {
            result 
*=   10 ;
            result 
+=  ( * str  -   ' 0 ' );
            state 
=  STATE_RECOGNIZE_TAIL_CHAR;
            str
++ ;
          }
        }
        
break ;
      
case  STATE_RECOGNIZE_TAIL_CHAR: // 不能再识别数字了
        
if ( * str  < ' 0 '   ||   * str > ' 9 '   ||   * str == ' \0 ' //  当前字符不是数字,或者已经结束
           return  result  *  sign;
        
else   //  当前字符是数字,此时必然溢出 
           throw   " over num limit ! " ;
        
break ;
      
default :
        
break ;
    }
  }
  
return   0 ;
}

int  main() {
  
char *  a  =   "         +123213123abc " ;
  
char *  max  =   "      2147483647abc " ;
  
char *  min  =   "      -2147483648abc " ;
  
char *  max_more_1  =   "      2999999997abc " ;
  
char *  max_more_2  =   "      2147483648abc " ;
  
char *  min_more_1  =   "      -2147483649abc " ;
  cout 
<<  a  <<   " :   "   <<  my_atoi(a)  <<  endl;
  cout 
<<  max  <<   " :   "   <<  my_atoi(max)  <<  endl;
  cout 
<<  min  <<   " :   "   <<  my_atoi(min)  <<  endl; 
  
try  {
    cout 
<<  max_more_1  <<   " :   " ;
    my_atoi(max_more_1);
  }
  
catch  ( const   char *  info){
    cout 
<<  info  <<  endl;
  }
  
try  {
    cout 
<<  max_more_2  <<   " :   " ;
    my_atoi(max_more_2);
  }
  
catch  ( const   char *  info){
    cout 
<<  info  <<  endl;
  }
  
try  {
    cout 
<<  min_more_1  <<   " :   " ;
    my_atoi(min_more_1);
  }
  
catch  ( const   char *  info){
    cout 
<<  info  <<  endl;
  }
  
char  wait;
  cin 
>>  wait;
  
return   0 ;
}

    long int 的转化与int的转化差不多。

4. 参考资料
    C++ Reference atoi    http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/ 
    C/C++常见面试题(30)----atoi函数    http://blog.csdn.net/lzueclipse/archive/2011/05/26/6446945.aspx
    程序员面试题精选---“itoa函数”和“atoi函数    http://blog.csdn.net/zhangxinrun/archive/2010/12/01/6048695.aspx
    atoi的实现,一道对数值边界考察的题目    http://hi.baidu.com/xuelianglv/blog/item/cda76b2c52fbdded8a1399fe.html
    C库函数atoi的实现和一些讨论_c/c++_电脑编程网    http://blog.csdn.net/udknight/archive/2007/10/22/1836799.aspx   

你可能感兴趣的:(函数)