«

C语言如何实现将字符串转换成整数

时间:2024-6-10 11:15     作者:韩俊     分类: Java


本文小编为大家详细介绍“C语言如何实现将字符串转换成整数”,内容详细,步骤清晰,细节处理妥当,希望这篇“C语言如何实现将字符串转换成整数”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

这是一个很有意思的问题。请不要把这个问题想的太简单了,考虑问题时应该尽可能的全面一些。请先思考并且实现这个函数,再来看讲解。

分析一下:函数名是StrToInt,那么可以这么调用:

int ret = StrToInt("1234");
printf("%d
", ret);

如果你写的程序能够正确输出1234,然后就觉得这道题就这样了,那么考虑的就不够全面。有没有一种可能:

1.传参时传了NULL指针。

2.传入空字符串。

3.字符串前面有空格,如:" 1234"。

4.有正负号,如:“-1234”。

5.有非法字符,如:“1234abcd”。

6.数字太大了,超出了int的存储范围,如:“1111111111111111111111111111111111111”。

下面我们一个一个解决。

准备工作

由于有可能出现非法字符,或者空字符串等,会有一些情况的转换是非法的。所以,定义一个全局性质的枚举类型来检验转换是否合法:

enum State
{
    VALID,
    INVALID
}s = INVALID;

默认的情况是非法的,只有转换成功才会把s的值置为VALID。

先把函数的框架撘出来:

int StrToInt(const char* str)
{

}

接下来开始解决以下问题:

1.NULL指针

NULL指针是不能解引用的!所以最好断言一下。

int StrToInt(const char* str)
{
    // 如果str是NULL,不能对其解引用
    assert(str);

    return ret;
}

2.空字符串

如果一上来就遇到了’’,那么就是空字符串。

int StrToInt(const char* str)
{
    // 如果str是NULL,不能对其解引用
    assert(str);

    // 空字符串
    if (*str == '')
    {
        return 0;
    }
}

3.空格

接下来,有可能会遇到空格,使用isspace函数来判断,把空格跳过去。

int StrToInt(const char* str)
{
    // 如果str是NULL,不能对其解引用
    assert(str);

    // 空字符串
    if (*str == '')
    {
        return 0;
    }
    // 空格
    while (isspace(*str))
    {
        ++str;
    }
}

4.正负号

接下来有可能遇到正负号,用一个flag来保存。

int StrToInt(const char* str)
{
    // 如果str是NULL,不能对其解引用
    assert(str);

    // 空字符串
    if (*str == '')
    {
        return 0;
    }
    // 空格
    while (isspace(*str))
    {
        ++str;
    }
    // 正负号
    int flag = 1;
    if (*str == '+')
    {
        flag = 1;
        ++str;
    }
    else if (*str == '-')
    {
        flag = -1;
        ++str;
    }
}

5.非法字符

下面开始处理数字。但是,有可能会遇到非法字符,所以要先判断一下。

int StrToInt(const char* str)
{
    // 如果str是NULL,不能对其解引用
    assert(str);

    // 空字符串
    if (*str == '')
    {
        return 0;
    }
    // 空格
    while (isspace(*str))
    {
        ++str;
    }
    // 正负号
    int flag = 1;
    if (*str == '+')
    {
        flag = 1;
        ++str;
    }
    else if (*str == '-')
    {
        flag = -1;
        ++str;
    }

    // 处理数字
    while (*str)
    {
        if (isdigit(*str))
        {

        }
        else
        {
            return ret;
        }
    }
}

如何处理合法的数字呢?假设是1234,我们可以先定义一个ret,初始化成0。先拿到1,0*10+1,就得到了1。接着拿到2,1*10+2,就得到了12。再拿到3,12*10+3,就得到了123。最后拿到4,123*10+4,就得到了1234。以此类推。

每次ret = ret*10 + 拿到的数字就行了。但是“拿到的数字”是什么呢?就是*str-'0'。想象一下,'1'-'0'就是数字1,'6'-'0'就是数字6。两个字符相减就是对应的ASCII码相减。不过,拿到的数字得乘上flag再加上去,因为有可能是负数。

int StrToInt(const char* str)
{
    // 如果str是NULL,不能对其解引用
    assert(str);

    // 空字符串
    if (*str == '')
    {
        return 0;
    }
    // 空格
    while (isspace(*str))
    {
        ++str;
    }
    // 正负号
    int flag = 1;
    if (*str == '+')
    {
        flag = 1;
        ++str;
    }
    else if (*str == '-')
    {
        flag = -1;
        ++str;
    }

    // 处理数字
    int ret = 0;
    while (*str)
    {
        if (isdigit(*str))
        {
            ret = ret * 10 + flag * (*str - '0');
            ++str;
        }
        else
        {
            return ret;
        }
    }

    s = VALID;
    return (int)ret;
}

6.越界

这就完了吗?还有一种情况,假设传入的数字过大或过小,导致超出了int的存储范围,此时的转换也是非法的。判断方法,就是用更大的类型,如long long来存储,如果超出了int的存储范围(ret>INT_MAX || ret<INT_MIN),但是不会超出long long的存储范围,就能够识别什么时候越界了。

int StrToInt(const char* str)
{
    // 如果str是NULL,不能对其解引用
    assert(str);

    // 空字符串
    if (*str == '')
    {
        return 0;
    }
    // 空格
    while (isspace(*str))
    {
        ++str;
    }
    // 正负号
    int flag = 1;
    if (*str == '+')
    {
        flag = 1;
        ++str;
    }
    else if (*str == '-')
    {
        flag = -1;
        ++str;
    }

    // 处理数字
    long long ret = 0;
    while (*str)
    {
        if (isdigit(*str))
        {
            ret = ret * 10 + flag * (*str - '0');
            // 判断有没有超过int的存储范围
            if (ret > INT_MAX || ret < INT_MIN)
            {
                return (int)ret;
            }
            else
            {
                ++str;
            }
        }
        else
        {
            return (int)ret;
        }
    } // end of while

    s = VALID;
    return (int)ret;
}

最后如果转换成功,就把s置成VALID,再返回ret即可。注意ret是long long类型,但是返回类型是int,所以需要强制类型转换。

测试

完整的测试代码如下:

#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <limits.h>

enum State
{
    VALID,
    INVALID
}s = INVALID;

int StrToInt(const char* str)
{
    // 如果str是NULL,不能对其解引用
    assert(str);

    // 空字符串
    if (*str == '')
    {
        return 0;
    }
    // 空格
    while (isspace(*str))
    {
        ++str;
    }
    // 正负号
    int flag = 1;
    if (*str == '+')
    {
        flag = 1;
        ++str;
    }
    else if (*str == '-')
    {
        flag = -1;
        ++str;
    }

    // 处理数字
    long long ret = 0;
    while (*str)
    {
        if (isdigit(*str))
        {
            ret = ret * 10 + flag * (*str - '0');
            // 判断有没有超过int的存储范围
            if (ret > INT_MAX || ret < INT_MIN)
            {
                return (int)ret;
            }
            else
            {
                ++str;
            }
        }
        else
        {
            return (int)ret;
        }
    } // end of while

    s = VALID;
    return (int)ret;
}

int main()
{
    int ret = StrToInt("      -1234");
    if (s == VALID)
    {
        printf("转换成功:%d
", ret);
    }
    else
    {
        printf("转换失败:%d
", ret);
    }

    return 0;
}

输出结果:

标签: java

热门推荐