C语言m进制转十进制程序for循环末轮取整串而非单字符问题求解
问题触发原因
- 核心问题出在数字字符转数位的逻辑上:代码中
else分支使用sscanf(&str[i], "%d", &digit)读取数位,%d格式化符的规则是从传入的起始地址开始,读取所有连续的数字字符直到遇到非数字字符才停止,而非仅读取单个字符。 - 以输入字符串
"100"为例,循环执行到i=0时,&str[0]就是整个字符串的首地址,sscanf会把连续的三个数字字符1、0、0整体转换成整数100赋值给digit,就出现了将整个数字当作单个数位计算的问题。 - 额外隐藏问题:
pow函数返回值是浮点数,多次计算后可能出现精度误差,导致最终十进制结果偏差。
修复方案
- 替换数字字符转数位的逻辑,直接通过ASCII码差值计算单个数字字符对应的数值:
digit = str[i] - '0',因为ASCII编码中数字字符'0'到'9'是连续排列的,单个字符减去'0'即可得到对应的0-9的整数值,不会读取后续字符。 - (可选优化)替换
pow浮点数计算逻辑,改用整数累乘的方式计算,避免精度问题,执行效率也更高。
基础修复版代码(仅修复核心bug,保留原有循环逻辑)
#include <stdio.h> #include <string.h> #include <ctype.h> #include <math.h> int main(){ int m = 0; char str[100]; scanf("%d\n%s", &m, str); int length = strlen(str); int number = 0; int power = 0; for (int i = length-1; i >= 0; i--){ int digit = 0; if (isalpha(str[i])){ // 增加toupper兼容小写字母输入 switch(toupper(str[i])){ case 'A': digit = 10;break; case 'B': digit = 11;break; case 'C': digit = 12;break; case 'D': digit = 13;break; case 'E': digit = 14;break; case 'F': digit = 15; } } else{ // 替换原sscanf逻辑 digit = str[i] - '0'; } number += digit * pow((double)m, (double)power); power++; } printf("%d\n", number); return 0; }
优化版代码(无浮点数精度问题,效率更高)
#include <stdio.h> #include <string.h> #include <ctype.h> int main(){ int m = 0; char str[100]; scanf("%d\n%s", &m, str); int length = strlen(str); int number = 0; for (int i = 0; i < length; i++){ int digit = 0; if (isalpha(str[i])){ switch(toupper(str[i])){ case 'A': digit = 10;break; case 'B': digit = 11;break; case 'C': digit = 12;break; case 'D': digit = 13;break; case 'E': digit = 14;break; case 'F': digit = 15; } } else{ digit = str[i] - '0'; } // 整数累乘逻辑,无需pow计算 number = number * m + digit; } printf("%d\n", number); return 0; }
内容的提问来源于stack exchange,提问作者Вова Шевчук
相关产品推荐
相关产品推荐

