C语言16进制转10进制如何实现?

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

使用C语言标准库函数 (推荐)

这是最简单、最直接、也是最安全的方法,C标准库提供了 strtol() 函数,可以将一个字符串形式的数字转换为指定进制的长整型(long)值。

strtol() 函数简介

long strtol(const char *str, char **endptr, int base);
  • str: 指向要转换的字符串的指针。
  • endptr: 指向一个 char* 类型的指针,函数执行后,*endptr 会指向转换过程中停止的位置,如果字符串中包含非数字字符,转换会在第一个非数字字符处停止,如果不需要这个功能,可以传入 NULL
  • base: 转换的基数(进制)。
    • base0,函数会自动判断字符串的进制:
      • 如果字符串以 0x0X 开头,则被当作16进制。
      • 如果字符串以 0 开头,则被当作8进制(或8/10进制,取决于编译器)。
      • 否则,被当作10进制。
    • base16,则明确将字符串当作16进制处理,这通常是我们的选择。
    • base 的取值范围是 2 到 36。

示例代码

#include <stdio.h>
#include <stdlib.h> // 必须包含此头文件才能使用 strtol
#include <string.h> // 用于 strlen
int main() {
    // 1. 使用字符串表示的16进制数
    const char *hex_str1 = "1A3F";       // 对应的10进制是 6719
    const char *hex_str2 = "0xFF";       // 对应的10进制是 255
    const char *hex_str3 = "0x7FFFFFFF"; // 对应的10进制是 2147483647 (32位int的最大值)
    char *endptr; // 用于存放转换结束后的位置
    // 使用 strtol 进行转换,base设为16表示明确是16进制
    long num1 = strtol(hex_str1, &endptr, 16);
    long num2 = strtol(hex_str2, &endptr, 16);
    long num3 = strtol(hex_str3, &endptr, 16);
    // 打印结果
    printf("字符串 \"%s\" 转换为10进制是: %ld\n", hex_str1, num1);
    printf("字符串 \"%s\" 转换为10进制是: %ld\n", hex_str2, num2);
    printf("字符串 \"%s\" 转换为10进制是: %ld\n", hex_str3, num3);
    // 2. 处理包含非法字符的字符串
    const char *hex_str4 = "1G5H"; // 'G'和'H'不是有效的16进制字符
    long num4 = strtol(hex_str4, &endptr, 16);
    // num4 会被成功转换到 'G' 出现之前,即 "1"
    // endptr 会指向 'G'
    printf("\n处理非法字符字符串 \"%s\":\n", hex_str4);
    printf("成功转换的部分是: %ld\n", num4);
    printf("转换停止的位置是: %c\n", *endptr); // 应该输出 'G'
    return 0;
}

编译与运行:

gcc hex_to_dec.c -o hex_to_dec
./hex_to_dec

输出结果:

字符串 "1A3F" 转换为10进制是: 6719
字符串 "0xFF" 转换为10进制是: 255
字符串 "0x7FFFFFFF" 转换为10进制是: 2147483647
处理非法字符字符串 "1G5H":
成功转换的部分是: 1
转换停止的位置是: G

手动编写转换算法

为了更好地理解转换的原理,我们可以自己实现一个转换函数,16进制转10进制的核心思想是按权展开求和

一个16进制数 dn dn-1 ... d2 d1 d0 的10进制值为: Value = dn * 16^n + dn-1 * 16^(n-1) + ... + d2 * 16^2 + d1 * 16^1 + d0 * 16^0

1A3F 的转换过程是: 1 * 16^3 + 10 * 16^2 + 3 * 16^1 + 15 * 16^0 = 1 * 4096 + 10 * 256 + 3 * 16 + 15 * 1 = 4096 + 2560 + 48 + 15 = 6719

我们可以用一个循环来实现这个过程,每次循环将当前的结果乘以16,然后加上新的数字位。

实现步骤

  1. 初始化一个 result 变量为0。
  2. 遍历16进制字符串的每一个字符。
  3. 对于每个字符,将其转换为对应的10进制数值('0'->0, '1'->1, ..., '9'->9, 'A'->10, 'B'->11, ..., 'F'->15, 'a'->10, 'b'->11, ..., 'f'->15)。
  4. 更新 resultresult = result * 16 + current_digit_value
  5. 循环结束后,result 就是最终的10进制值。

示例代码

#include <stdio.h>
#include <ctype.h> // 用于 isxdigit 和 toupper
// 手动实现16进制字符串转10进制长整型
long hexToDecManual(const char *hexStr) {
    long result = 0;
    if (hexStr == NULL) {
        return 0;
    }
    // 跳过可能的 "0x" 前缀
    if (hexStr[0] == '0' && (hexStr[1] == 'x' || hexStr[1] == 'X')) {
        hexStr += 2;
    }
    while (*hexStr != '\0') {
        char c = toupper(*hexStr); // 统一转换为大写,方便处理
        int digitValue = 0;
        if (c >= '0' && c <= '9') {
            digitValue = c - '0';
        } else if (c >= 'A' && c <= 'F') {
            digitValue = 10 + (c - 'A');
        } else {
            // 遇到非法字符,停止转换
            printf("警告: 遇到非法16进制字符 '%c',转换提前终止,\n", c);
            break;
        }
        result = result * 16 + digitValue;
        hexStr++;
    }
    return result;
}
int main() {
    const char *hex_str1 = "1A3F";
    const char *hex_str2 = "0xFF";
    const char *hex_str3 = "abc";
    const char *hex_str4 = "1G5H"; // 测试非法字符
    long num1 = hexToDecManual(hex_str1);
    long num2 = hexToDecManual(hex_str2);
    long num3 = hexToDecManual(hex_str3);
    long num4 = hexToDecManual(hex_str4);
    printf("手动转换:\n");
    printf("字符串 \"%s\" 转换为10进制是: %ld\n", hex_str1, num1);
    printf("字符串 \"%s\" 转换为10进制是: %ld\n", hex_str2, num2);
    printf("字符串 \"%s\" 转换为10进制是: %ld\n", hex_str3, num3);
    printf("字符串 \"%s\" 转换为10进制是: %ld\n", hex_str4, num4);
    return 0;
}

编译与运行:

gcc hex_to_dec_manual.c -o hex_to_dec_manual
./hex_to_dec_manual

输出结果:

手动转换:
字符串 "1A3F" 转换为10进制是: 6719
字符串 "0xFF" 转换为10进制是: 255
字符串 "abc" 转换为10进制是: 2748
警告: 遇到非法16进制字符 'G',转换提前终止。
字符串 "1G5H" 转换为10进制是: 27

注意,对于 "1G5H",我们的手动函数在遇到 'G' 时就停止了,所以结果是 "1" 的转换结果,即 1。


总结与对比

特性 方法一 (strtol) 方法二 (手动算法)
易用性 非常高,一行代码即可完成 较低,需要自己编写函数和逻辑
健壮性 ,能正确处理前缀 "0x",有错误检测机制 较低,需要自己处理前缀和错误
性能 通常是优化过的,性能很好 取决于实现,一般能满足需求
可读性 代码简洁,意图明确 需要理解算法才能看懂
适用场景 绝大多数情况下的首选,特别是处理用户输入或文件数据时 学习目的、面试考察、或者有特殊转换需求时

在实际开发中,强烈推荐使用方法一 strtol() 函数,它简单、可靠且是C语言标准的一部分,方法二则有助于深入理解16进制到10进制的转换原理,适合在学习和面试中展示你的编程基础。

-- 展开阅读全文 --
头像
dede 模板路径修改
« 上一篇 今天
织梦调用文章摘要标签
下一篇 » 今天
取消
微信二维码
支付宝二维码

目录[+]