atoi()函数解析以及缺陷分析,以及对atoi()、atof()的改造

1、atoi()解析

atoi()原型: int atoi(const char *str );

函数功能:把字符串转换成整型数。

参数str:要进行转换的字符串

返回值:每个函数返回 int 值,此值由将输入字符作为数字解析而生成。 如果该输入无法转换为该类型的值,则atoi的返回值为 0。

工作原理:atoi通过全局变量来区分返回0的情况。
如果是非法输入,返回0,并把这个全局变量设为特殊标志;
如果输入是”0”,则返回0,不会设置全局变量。

注意:使用该函数时要注意atoi返回的是int类型,注意输入str的范围不要超出int类型的范围。

#include 
#include 
 
int main()
{
	int a;
 
	char *ptr1 = "3124";
	char *ptr2 = "0";
	char *ptr3 = "12.33";
	char *ptr4 = "-1245";
	char *ptr5 = "+21";
	char *ptr6 = "s3241";
 
	a = atoi(ptr1);
	printf("\"%s\"\t-> %d\n",ptr1, a);
 
	a = atoi(ptr2);
	printf("\"%s\"\t-> %d\n",ptr2, a);
 
	a = atoi(ptr3);
	printf("\"%s\"\t-> %d\n",ptr3, a);
 
	a = atoi(ptr4);
	printf("\"%s\"\t-> %d\n",ptr4, a);
 
	a = atoi(ptr5);
	printf("\"%s\"\t-> %d\n",ptr5, a);
 
	a = atoi(ptr6);
	printf("\"%s\"\t-> %d\n",ptr6, a);
 
	return 0;
}

打印如下:

"3124"     -> 3124
"0"           -> 0
"12.33"    -> 12
"-1245"    -> -1245
"+21"       -> 21
"s3241"    -> 0

2、atoi()函数缺陷分析

从上述打印能够看出来,要是首字母是非法字母,及无法转换的类型,是输出为0的。这可能会造成灾难性的结果,因为不知道输入的是0,字符串还是非法字符串。

解决方案:可以加一个传参(变量)和主函数中switch语句判断转化错误的原因。(更好的解决方案)

比如工控上钻头移动坐标(x,y,z)。x,y,z三个坐标是靠服务器下发下来,若程序错误,传入了一个错误的结果(s12,3,4)(以字符串形式下发),如果直接调用atoi,必然解析成(0,3,4),移动到了错误的位置!

当然可以对输入的字符串进行检查,可为啥不在atoi里面检查呢?

3、aioi()函数改造

/*
用法:将字符串里的数字字符转化为整形数。并返回处理的字符个数。
注意:转化时跳过前面的空格等空字符,直到遇上数字或正负符号才开始做转换,
而再遇到非数字或字符串结束标志('/0')才结束转换,并将结果返回。
目的是改造atoi函数
处理失败或者没有整型字符串则返回0,处理成功发回处理字符串的个数
*/
int CM_Atoi(char* source,int* integer)//为了在被调用函数中修改其无法直接访问的实参的值
{
	int offset1,offset2,num;
	int signedflag;//+为1 -为0
 
	if(source == NULL || *source == '\0' ||integer == NULL)
	{
		return 0;
	}
 
	offset1 = 0;//记录处理正负号的个数
	offset2 = 0;//记录处理数字的个数
	num = 0;
 
	while(*source > 0 && *source <= 32)//去除首部空格 \r \n \t \r 等异常字符,ASCII码值是32(含义为空格),ASCII码值是0(含义为空字符)。
	{
		source++;
		offset1++;
	}
 
	signedflag = 1;//默认为+
	if(*source == '+')
	{
		signedflag = 1;
		source++;
		offset1++;
	}
	else if(*source == '-')
	{
		signedflag = 0;
		source++;
		offset1++;
	}
 
	while(*source != '\0' && *source >= '0' && *source <= '9')
	{
		num = *source- '0' + num*10;
		source++;
		offset2++;
		if (num < 0)//整数溢出的情况,若溢出肯定变为负数
		{
			*integer = 0;
			return 0;
		}
	}
 
	if(signedflag == 0)
	{
		num = 0 - num;
	}
 
	if(offset2)
	{
		*integer = num;
		return offset1+offset2;
	}
	else
	{
		return 0;
	}
}

转发的整型已指针带入,返回转换的成功的字符串个数,应用层对CM_Atoi()函数返回值做检查,若返回为0,则比如转换失败,大于0,才成功转换成功。

4、atof()函数改造

同样方法对atof进行改造

/*
简单的x的y次幂
*/
long long pow1(int x,int y)
{
	long long num = 1;
	int i;
 
	for(i = 0; i < y; i++)
	{
		num = num*x;
	}
 
	return num;
}
 
/*
用法:将字符串里的数字字符转化为浮点型。并返回处理的字符个数。
注意:转化时跳过前面的空格等空字符,直到遇上数字或正负符号才开始做转换,
而再遇到非数字或字符串结束时('/0')才结束转换,并将结果返回。
目的是改造atof函数
处理失败或者没有浮点型字符串则返回0
支持正负号
*/
 
int CM_Atof(char* source,double* doubleing)
{
	int offset1,offset2,n;
	double num;
	int signedflag;//+为1 -为0
 
	if(source == NULL || *source == '\0' || doubleing == NULL)
	{
		return 0;
	}
 
	offset1 = 0;
	offset2 = 0;
	num = 0.0;
 
	while(*source > 0 && *source <= 32)//去除首部空格 \r \n \t \r 等异常字符,ASCII码值是32(含义为空格),ASCII码值是0(含义为空字符)。
	{
		source++;
		offset1++;
	}
 
	signedflag = 1;//默认为+
	if(*source == '+')
	{
		signedflag = 1;
		source++;
		offset1++;
	}
	else if(*source == '-')
	{
		signedflag = 0;
		source++;
		offset1++;
	}
 
 
	//整数部分
	while(*source != '\0' && *source >= '0' && *source <= '9')
	{
		num = *source- '0' + num*10.0;
		source++;
		offset2++;
		if (num < 0)//整数溢出的情况,若溢出肯定变为负数
		{
			*doubleing = 0;
			return 0;
		}
	}
 
	if(offset2 != 0 && *source == '.')
	{
		source++;
		offset2++;
 
		//小数部分
		n = 0;
		while(*source != '\0' && *source >= '0' && *source <= '9')
		{
			num = (*source- '0')*(1.0/pow1(10,++n)) + num;
			source++;
			offset2++;
		}
	}
 
	if(signedflag == 0)
	{
		num = -num;
	}
 
	if(offset2)
	{
		*doubleing = num;
		return offset1 + offset2;
	}
	else
	{
		return 0;
	}
}

————————————————
原文链接:https://blog.csdn.net/dingzj2000/article/details/89277497

你可能感兴趣的:(c语言,字符串)