C程序设计语言习题2-3答案

作者:技术拾光时间:2026-06-11 06:35:13浏览:182

实现函数htoi将十六进制字符串(可含0x或0X前缀)转换为十进制整数。算法从字符串尾部逐位计算,跳过前两个前缀字符,按位权累加结果,输出对应的整数值。该函数支持大小写十六进制数字。

问题描述

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

C程序设计语言习题2-3答案

问题拆分

整个程序可以拆分为几个独立模块:

  • 主函数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 两个字符。这一思路清晰可靠,适合初学者理解十六进制到十进制的底层转换原理。