或许一听到这个问题,很多人可能会说:这很简单呀,可是我用自己做了实验,结果战况惨烈,下面是我从看到这道题到最终考虑各种条件后所写程序的历程,希望可以对你有一点启示。
一开始我的思路是:要将一个字符串转换为整数
❶ 首先判断字符串的第一个字符,是‘+’或者‘-’,定义一个变量来表示转换出来后整数的正负,如果第一个字符既不是‘+’也不是‘-’,那么就默认是正数。
❷接下来判断下一个字符,看是否在‘0’到‘9’的范围内,如果在,那么就累加到sum中,如果不是数字字符,那么就直接返回,这时说明出现了非法字符,即就是不能转化为数字的字符,那么就认为这个字符串无效,不能转换。
下面是第一次写的代码:
int strToInt(const char *str)
{
assert(str);
const char *newStr = str;
int sum = 0;
int s = 1;
if (*newStr == '+')
{
newStr++;
}
else if (*newStr == '-')
{
newStr++;
s = -1;
}
while (*newStr != '\0')
{
if (*newStr >= '0' && *newStr <= '9')
{
sum = sum * 10 + (*newStr - '0') * s;
}
else
{
return 0;
}
newStr++;
}
return sum;
}
❶ 没有考虑如果字符串是“0”,那么最终返回的0到底是转换后的0还是因为字符串中有非法字符而返回的。
❷没有考虑溢出问题
❸对于非法的返回值应该考虑最终如何检测返回值是有效的还是无效的。
下面是看过《剑指offer》后做的修改:
对于返回值:可以使用全局变量来表示,如果是非法字符,那么就给全局变量置数(表示非法数),如果是合法字符,那么就不修改全局变量的值。最终如果结果为0,那么就检查全局变量的值来判断。
对于溢出问题:
在32位的平台下int占4个字节,所以整型的最大数为0x7fff ffff ,最小数为0x8000 0000,这里需注意,应该将最小数强转为 int 类型,不然可能因为编译器的不同而出现错误。
#pragma warning (disable : 4996)
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
enum status
{
kValid,
kInValid,
};
int g_Status = kValid;//定义全局变量作为参数是否有效的标志
//1.非法字符
//2.溢出问题
int StrToInt(const char *str)
{
int s = 1;
assert(str);
const char *newStr = str;
g_Status = kInValid;
long long sum = 0;
if (*newStr == '+')
{
newStr++;
}
else if (*newStr == '-')
{
newStr++;
s = -1;
}
while (*newStr != '\0')
{
if (*newStr >= '0' && *newStr <= '9')
{
sum = sum * 10 + (*newStr - '0') * s;
if ((s == 1) && (sum >= 0x7fffffff) || (s == -1) && (sum <= (int)0x80000000))
{
return 0;
}
}
else
{
return 0;
}
newStr++;
}
if (*newStr == '\0')
{
g_Status = kValid;
return sum;
}
}
int main()
{
const char *str = "-278";
int ret = StrToInt(str);
if ((ret == 0) && (g_Status == kInValid))
{
printf("转换的字符串无效\n");
}
else
{
printf("data : %d\n",ret);
}
system("pause");
return 0;
}
还应该注意的是:这并不是模拟atoi函数,虽然接近atoi函数的功能,但是也有一些区别,例如,对于atoi函数,如果字符串的第一个字符为空格,那么就跳过这个字符,继续处理后面的字符,但是在字符串内部,数字字符必须是连续的,如果出现这样的字符串,例如“156aa86”,那么atoi函数只处理前面的156,并且返回这个值,后面的字符则不处理。所以将上面的程序稍微修改就可以得到模拟atoi的函数,在遇到非法字符时,就将当前的sum返回即可。
有什么问题还望大家多多指正,共同学习,共同成长。