C语言经典练习:十六进制字符串转整数问题
先来看一个经典的C语言练习题:编写一个函数htoi(s),将包含十六进制数字的字符串(允许带有可选的0x或0X前缀)转换为对应的十进制整数值。字符串中可能出现的合法字符包括0-9、A-F和a-f。看似简单,但实际处理时涉及前缀识别、字符有效性验证以及位权计算等细节,值得深入推敲。

分步拆解程序功能模块
整个程序可以拆分为几个独立的功能模块:
- 主函数
main负责获取用户输入,并循环调用转换函数完成多次转换; - 输入函数
get_line(注意命名规范,因为标准库stdio.h中已存在getline,此处不能直接使用)用于读取一行输入字符串; - 核心函数
htoi是整个程序的关键,负责将十六进制字符串转化为十进制整数。
完整代码实现与算法解析
下面给出完整的实现代码,并附上必要的注释帮助理解。算法逻辑非常直观:例如输入0x32,结果等于 3 × 16¹ + 2 × 16⁰,只需从字符串尾部往前逐位计算即可。
#include
#define LINE 1000 // 每行接收的最大字符数
#define DEC 10 // 数字10
#define HEX 16 // 数字16
int get_line(char s[]);
int htoi(char s[]);
int main() {
char line[LINE];
int len;
int dec;
while ((len = get_line(line)) > 0) {
printf("Hex is: %s\n", line);
dec = htoi(line);
printf("Dec is: %d\n", dec);
}
return 0;
}
// 接收每次输入的字符,并返回长度
int get_line(char s[]) {
int i;
char c;
for (i = 0; i < LINE - 1 && (c = getchar()) != EOF && c != '\n'; i++) {
s[i] = c;
}
s[i] = '\0';
return i;
}
/*
* 十六进制字符串转为十进制整数
* 算法描述:例如输入字符串 "0x32",那么 result = 3 * 16^1 + 2 * 16^0
*/
int htoi(char s[]) {
int dec, len, i, n, j, ji, k;
len = 0;
dec = 0;
while (s[len] != '\0') {
len++; // 获取字符串长度
}
j = 0;
for (i = len - 1; i >= 2; i--) { // 从最后一位往前,跳过前两个字符("0x")
// 处理不同字符
if (s[i] >= '0' && s[i] <= '9') {
n = s[i] - '0';
} else if (s[i] >= 'a' && s[i] <= 'f') {
n = s[i] - 'a' + DEC;
} else if (s[i] >= 'A' && s[i] <= 'F') {
n = s[i] - 'A' + DEC;
}
ji = 1;
if (j == 0) {
ji = 1;
} else {
k = j;
while (k > 0) {
ji = ji * HEX;
k--;
}
}
j++;
dec = dec + ji * n;
}
return dec;
}
代码中htoi函数从字符串尾部开始逐位计算,变量j记录当前位数(0表示个位,1表示十六位,以此类推),每次循环更新位权ji并累加结果。需要特别注意的是,循环从下标len-1开始,直到下标2结束,目的是跳过开头的0x或0X两个字符。这种实现思路清晰可靠,非常适合初学者理解十六进制转十进制的底层原理和位权计算方法。
