问题:输入一串数字字符串,经过转换输出为整数,例如“12345”,转换为12345。
分析如下:
1.确定扫描方向,从左至右
2.具体转换:a. 1 = 0*10+1,b. 12=1*10+2,…..如此循环
int str2int(const char* str)
{
int temp = 0;
while(*str != '\0')
{
temp = temp*10+(*str-'0');
++str;
}
return temp;
}
以上代码过于简陋,很多问题没有考虑到:
1.要确认字符串是否为空,assert(str != NULL)。
2.数字字符串正负问题,“-12345”和“12345”之间的区别。
3.要确认字符串是否为正确的数字字符串。
4.数字字符串过长,产生溢出的问题,又该如何处理。(重点)
下面逐个进行讨论:
1.是否为空,这个比较简单,上面已经说明,或者如下:
if (str == NULL)
{
printf("str error!\n");
return 0;
}
2.正负问题:
int signFlag = 1;
if (*str == '+')
{
signFlag = 1;
str++;
}
else if (*str == '-')
{
signFlag = -1;
str++;
}
3.是否为完整数字字符串:
if (*str < '0' || *str > '9')
{
printf("str Error!\n");
break;
}
4.溢出处理:
根据数据类型的大小,当输入的数字字符串转换为整数的值,超出了合理范围的上限,输出上限值,超出了合理范围下限,输出下限值。
以下为各数据类型大小的介绍:(来源网络)
变量的长度(VC6环境下)
char 8 (bit)
short 16
int 32 通常同具体的机器长度相同
long 32
float 32
double 64
变量的范围(VC6环境下)
signed char -128~127
unsigned char 0~255
signed short -32768~32767
unsigned short 0~0xffff
signed int (-2147483647 - 1)~2147483647
unsigned int 0~0xffffffff
signed long (-2147483647L - 1)~2147483647
unsigned long 0~0xffffffffUL
float 1.175494351e-38F/* min pos value */
3.402823466e+38F /* max value */
double 3.3621031431120935063e-4932L
1.189731495357231765e+4932L
我们以这个为例子:signed int (-2147483647 - 1)~2147483647
const int Max_int = (int)((unsigned int)~0>>1);
const int Min_int = -(int)((unsigned int)~0>>1)-1;
那么问题来了,我们该怎样去判断该数字字符串转换的整数是属于(-2147483647 - 1)~2147483647这个区间的呢?
那我们可以列出几个例子做出比较,“2147483647999”和2147483647,“2147483648“和2147483647,等等。这样的比较依旧无法进行,因为数据会溢出,溢出了就会存在错误的比较。
我们可以考虑降级比较,即把数据字符串和2147483647/10进行比较,就拿“2147483648“和2147483647进行分析。
1.当数据字符串为“214748364”时(即扫描到2147483648倒数第二位),214748364”和2147483647/10相等。
2.当数字字符串“2147483648“扫描到最后一位‘8’时,和2147483647%10的7就不相等。
根据这样的分析就可以得到以下实现代码:
if (signFlag == 1 && (n>Max_int/10 || (n==Max_int/10 && c>Max_int%10)))
{
n = Max_int;
break;
}
else if (signFlag == -1 && (n>(unsigned)Min_int/10 || (n == (unsigned)Min_int/10 && c>(unsigned)Min_int%10)))
{
n = Min_int;
break;
}
具体实现代码:
#include <iostream>
using namespace std;
const int Max_int = (int)((unsigned int)~0>>1);
const int Min_int = -(int)((unsigned int)~0>>1)-1;
int str2int(char* str)
{
//字符串判断
if (str == NULL)
{
printf("str error!\n");
return 0;
}
//符号处理
int signFlag = 1;
if (*str == '+')
{
signFlag = 1;
str++;
}
else if (*str == '-')
{
signFlag = -1;
str++;
}
int n = 0;
while (*str != '\0')//字符串遍历
{
if (*str < '0' || *str > '9')//数字字符串判断
{
printf("str Error!\n");
break;
}
//溢出处理
int c = *str - '0';
if (signFlag == 1 && (n>Max_int/10 || (n==Max_int/10 && c>Max_int%10)))
{
n = Max_int;
break;
}
else if (signFlag == -1 && (n>(unsigned)Min_int/10 || (n == (unsigned)Min_int/10 && c>(unsigned)Min_int%10)))
{
n = Min_int;
break;
}
//转换处理
n = n*10 + (*str - '0');
++str;
}
return signFlag>0?n:-n;
}
int main()
{
char *strdata0 = "-123456789987654321";
char *strdata1 = "123456789987654321";
char *strdata2 = "-12345678";
char *strdata3 = "12345678";
char *strdata4 = "1234k678";
int temp =str2int(strdata0);
printf("\"-123456789987654321\"输出为:%d\n",temp);
temp =str2int(strdata1);
printf("\"123456789987654321\"输出为:%d\n",temp);
temp =str2int(strdata2);
printf("\"-12345678\"输出为:%d\n",temp);
temp =str2int(strdata3);
printf("\"12345678\"输出为:%d\n",temp);
temp =str2int(strdata4);
printf("\"1234k678\"输出为:%d\n",temp);
system("pause");
return 0;
}
1263

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



