C语言提取字符串数字求和时atoi使用异常问题排查
问题背景
需求为C语言场景下实现功能:接收用户键盘输入的字符串,提取字符串中所有数字字符对应的单个整数值并累加求和。例如输入字符串C35#37时,程序应计算3+5+3+7,最终输出结果18。
原实现思路是通过strlen获取字符串长度,遍历每个下标位置,调用atoi完成字符转整数,原思路误以为非数字字符传入atoi会返回0,以此自动区分普通字符与数字,但程序运行结果不符合预期。
原问题代码如下:
#include<stdio.h> #include<string.h> #include<stdlib.h> int main(void) { char str[200]; int len, i,sum=0; fputs("문자열을 입력해 주세요: ",stdout); fgets(str,sizeof(str),stdin); len = strlen(str); for(i=0; i<len; i++) { sum= sum + atoi(&str[i]); } printf("%d",sum); return 0; }
异常运行结果:
- 输入
a12时,输出14(预期结果应为3) - 输入
123时,输出149(预期结果应为6)
错误原因
核心问题是对atoi函数的行为理解错误:
atoi的入参是C字符串(以'\0'结尾的字符序列)的起始地址,函数会从该地址开始连续读取字符,直到碰到非数字字符或字符串结束符,将读取到的连续数字序列转换为整数返回,并非只转换当前地址对应的单个字符。- 以输入
a12为例:- i=0时传入
&str[0],指向字符串"a12",开头为非数字,atoi返回0 - i=1时传入
&str[1],指向字符串"12",atoi读取连续数字1、2,返回12 - i=2时传入
&str[2],指向字符串"2",atoi返回2 - 累加结果0+12+2=14,和异常结果完全吻合
- i=0时传入
- 以输入
123为例:- i=0时传入
&str[0],指向"123",返回123 - i=1时传入
&str[1],指向"23",返回23 - i=2时传入
&str[2],指向"3",返回3 - 累加结果123+23+3=149,和第二个异常结果完全吻合
- i=0时传入
- 额外冗余问题:
fgets读取输入时会将用户输入的换行符\n存入字符串,原实现会遍历到这个换行符,虽然不会影响计算结果,但属于无意义操作。
修复方案
不需要使用atoi处理单个数字字符:C标准中规定数字字符'0'到'9'的ASCII值是连续递增的,单个数字字符减去'0'即可得到对应的整数值。遍历过程中只需要判断当前字符是否为数字字符,是就累加对应数值,非数字直接跳过即可。
修复后的代码:
#include<stdio.h> int main(void) { char str[200]; int i, sum = 0; fputs("문자열을 입력해 주세요: ", stdout); fgets(str, sizeof(str), stdin); for(i = 0; str[i] != '\0'; i++) { // 判断当前字符是否为数字 if(str[i] >= '0' && str[i] <= '9') { sum += str[i] - '0'; } } printf("%d\n", sum); return 0; }
修复后验证:
- 输入
C35#37,累加3+5+3+7=18,符合需求 - 输入
a12,累加1+2=3,结果正确 - 输入
123,累加1+2+3=6,结果正确
内容的提问来源于stack exchange,提问作者chobodark
相关产品推荐
相关产品推荐

