大十六进制(18 个字符)到十进制转换在 C 程序中不正确

问题描述 投票:0回答:1

我正在尝试编写一个小型 C 程序来将 18 个字符的十六进制数字(例如:ec6260d8b431e420d6)转换为十进制。然而,每次我用在线转换器检查我的代码时,它总是错误的。我读到我的变量类型对于我尝试转换的数字可能不够大,并且在不使用负数时使用无符号变量。当我查看我正在使用的代码时,我不知道在哪里更改上述可能的解决方案。这是我正在使用的代码:

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

int main() {
    char hex[100];
    printf("Enter a hexadecimal number: ");
    scanf("%s", hex);
    long decimal = 0;
    int i = 0;
    while (hex[i] != '\0') {
        int digit = hex[i] - '0';
        if (digit >= 10) {
            digit -= 7;
        }
        decimal = decimal * 16 + digit;
        i++;
    }
    printf("The decimal equivalent of %s is %ld.\n", hex, decimal);
    return 0;
}

任何关于我做错或不理解的事情的指示和建议将不胜感激。

c hex data-conversion
1个回答
0
投票

OP代码中至少存在两个问题:

  1. 对输入的十六进制数字进行解码:转换仅支持大写字母,并且不检查数字是否有效。
  2. 转换假定整个数字适合单个变量:18 个十六进制数字对应于 72 位,平台可能支持也可能不支持。

第一个问题可以通过此答案解决(修改为一次读取一个数字并添加错误处理):C 中的十六进制字符串到字节数组

第二个问题可以通过将十六进制数字存储在数组中并实现必要的“big int”操作(除以 10 余数)来解决,如本答案中所述(修改为基数 16 而不是基数 256):如何我在c中将一个非常大的十六进制数转换为十进制数组?

总而言之:

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

// Divide 16-base number by 10 and return remainder
unsigned char div10(unsigned char *hex, unsigned size)
{
    unsigned rem = 0;
    for(int i = 0; i < size; i++)
    {
        unsigned n = rem * 16 + hex[i];
        hex[i] = n / 10;
        rem = n % 10;
    }
    return rem;
}

int main(int argc, char **argv) {
    char hex[101];
    printf("Enter a hexadecimal number: ");
    scanf("%100s", hex);

    // Decode hexadecimal number
    const char *pos = hex;
    unsigned hex_count = 0;

    unsigned char hex_digits[100];  // Digit values 0-15, most significant first
    while(*pos != 0)
    {
        short unsigned hex;
        if(sscanf(pos, "%1hx", &hex) != 1)
        {
            printf("ERROR: invalid hex digit '%c'\n", *pos);
             // Error: not a valid hex digit
        }
        else
        {
            hex_digits[hex_count++] = hex;
        }
        pos++;
    }

    // Convert hexadecimal to decimal
    unsigned char hex_zero[100] = {0};
    unsigned dec_count = 0;
    unsigned char dec_digits[300];  // Digit values 0-9, most significant first, aligned to end of array
    while(memcmp(hex_digits, hex_zero, hex_count) != 0 && dec_count < sizeof(dec_digits))
    {
        dec_digits[sizeof(dec_digits) - dec_count - 1] = div10(hex_digits, hex_count);
        dec_count++;
    }

    // Display decimal number
    if(memcmp(hex_digits, hex_zero, hex_count) != 0)
    {
        printf("ERROR: result buffer too small\n");
    }
    else if(dec_count == 0)
    {
        printf("0\n");
    }
    else
    {
        for(unsigned n = 0; n < dec_count; n++)
        {
            printf("%c", dec_digits[sizeof(dec_digits) - dec_count + n]+'0');
        }
        printf("\n");
    }

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.