求修正十六进制转十进制程序:需手动实现转换而非调用库函数
手动实现十六进制转十进制的修正方案
你的代码已经完成了输入验证和错误检查的部分,现在只需要替换掉strtoull库函数,用手动计算的方式实现十六进制到十进制的转换。下面是修正后的完整代码,以及关键逻辑的解释:
#include <stdlib.h> #include <stdio.h> #include <ctype.h> #include <limits.h> // 用于溢出检查,可选 #define SIZE 20 // 手动实现十六进制转十进制 unsigned long long hex_to_dec(const char *hex_str) { unsigned long long result = 0; // 跳过可选的0x或0X前缀 if (hex_str[0] == '0' && (hex_str[1] == 'x' || hex_str[1] == 'X')) { hex_str += 2; } while (*hex_str != '\0') { int digit; char c = *hex_str; if (isdigit(c)) { digit = c - '0'; } else if (isupper(c)) { digit = c - 'A' + 10; } else if (islower(c)) { digit = c - 'a' + 10; } else { // 理论上不会触发,因为前面已验证是合法十六进制字符 return 0; } // 可选:溢出检查,防止超出unsigned long long最大值 if (result > ULLONG_MAX / 16 || (result * 16 > ULLONG_MAX - digit)) { printf("警告:数值超出范围,可能溢出\n"); return ULLONG_MAX; } result = result * 16 + digit; hex_str++; } return result; } int main(void) { system("chcp 1251"); char str[SIZE][SIZE], (*pstr)[SIZE]; pstr = str; char* pcode; int kst; printf("请输入要转换的十六进制数的行数:"); scanf_s("%d", &kst); getchar(); while (kst > SIZE) { printf("超出允许范围(行数必须小于20):"); scanf_s("%d", &kst); getchar(); } while (kst < 1) { printf("输入的数值太小,请输入1到20之间的数:"); scanf_s("%d", &kst); getchar(); } printf("\n请输入十六进制数:\n\n"); while (pstr < str + kst) { gets_s(*pstr); // 验证是否为合法十六进制字符 int is_valid = 1; for (pcode = *pstr; *pcode != '\0'; pcode++) { if (!isxdigit((unsigned char)*pcode)) { **pstr = '\0'; // 标记为无效输入 is_valid = 0; break; } } pstr++; } printf("\n转换结果\n"); unsigned long long decimal; for (pstr = str; pstr < str + kst; pstr++) { if (**pstr == '\0') { printf("十六进制:输入错误!\n"); } else { decimal = hex_to_dec(*pstr); printf("十六进制:%#020llx | 十进制:%llu\n", decimal, decimal); } } return 0; }
关键逻辑说明
hex_to_dec函数核心:- 先处理十六进制的
0x/0X前缀,兼容带前缀的输入格式 - 逐个字符映射:将字符转换为0-15的数值(数字直接转,字母按大小写对应10-15)
- 累加计算:通过
result = result * 16 + digit实现转换——十六进制每一位的权重是前一位的16倍,比如0x1A就是1*16 + 10 = 26 - 可选溢出检查:避免数值超出
unsigned long long的存储范围
- 先处理十六进制的
原代码的保留与优化:
- 保留了你原本的输入行数验证、十六进制字符合法性检查逻辑
- 把模糊的
isXDigit变量替换为更清晰的is_valid,明确标记无效输入
注意事项
- 如果输入的十六进制数超过
unsigned long long的最大值(0xFFFFFFFFFFFFFFFF),会触发溢出警告,新手可以暂时注释掉溢出检查部分,先专注于转换逻辑的理解 - 代码中使用的
scanf_s和gets_s是微软编译器的安全输入函数,若使用GCC等编译器,可替换为scanf和fgets(注意fgets会读取换行符,需额外处理)
内容的提问来源于stack exchange,提问作者dan1chX
相关产品推荐
相关产品推荐

