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实现。
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
本文详细解析了atoi函数的工作原理,提供了一种基于状态机的atoi函数实现方式,该实现能够有效处理数值溢出等问题。

2909

被折叠的 条评论
为什么被折叠?



