函数实现-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   

posted @ 2011-06-17 18:20  xiaodongrush  阅读(9204)  评论(3编辑  收藏  举报