本文转自csdn博主v_JULY_v
字符串转整数基本思路:每扫描到一个字符,我们便把在之前得到的数字乘以10,然后再加上当前字符表示的数字
要求:不能用库函数atoi,此处相当于要求程序猿写一个实现atoi功能函数函数
需注意的细节:
- “由于整数可能不仅仅之含有数字,还有可能以'+'或者'-'开头,表示整数的正负。因此我们需要把这个字符串的第一个字符做特殊处理。如果第一个字符是'+'号,则不需要做任何操作;如果第一个字符是'-'号,则表明这个整数是个负数,在最后的时候我们要把得到的数值变成负数。
- 接着我们试着处理非法输入。由于输入的是指针,在使用指针之前,我们要做的第一件是判断这个指针是不是为空。如果试着去访问空指针,将不可避免地导致程序崩溃。
- 另外,输入的字符串中可能含有不是数字的字符。每当碰到这些非法的字符,我们就没有必要再继续转换。
- 最后一个需要考虑的问题是溢出问题。由于输入的数字是以字符串的形式输入,因此有可能输入一个很大的数字转换之后会超过能够表示的最大的整数而溢出。”
- 有2种溢出的情况:
- 一种是诸如2147483650,即n > MAX/10 的;
- 一种是诸如2147483649,即n == MAX/10 && c > MAX%10。
- 有2种溢出的情况:
比如,当给的字符串是如左边图片所示的时候,有考虑到么?当然,它们各自对应的正确输出如右边图片所示(
假定你是在32位系统下,且编译环境是VS2008以上):
优化好的代码 如下:
unsigned int为0 ~ 2^31-1 (2147483648),int为-2^31 ~ 2^31-1
- //copyright@njnu_mjn 2013
- int StrToDecInt(const char* str)
- {
- static const int MAX = (int)((unsigned)~0 >> 1); //2147483647
- static const int MIN = -(int)((unsigned)~0 >> 1) - 1; //-2147483649
- static const int MAX_DIV = (int)((unsigned)~0 >> 1) / 10; //214748364
- static const int MIN_DIV = (int)((((unsigned)~0 >> 1) + 1) / 10); //214748364
- static const int MAX_R = (int)((unsigned)~0 >> 1) % 10; //7
- static const int MIN_R = (int)((((unsigned)~0 >> 1) + 1) % 10); //8
- int n = 0;
- int sign = 1;
- int c;
- while (isspace(*str)) //检查空指针
- ++str;
- if (*str == '+' || *str == '-') //特殊处理第一个字符
- {
- if (*str == '-')
- sign = -1;
- ++str;
- }
- while (isdigit(*str)) //提前处理,避免溢出
- {
- c = *str - '0';
- if (sign > 0 && (n > MAX_DIV || (n == MAX_DIV && c >= MAX_R)))
- {
- n = MAX;
- break;
- }
- else if (sign < 0 && (n > MIN_DIV
- || (n == MIN_DIV && c >= MIN_R)))
- {
- n = MIN;
- break;
- }
- n = n * 10 + c;
- ++str;
- }
- return sign > 0 ? n : -n;
- }