C语言hex转ASCII如何实现?

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

“十六进制”和“ASCII”并不是两种可以直接相互转换的数据类型。

c语言hextoascii
(图片来源网络,侵删)
  • 十六进制:是一种数字的表示方法,它用16个符号(0-9, A-F)来表示数值,数字 255 用十进制表示,用十六进制表示就是 0xFF,它们都指向同一个数值。
  • ASCII:是一个字符编码标准,它规定了数字(0-255)与字符(如 'A', 'B', '1', '@')之间的对应关系。

我们通常所说的“十六进制转ASCII”,其实指的是以下两种常见的操作:

  1. 将一个十六进制字符串(如 "48656C6C6F")转换成一个ASCII字符串(如 "Hello")。 这是最常见的需求。
  2. 将一个十六进制数值(如 0x48)转换成它对应的ASCII字符(如 'H')。

下面我们分别对这两种操作进行详细的代码实现和解释。


十六进制字符串转ASCII字符串

这是最常见的场景,网络数据包、传感器数据、文件内容等常常以十六进制字符串的形式出现,我们需要将其转换成人类可读的文本。

核心思路

  1. 遍历输入的十六进制字符串,每两个字符(一个字节)组成一个十六进制数值。
  2. 将这个十六进制数值转换成对应的 char 类型(ASCII码)。
  3. 将转换后的 char 追加到结果字符串的末尾。
  4. 最后在结果字符串的末尾添加字符串结束符 \0

示例代码

这个函数会处理小写和大写的十六进制字符。

c语言hextoascii
(图片来源网络,侵删)
#include <stdio.h>
#include <string.h>
#include <ctype.h> // 用于 tolower 函数
/**
 * @brief 将十六进制字符串转换为ASCII字符串
 * 
 * @param hex_str 输入的十六进制字符串 ( "48656C6C6F")
 * @param ascii_str 输出的ASCII字符串缓冲区 ( "Hello")
 * @param ascii_buf_size 输出缓冲区的大小,防止溢出
 * @return int 成功转换的字符数,如果失败则返回 -1
 */
int hexstr_to_asciistr(const char* hex_str, char* ascii_str, size_t ascii_buf_size) {
    // 检查输入有效性
    if (hex_str == NULL || ascii_str == NULL || ascii_buf_size == 0) {
        return -1;
    }
    size_t hex_len = strlen(hex_str);
    size_t ascii_len = hex_len / 2;
    // 检查十六进制字符串长度是否为偶数,并且缓冲区是否足够大
    if (hex_len % 2 != 0 || ascii_len >= ascii_buf_size) {
        return -1;
    }
    for (size_t i = 0; i < hex_len; i += 2) {
        // 将两个十六进制字符转换为一个字节
        char high_nibble = tolower(hex_str[i]);
        char low_nibble = tolower(hex_str[i + 1]);
        // 检查字符是否为有效的十六进制字符
        if (!((high_nibble >= '0' && high_nibble <= '9') || (high_nibble >= 'a' && high_nibble <= 'f')) ||
            !((low_nibble >= '0' && low_nibble <= '9') || (low_nibble >= 'a' && low_nibble <= 'f'))) {
            return -1; // 遇到非法字符
        }
        // 将十六进制字符转换为数值
        // 'a' - 'a' + 10 = 10
        // '5' - '0' = 5
        int high_val = (high_nibble >= 'a') ? (high_nibble - 'a' + 10) : (high_nibble - '0');
        int low_val = (low_nibble >= 'a') ? (low_nibble - 'a' + 10) : (low_nibble - '0');
        // 组合成一个字节
        unsigned char byte = (high_val << 4) | low_val;
        // 将字节存入结果字符串
        ascii_str[i / 2] = byte;
    }
    // 添加字符串结束符
    ascii_str[ascii_len] = '\0';
    return (int)ascii_len;
}
int main() {
    const char* hex_input = "48656C6C6F20576F726C64"; // "Hello World"
    char ascii_output[50]; // 确保缓冲区足够大
    int result = hexstr_to_asciistr(hex_input, ascii_output, sizeof(ascii_output));
    if (result != -1) {
        printf("原始十六进制字符串: %s\n", hex_input);
        printf("转换后的ASCII字符串: %s\n", ascii_output);
    } else {
        printf("转换失败!请检查输入字符串或缓冲区大小,\n");
    }
    // 测试带空格的十六进制字符串(需要先处理)
    const char* hex_input_with_spaces = "48 65 6C 6C 6F";
    char temp_hex[20];
    char ascii_output_with_spaces[20];
    // 先移除空格
    int j = 0;
    for (int i = 0; hex_input_with_spaces[i] != '\0'; i++) {
        if (hex_input_with_spaces[i] != ' ') {
            temp_hex[j++] = hex_input_with_spaces[i];
        }
    }
    temp_hex[j] = '\0';
    result = hexstr_to_asciistr(temp_hex, ascii_output_with_spaces, sizeof(ascii_output_with_spaces));
    if (result != -1) {
        printf("\n带空格的十六进制字符串: %s\n", hex_input_with_spaces);
        printf("移除空格后: %s\n", temp_hex);
        printf("转换后的ASCII字符串: %s\n", ascii_output_with_spaces);
    }
    return 0;
}

代码解释

  1. 函数参数hexstr_to_asciistr 接收一个十六进制字符串、一个用于存储结果的缓冲区,以及缓冲区的大小,缓冲区大小参数是防止缓冲区溢出(Buffer Overflow)的关键安全措施。
  2. 有效性检查:检查输入指针是否为 NULL,以及缓冲区大小是否为0。
  3. 长度检查:一个字节由两个十六进制字符表示,所以输入字符串的长度必须是偶数,结果字符串的长度是输入长度的一半,必须小于输出缓冲区的大小。
  4. 循环转换for 循环步长为2,每次处理两个字符。
  5. tolower:将字符统一转换为小写,这样无论是 'A' 还是 'a' 都能被正确处理。
  6. 有效性检查:再次检查这两个字符是否是合法的十六进制字符(0-9, a-f)。
  7. 字符转数值:这是核心步骤。
    • 如果字符在 'a''f' 之间,它的值就是 字符 - 'a' + 10
    • 如果字符在 '0''9' 之间,它的值就是 字符 - '0'
  8. 组合字节high_val << 4 将高4位移动到正确的位置, 按位或运算将低4位合并进来。
  9. 存入结果:将组合好的 unsigned char 存入结果数组。
  10. 结束符:循环结束后,手动在结果字符串的最后添加 \0
  11. main 函数:展示了如何调用此函数,并处理了一个带有空格的输入(通常需要先去除空格再进行转换)。

十六进制数值转ASCII字符

这个操作相对简单,就是将一个数值(0-255)强制类型转换为 char,这个 char 就是它对应的ASCII字符。

核心思路

直接将一个表示十六进制数值的整数(如 0x48)赋值给一个 char 类型的变量。

示例代码

#include <stdio.h>
int main() {
    // 定义一个整型变量,用十六进制赋值
    int hex_value = 0x48; // 十进制的72
    int hex_value_2 = 0x6F; // 十进制的111
    // 将整型变量强制转换为 char 类型
    // 在ASCII码表中,72对应'H',111对应'o'
    char ascii_char = (char)hex_value;
    char ascii_char_2 = (char)hex_value_2;
    printf("十六进制数值 0x%x 对应的ASCII字符是: '%c'\n", hex_value, ascii_char);
    printf("十六进制数值 0x%x 对应的ASCII字符是: '%c'\n", hex_value_2, ascii_char_2);
    // 也可以直接将十进制数值转换
    char another_char = (char)65; // ASCII码65是 'A'
    printf("十进制数值 65 对应的ASCII字符是: '%c'\n", another_char);
    return 0;
}

代码解释

  • int hex_value = 0x48;:这里定义了一个整型变量 hex_value,并给它赋了一个十六进制值 0x48,在内存中,它存储的就是数字 72
  • char ascii_char = (char)hex_value;:这是一个类型转换,它将 int 类型的 72 截断为 char 类型,因为 72char 的可表示范围内(-128到127),所以转换后 ascii_char 的值就是 72
  • printf(..., '%c', ...)%cprintf 的格式化字符,它会将一个数值解释为ASCII码并打印出对应的字符。72 被打印成了 'H'

场景 输入 输出 核心方法
字符串转换 "48656C6C6F" "Hello" 逐字符解析,计算数值,存入新字符串。
数值转换 0x48 (整数) 'H' (字符) 类型转换 (char)0x48

在实际编程中,操作一(字符串转换) 的应用远比操作二更普遍,请务必注意字符串转换时的缓冲区大小检查,以避免程序出现严重的安全漏洞。

c语言hextoascii
(图片来源网络,侵删)
-- 展开阅读全文 --
头像
织梦站点默认关键字如何设置与优化?
« 上一篇 今天
织梦代码从入门到精通,如何快速掌握核心技巧?
下一篇 » 今天
取消
微信二维码
支付宝二维码

目录[+]