十六进制转十进制 c语言函数

99ANYc3cd6
预计阅读时长 23 分钟
位置: 首页 C语言 正文

使用标准库函数 strtol (最推荐)

这是最标准、最安全、也是最推荐的方法。strtol (string to long) 函数可以将一个字符串转换为长整型,并可以自动处理不同进制(包括十六进制)。

函数原型

long strtol(const char *str, char **endptr, int base);

参数说明

  • str: 要转换的字符串指针。
  • endptr: 一个指向 char* 类型的指针,转换完成后,*endptr 会指向第一个未能被转换的字符,如果这个参数是 NULL,则不使用它。
  • base: 转换的基数(进制)。base 是 0,函数会根据字符串的前缀来判断进制:
    • "0x""0X" 开头:十六进制
    • "0" 开头:八进制
    • 其他情况:十进制 base 是 16,则直接按十六进制转换,并且可以不要求字符串必须有 "0x" 前缀。

返回值

  • 成功时,返回转换后的长整型值。
  • 如果转换后的值超出 long 类型的表示范围,函数会返回 LONG_MAXLONG_MIN,并设置全局变量 errnoERANGE
  • 如果第一个字符就不能转换,函数返回 0。

示例代码

#include <stdio.h>
#include <stdlib.h> // 包含 strtol 的头文件
#include <errno.h>  // 包含 errno 的头文件
#include <limits.h> // 包含 LONG_MAX 的头文件
// 使用 strtol 函数进行十六进制转十进制的函数
long hex_to_dec_strtol(const char *hex_str) {
    char *endptr; // 用于检查转换是否完全成功
    long decimal_value;
    // 设置 errno 为 0,以便检测溢出
    errno = 0;
    // 调用 strtol,base设为16表示十六进制
    decimal_value = strtol(hex_str, &endptr, 16);
    // 错误处理
    if (errno == ERANGE) {
        // 转换后的值超出 long 范围
        printf("错误:数值超出范围!\n");
        return -1; // 或者返回 LONG_MAX/LONG_MIN
    } else if (endptr == hex_str) {
        // 没有字符被转换,说明输入无效
        printf("错误:无效的十六进制输入!\n");
        return -1;
    } else if (*endptr != '\0') {
        // 字符串末尾还有未转换的字符("1A2G" 中的 'G')
        printf("警告:字符串中存在非十六进制字符 '%c',已忽略,\n", *endptr);
    }
    return decimal_value;
}
int main() {
    const char *hex_num1 = "1A";      // 26
    const char *hex_num2 = "FF";      // 255
    const char *hex_num3 = "0x7FFFFFFF"; // 2147483647 (32位系统上的 LONG_MAX)
    const char *hex_num4 = "GHI";     // 无效输入
    const char *hex_num5 = "123abc";  // 可以不带 0x 前缀
    printf("字符串 \"%s\" 转换为十进制是: %ld\n", hex_num1, hex_to_dec_strtol(hex_num1));
    printf("字符串 \"%s\" 转换为十进制是: %ld\n", hex_num2, hex_to_dec_strtol(hex_num2));
    printf("字符串 \"%s\" 转换为十进制是: %ld\n", hex_num3, hex_to_dec_strtol(hex_num3));
    printf("字符串 \"%s\" 转换为十进制是: %ld\n", hex_num4, hex_to_dec_strtol(hex_num4));
    printf("字符串 \"%s\" 转换为十进制是: %ld\n", hex_num5, hex_to_dec_strtol(hex_num5));
    return 0;
}

手动实现算法 (适合学习和面试)

如果你需要自己实现这个转换逻辑,或者想了解其背后的原理,可以手动编写一个函数,其核心思想是遍历字符串的每一个字符,根据其权重(16的幂次方)进行累加。

算法步骤

  1. 初始化一个结果变量 result 为 0。
  2. 遍历字符串中的每一个字符,直到遇到字符串结束符 \0
  3. 对于每个字符,检查它是否是一个有效的十六进制字符(0-9, a-f, A-F)。
  4. 如果字符是 '0''9',其值为 字符 - '0'
  5. 如果字符是 'a''f',其值为 字符 - 'a' + 10
  6. 如果字符是 'A''F',其值为 字符 - 'A' + 10
  7. 如果字符无效,可以报错或停止转换。
  8. 更新 result 的值:result = result * 16 + current_char_value
  9. 返回最终的 result

示例代码

#include <stdio.h>
#include <ctype.h> // 包含 isxdigit, toupper 等函数
// 手动实现的十六进制转十进制函数
// 返回 int 类型,假设输入是有效的且在 int 范围内
int hex_to_dec_manual(const char *hex_str) {
    int result = 0;
    int i = 0;
    // 跳过可选的 "0x" 或 "0X" 前缀
    if (hex_str[0] == '0' && (hex_str[1] == 'x' || hex_str[1] == 'X')) {
        i = 2;
    }
    // 遍历字符串的其余部分
    while (hex_str[i] != '\0') {
        char c = toupper(hex_str[i]); // 统一转换为大写,方便处理
        int value;
        if (c >= '0' && c <= '9') {
            value = c - '0';
        } else if (c >= 'A' && c <= 'F') {
            value = 10 + (c - 'A');
        } else {
            // 遇到非法字符,打印错误并停止转换
            printf("错误:非法的十六进制字符 '%c'\n", hex_str[i]);
            return -1; // 返回错误码
        }
        result = result * 16 + value;
        i++;
    }
    return result;
}
int main() {
    const char *hex_num1 = "1A";      // 26
    const char *hex_num2 = "FF";      // 255
    const char *hex_num3 = "0x7F";    // 127
    const char *hex_num4 = "123abc";  // 1194684
    printf("字符串 \"%s\" 转换为十进制是: %d\n", hex_num1, hex_to_dec_manual(hex_num1));
    printf("字符串 \"%s\" 转换为十进制是: %d\n", hex_num2, hex_to_dec_manual(hex_num2));
    printf("字符串 \"%s\" 转换为十进制是: %d\n", hex_num3, hex_to_dec_manual(hex_num3));
    printf("字符串 \"%s\" 转换为十进制是: %d\n", hex_num4, hex_to_dec_manual(hex_num4));
    return 0;
}

使用 sscanf (简单直接)

sscanf 是一个强大的格式化输入函数,可以从字符串中读取格式化数据,你也可以用它来转换进制。

函数原型

int sscanf(const char *str, const char *format, ...);

示例代码

#include <stdio.h>
// 使用 sscanf 函数进行转换
int hex_to_dec_sscanf(const char *hex_str) {
    int decimal_value;
    // %x 是 sscanf 中用于读取十六进制数的格式说明符
    // sscanf 会尝试从 hex_str 中读取一个十六进制数存入 decimal_value
    // 返回成功赋值的字段数量,成功应该是 1
    int items_read = sscanf(hex_str, "%x", &decimal_value);
    if (items_read != 1) {
        printf("错误:无效的十六进制输入!\n");
        return -1;
    }
    return decimal_value;
}
int main() {
    const char *hex_num1 = "1A";      // 26
    const char *hex_num2 = "FF";      // 255
    const char *hex_num3 = "0x7F";    // 127 (sscanf 的 %x 能自动识别 0x 前缀)
    const char *hex_num4 = "GHI";     // 无效输入
    printf("字符串 \"%s\" 转换为十进制是: %d\n", hex_num1, hex_to_dec_sscanf(hex_num1));
    printf("字符串 \"%s\" 转换为十进制是: %d\n", hex_num2, hex_to_dec_sscanf(hex_num2));
    printf("字符串 \"%s\" 转换为十进制是: %d\n", hex_num3, hex_to_dec_sscanf(hex_num3));
    printf("字符串 \"%s\" 转换为十进制是: %d\n", hex_num4, hex_to_dec_sscanf(hex_num4));
    return 0;
}

总结与对比

方法 优点 缺点 适用场景
strtol 最安全、最灵活,能处理溢出、无效字符、前缀,错误处理机制完善。 语法稍复杂,需要理解 endptrerrno 生产环境、健壮的程序、库函数的首选。
手动实现 易于理解,能深入掌握转换原理,不依赖任何库函数。 代码量多,需要自己处理所有边界情况(如前缀、非法字符、溢出等),容易出错。 学习、算法练习、面试
sscanf 代码简洁,一行代码即可完成转换。 错误处理能力较弱,无法像 strtol 那样精确地知道哪里出了问题,对输入格式的要求可能更严格。 快速原型开发、输入格式确定且简单的场景。

对于绝大多数实际应用,请优先使用 方法一 (strtol),它是最专业、最安全的选择,手动实现的方法虽然不推荐用于生产代码,但对于学习和理解底层原理非常有帮助。sscanf 是一个方便的工具,但在需要严格错误验证的场合,strtol 更胜一筹。

-- 展开阅读全文 --
头像
c程序设计语言第2版 pdf哪里能免费下载?
« 上一篇 02-12
织梦网站install步骤如何正确操作?
下一篇 » 02-12

相关文章

取消
微信二维码
支付宝二维码

目录[+]