字符串转换为整数,相关问题探讨

来源:互联网 发布:小米wifi mac 编辑:程序博客网 时间:2024/06/11 13:19

问题:输入一串数字字符串,经过转换输出为整数,例如“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     16int       32  通常同具体的机器长度相同long      32float     32double    64

变量的范围(VC6环境下)

signed char             -128~127unsigned char           0~255signed short            -32768~32767unsigned short          0~0xffffsigned int              (-2147483647 - 1)~2147483647unsigned int            0~0xffffffffsigned long             (-2147483647L - 1)~2147483647unsigned long           0~0xffffffffULfloat                   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;}

这里写图片描述

0 0
原创粉丝点击