atoi函数的自实现

(本片文章参考与借鉴了公众号编程珠玑关于atoi函数的文章,原文链接https://mp.weixin.qq.com/s/CBvdzYrjt81Ko_a1LROusw)
首先是百度百科关于atoi函数的介绍

atoi (表示 ascii to integer)是把字符串转换成整型数的一个函数,应用在计算机程序和办公软件中。int atoi(const char *nptr) 函数会扫描参数 nptr字符串,会跳过前面的空白字符(例如空格,tab缩进)等。

概括一下就是可以把一个字符串转换成相应的整型数,并且可以自动跳过字符串前面的空格

如“ 123”可以转换成123;

“-123”可以转换成-123;

“+123”可以转换成123;

下面是自己实现atoi函数的代码

我们需要考虑以下几种情况

  • 如果开头是负号,则标记为负数;正号或数值,则标记为正数
  • 跳过开头的空格,从第一个有效字符开始
  • 使用更大类型存储计算值,如果负数比INT_MIN还小或正数比INT_MAX还大,则表明溢出,返回INT_MIN或INT_MAX,或者在下次计算之前与INT_MIN/10或INT_MAX/10比较
  • 使用全局变量记录出错情况,区别正常转换为0或最大最小值
  • 遇到非数值时即退出
    (此处源码来自公众号编程珠玑,原文https://mp.weixin.qq.com/s/CBvdzYrjt81Ko_a1LROusw)
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>
#define NULL_PTR_ERR 1
#define ERANGE 2
int errCode = 0;
int my_atoi(char* str) {
    int negative = 0;
    char c = 0;
    /*计算结果存储*/
    long long ret = 0;
    errCode = 0;
    if(NULL == str)
    {
        errCode = NULL_PTR_ERR;
        return 0;
    }
    /*跳过开始的空格*/
    while(' ' == (*str))
        str++;
    /*跳过空格之后,到达了字符串结尾,则退出*/
    if(0 == *str)
        return 0;
    /*负数*/
    if(*str == '-' )
    {
        negative = 1;
        str++;
    }
    /*正数*/
    else if(*str == '+')
    {
        negative = 0;
        str++;
    }
    /*正数*/
    else if(isdigit(*str))
    {
        negative = 0;
    }
    /*如果不是以上内容,则直接退出*/
    else
    {
        return 0;
    }
    while(isdigit(*str))
    {
        /*计算结果*/
        ret = ret*10 + *str -'0';

        /*如果发现结果大于INT_MAX或者小于INT_MIN,则溢出,返回最值*/
        if(ret > (negative?-(long long )INT_MIN:INT_MAX))
        {
            /*溢出,返回最大值*/
            errCode = ERANGE;
            return negative?INT_MIN:INT_MAX;
        }
        str++;
    }
    /*根据正负号返回正确的结果*/
    return negative?-ret:ret;
}
int main(void)
{
    /*只有一个负号*/
    int result = my_atoi("-");
    printf("-:%d,errCode:%d\n\n",result,errCode);

    /*空指针*/
    result = my_atoi(NULL);
    printf("NULL:%d,errCode:%d\n\n",result,errCode);
    /*空字符串*/
    result = my_atoi("      ");
    printf("(empty string)     :%d,errCode:%d\n\n",result,errCode);

    /*负数*/
    result = my_atoi("-1");
    printf("-1:%d,errCode:%d\n\n",result,errCode);

    /*负数溢出*/
    result = my_atoi("   -11111111111");
    printf("   -11111111111:%d,errCode:%d\n\n",result,errCode);

    /*正数*/
    result = my_atoi("+123");
    printf("+123:%d,errCode:%d\n\n",result,errCode);

     /*正数溢出*/
    result = my_atoi("+123111111111111111");
    printf("+123111111111111111:%d,errCode:%d\n\n",result,errCode);

    /*字母开头*/
    result = my_atoi("a12345");
    printf("a12345:%d,errCode:%d\n\n",result,errCode);

    /*字母开头,字母空格混用*/
    result = my_atoi(" a b c 123d45");
    printf(" a b c 123d45:%d,errCode:%d\n\n",result,errCode);
    return 0;
}

运行结果如下
在这里插入图片描述

从结果上来看,好像能应对所有的状况了,但是没有办法应对开头字母的情况。

下面我自己稍微改进了一下代码使其适应开头字母空格混合情况

int my_atoi(char *str)
{
    int negative = 0;//0表示正数,1表示负数
    long long ret = 0;
    errCode = 0;
    //首先判断空
    if (str == NULL)
    {
        errCode = NULL_PTR_ERR;
        return 0;
    }
    //跳过空格--atoi只会跳过空格
    while(!isdigit(*str))
    {
        if('0' == *str)
        {
            return 0;
        }
        else if('-' == *str)
        {
            negative = 1;
            str++;
            break;
        }
        else if('+' == *str)
        {
            negative = 0;
            str++;
            break;
        }
        else if(isdigit(*str))
        {
            negative = 0;
            break;
        }
        else
        {
            str++;
        }
    }



    while(isdigit(*str))
    {
        //计算结果,*str - '0'是通过ASCII码计算相对应的数值
        ret = ret*10 + *str - '0';
        //如果发现结果大于INT_MAX或者小于INE_MIN,则溢出,返回最值
        if(ret >(negative?-(long long)INT_MIN:INT_MAX))
        {
            errCode = ERANGE;
            return negative?INT_MIN:INT_MAX;
        }
        str++;
    }
    return negative?-ret:ret;
}
int main(void)
{
    /*只有一个负号*/
    int result = my_atoi("-");
    printf("-:%d,errCode:%d\n\n",result,errCode);

    /*空指针*/
    result = my_atoi(NULL);
    printf("NULL:%d,errCode:%d\n\n",result,errCode);
    /*空字符串*/
    result = my_atoi("      ");
    printf("(empty string)     :%d,errCode:%d\n\n",result,errCode);

    /*负数*/
    result = my_atoi("-1");
    printf("-1:%d,errCode:%d\n\n",result,errCode);

    /*负数溢出*/
    result = my_atoi("   -11111111111");
    printf("   -11111111111:%d,errCode:%d\n\n",result,errCode);

    /*正数*/
    result = my_atoi("+123");
    printf("+123:%d,errCode:%d\n\n",result,errCode);

     /*正数溢出*/
    result = my_atoi("+123111111111111111");
    printf("+123111111111111111:%d,errCode:%d\n\n",result,errCode);

    /*字母开头*/
    result = my_atoi("a12345");
    printf("a12345:%d,errCode:%d\n\n",result,errCode);

    /*字母开头,字母空格混用*/
    result = my_atoi(" a b c 123d45");
    printf(" a b c 123d45:%d,errCode:%d\n\n",result,errCode);
    return 0;
}

上述代码会在一开始跳过所有的特殊字符(非‘+’、‘-’、十进制数值)

打印结果如下
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值