You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C17中任意长十进制字符串转十六进制字符串的实现方法问询

大十进制字符串转十六进制字符串的C17实现

对于超大十进制数(无法用基本整数类型存储)转十六进制,核心思路是模拟大整数的除法取余操作——反复将十进制数除以16,收集每次的余数(对应十六进制的一位),最后将余数倒序排列得到结果。以下是具体实现方案:

一、内存分配与计算

十六进制最大位数的整数计算方式:
十进制数的最大二进制位数为 n * log2(10)(n为十进制字符串长度),十六进制每4位二进制对应一位,因此最大十六进制位数可通过整数运算避免浮点误差:

size_t max_hex_len = (n * 10 + 11) / 12; // 等价于ceil(n * log2(10)/4)

先分配max_hex_len + 1(预留字符串终止符空间)的内存,待收集完所有余数后,再通过realloc调整到实际需要的长度,避免内存浪费。

二、核心实现步骤

  1. 模拟大整数除以16:
    • 用临时数组存储每一步除法后的商(十进制),初始商为输入的十进制字符串副本。
    • 遍历当前商的每一位,计算当前位数值加上前一位余数*10的总和,除以16得到新的商位,余数则是当前十六进制位的数值。
    • 当商变为全零状态时,停止计算。
  2. 收集并反转余数:
    • 余数范围是0-15,对应十六进制字符0-9A-F。
    • 收集的余数是从低位到高位的顺序,最后需反转数组得到正确的十六进制字符串顺序。

三、完整代码示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

// 十进制字符串转十六进制字符串,返回的内存需调用者free
char* dec_to_hex(const char* st_in) {
    if (!st_in || !*st_in) return NULL;

    size_t n = strlen(st_in);
    // 计算最大十六进制位数,加1存终止符
    size_t max_hex_len = (n * 10 + 11) / 12;
    char* hex_digits = malloc(max_hex_len + 1);
    if (!hex_digits) return NULL;

    // 临时存储商(十进制字符串),初始为输入的副本
    char* quotient = malloc(n + 1);
    if (!quotient) {
        free(hex_digits);
        return NULL;
    }
    strcpy(quotient, st_in);

    size_t hex_idx = 0;
    int has_non_zero = 0;

    while (1) {
        int remainder = 0;
        char new_quotient[n + 1] = {0};
        size_t q_idx = 0;

        // 遍历当前商的每一位,计算新的商和余数
        for (size_t i = 0; quotient[i]; i++) {
            int digit = quotient[i] - '0';
            int current = remainder * 10 + digit;
            new_quotient[q_idx] = (current / 16) + '0';
            remainder = current % 16;

            // 跳过前导零,只保留有效商位
            if (new_quotient[q_idx] != '0' || q_idx > 0) {
                q_idx++;
            }
        }
        new_quotient[q_idx] = '\0';

        // 处理余数:避免输入全零时生成多余的0
        if (!has_non_zero && remainder == 0) {
            if (strcmp(quotient, "0") == 0) {
                hex_digits[hex_idx++] = '0';
                break;
            }
        } else {
            has_non_zero = 1;
            // 余数转大写十六进制字符
            hex_digits[hex_idx++] = (remainder < 10) ? (remainder + '0') : (remainder - 10 + 'A');
        }

        // 更新商为新的商,若商为空则退出循环
        free(quotient);
        if (q_idx == 0) {
            quotient = NULL;
            break;
        }
        quotient = malloc(q_idx + 1);
        if (!quotient) {
            free(hex_digits);
            return NULL;
        }
        strcpy(quotient, new_quotient);
    }

    // 反转十六进制字符数组,得到正确顺序
    for (size_t i = 0; i < hex_idx / 2; i++) {
        char temp = hex_digits[i];
        hex_digits[i] = hex_digits[hex_idx - 1 - i];
        hex_digits[hex_idx - 1 - i] = temp;
    }
    hex_digits[hex_idx] = '\0';

    // 调整内存到实际需要的大小
    char* result = realloc(hex_digits, hex_idx + 1);
    if (result) {
        hex_digits = result;
    }

    if (quotient) free(quotient);
    return hex_digits;
}

// 测试示例
int main(int argc, char* argv[]) {
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <decimal-string>\n", argv[0]);
        return 1;
    }

    // 验证输入是否仅含数字
    for (size_t i = 0; argv[1][i]; i++) {
        if (!isdigit(argv[1][i])) {
            fprintf(stderr, "Input must contain only digits.\n");
            return 1;
        }
    }

    char* st_out = dec_to_hex(argv[1]);
    if (st_out) {
        printf("%s\n", st_out);
        free(st_out);
    } else {
        fprintf(stderr, "Memory allocation failed.\n");
        return 1;
    }

    return 0;
}

四、内存管理说明

  1. 初始分配的hex_digits按最大可能长度分配,最后通过realloc缩小到实际使用的长度(hex_idx + 1),避免多余内存占用。
  2. 临时的quotient数组每次循环后都会释放并重新分配,确保内存不泄漏。
  3. 返回的十六进制字符串由调用者负责调用free释放。

内容的提问来源于stack exchange,提问作者CopperCableIsolator

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 16:05:13