将字符串转换为数字(a_to_i)

字符串转整数atoi实现
本文探讨了如何实现一个更完善的atoi函数,该函数能够处理包含各种非数字字符的字符串,并能正确解析正负号、十六进制和八进制数字。

大部分人看到这样的题目,觉得很简单,很多人就会写出如下程序:

int My_atoi(const char* str)
{
    int val = 0;
    while(*str != '\0')
    {
        val = val * 10 + *str - '0';
        str++;
    }
    return val;
}

这个程序是没有问题的,但是这只适用于一小部分情况,就是字符串全部是数字,且转换后的数字不会超出整型int的范围,显然这考虑不够全面。

例如:给定一些字符串“a1345676”,“   123456”,“*#3456”,“876#8*74”,“-34567”,“+234.5”,“0x12346”,“03456”,“12345678909876543”,“-2345678987652”......

从这些字符串中可以看出,将一个字符串转换成数字还需要考虑很多方面:字符串以字母、空格、其他符号开始的情况怎么处理?字符串中间夹杂着非数字符号怎么处理?字符串以正负号开始的情况怎么处理?若字符串以“0x”或“0”开始,如何判断并将之转换为十六进制或八进制?若转换后的数字超出整型类型所能表示的范围怎么处理?

若给定的字符串是以非数字的其他字符开始,就需要将这些字符都删除或者跳过,直到遇到可以转换的数字字符;

若给定的字符串以正负号开始,则需要将正负号做个标记,然后按照正数来处理,返回结果是根据标记将结果值做符号的变化;

若给定的字符串中间夹杂着非数字字符,那么当遇到第一个非数字字符,程序就会结束,后面的所有字符便不会再做转换;

若给定的字符串以“0x”/“0X”或者“0”开始,那么就说明这是一个十六进制数字或者八进制数字,需要将它的十六进制或八进制形式转换过来,再将它转换成对应的十进制数字的结果;

若给定的字符串转换成数字以后,超出了整型所表示的范围,可以用long long类型或者是无符号类型来进行判断(下面的代码中采用的是long long定义的方法),若超出最大值表示范围,则只输出最大值,若超出了最小值所表示的范围,则只输出最小值即可;

根据以上情况的解决方法,我们可以知道,转换函数开始就需要判断给定字符是以哪一种情况开始的,在做出相应的转换过程,而且,为了是程序看起来简洁明了,我们可以将转换成十进制、八进制、十六进制的情况单独封装成各自的函数,这样在转换的函数中就可以直接调用。

完整的代码实现如下图所示:

在 Lua 中,将**字符串转换数字**是一个常见操作。Lua 提供了多种方式来实现这一转换,主要依赖 `tonumber()` 函数,并支持自动类型转换。 --- ### ✅ 方法一:使用 `tonumber(str)` —— 标准转换函数 ```lua local str = "123" local num = tonumber(str) print(num) --> 123 (number 类型) print(type(num)) --> number ``` - 如果字符串是合法的数字格式(整数、小数、科学计数法),会成功转换。 - 如果无法转换,则返回 `nil`。 #### 示例: ```lua print(tonumber("456")) --> 456 print(tonumber("3.14")) --> 3.14 print(tonumber("1e5")) --> 100000.0 print(tonumber("abc")) --> nil print(tonumber("")) --> nil ``` --- ### ✅ 方法二:通过数学运算**隐式转换** Lua 在进行数学运算时会**自动尝试将字符串转为数字**: ```lua print("123" + 1) --> 124(字符串先转成数字) print("3.5" * 2) --> 7.0 print("10" - "3") --> 7 ``` > ⚠️ 注意:这种写法虽然方便,但若字符串非法会导致运行时错误: ```lua print("hello" + 1) --> 错误!attempt to perform arithmetic on a string value ``` --- ### ✅ 方法三:指定进制转换(`tonumber(str, base)`) `tonumber()` 还可以接收第二个参数,表示进制(2 到 36): ```lua print(tonumber("1010", 2)) --> 10(二进制转十进制) print(tonumber("FF", 16)) --> 255(十六进制) print(tonumber("12", 8)) --> 10(八进制) print(tonumber("xyz", 10)) --> nil(无效字符) ``` --- ### 🔍 安全转换建议(避免出错) 由于 `tonumber()` 可能返回 `nil`,建议加上判断: ```lua local str = "123abc" local num = tonumber(str) if num then print("转换成功:", num) else print("转换失败,不是有效数字") end ``` 或者写一个安全转换函数: ```lua function toNumberSafe(s, default) local n = tonumber(s) return n or default end print(toNumberSafe("42", 0)) --> 42 print(toNumberSafe("abc", 0)) --> 0 ``` --- ### ❌ 常见错误与注意事项 | 字符串 | 转换结果 | 说明 | |--------|----------|------| | `"123"` | ✅ 123 | 正常整数 | | `"3.14"` | ✅ 3.14 | 小数 | | `" 123 "` | ✅ 123 | 自动忽略前后空格 | | `"12a3"` | ❌ nil | 包含非数字字符 | | `"0xFF"` | ❌ nil(除非用 base=16) | 需显式指定进制 | > 📝 注:Lua 不支持像 `"0xFF"` 直接用 `tonumber("0xFF")` 转换,必须写成: ```lua tonumber("FF", 16) -- 正确 ``` ---
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值