如何在C中手动将十进制值转换为十六进制字符串?

发布于 2024-10-21 05:28:28 字数 2188 浏览 4 评论 0原文

nb 我知道这个问题之前已经在 StackOverflow 上以各种不同的方式和情况被问过,但搜索我寻求的答案并不能完全帮助我的具体情况。因此,虽然这最初看起来像是问题的重复,例如 我怎样才能在C中将整数转换为十六进制字符串?给出的答案是准确的,但对我没有用。

我的问题是如何手动将十进制整数转换为十六进制字符串。我知道 stdlib.h 和 printf 有一些节拍技巧,但这是一项大学任务,我需要手动完成(教授的命令)。但是,我们可以寻求帮助。

使用古老的“除以 16 并将余数转换为十六进制并反转值” 方法来获取十六进制字符串,但我的代码中一定有一个大错误,因为它没有给我返回值,例如“BC”代表十进制值“188”。

假设该算法永远不需要查找大于 256(或 FF)的小数的十六进制值。虽然参数的传递可能不是最佳或理想的,但我们被告知要使用它(尽管我可以修改 getHexValue 函数,因为我自己编写了该函数)。

这就是我到目前为止所拥有的:

/* Function to get the hex character for a decimal (value) between
 * 0 and 16.  Invalid values are returned as -1.
 */
char getHexValue(int value) 
{
   if (value < 0) return -1;
   if (value > 16) return -1;
   if (value <= 9) return (char)value;
   value -= 10;
   return (char)('A' + value);
}


/* Function asciiToHexadecimal() converts a given character (inputChar) to
 * its hexadecimal (base 16) equivalent, stored as a string of
 * hexadecimal digits in hexString. This function will be used in menu
 * option 1.
 */
void asciiToHexadecimal(char inputChar, char *hexString)
{
   int i = 0;
   int remainders[2];
   int result = (int)inputChar;
   while (result) {
      remainders[i++] = result % 16;
      result /= (int)16;
   }
   int j = 0;
   for (i = 2; i >= 0; --i) {
      char c = getHexValue(remainders[i]);
      *(hexString + (j++)) = c;
   }
}

char *hexString 是指向我需要输出到屏幕(最终)的字符串的指针。我需要转换为十六进制的 char inputChar 参数(这就是为什么我永远不需要转换超过 256 的值)。

如果有更好的方法来做到这一点,仍然使用 void asciiToHexadecimal(char inputChar, char *hexString) 函数,我洗耳恭听,除此之外,我的调试似乎表明这些值是好的,但输出结果类似于 \377,而不是预期的十六进制字母数字表示形式。

抱歉,如果问题本身(或代码)有任何术语或其他问题,我对 C 的世界仍然很陌生。

更新: 我只是想到,可能与发布我显示值的方式有关,以防其打印,而不是错误的转换。如下:(

char* binaryString = (char*) malloc(8);
char* hexString = (char*) malloc(2);
asciiToBinary(*(asciiString + i), binaryString);
asciiToHexadecimal(*(asciiString + i), hexString);
printf("%6c%13s%9s\n", *(asciiString + i), binaryString, hexString);

除了 hexString 之外,此代码片段中的所有内容都有效)

n.b. I know that this question has been asked on StackOverflow before in a variety of different ways and circumstances, but the search for the answer I seek doesn't quite help my specific case. So while this initially looks like a duplicate of a question such as How can I convert an integer to a hexadecimal string in C? the answers given, are accurate, but not useful to me.

My question is how to convert a decimal integer, into a hexadecimal string, manually. I know there are some beat tricks with stdlib.h and printf, but this is a college task, and I need to do it manually (professor's orders). We are however, permitted to seek help.

Using the good old "divide by 16 and converting the remainder to hex and reverse the values" method of obtaining the hex string, but there must be a big bug in my code as it is not giving me back, for example "BC" for the decimal value "188".

It is assumed that the algorithm will NEVER need to find hex values for decimals larger than 256 (or FF). While the passing of parameters may not be optimal or desirable, it's what we've been told to use (although I am allowed to modify the getHexValue function, since I wrote that one myself).

This is what I have so far:

/* Function to get the hex character for a decimal (value) between
 * 0 and 16.  Invalid values are returned as -1.
 */
char getHexValue(int value) 
{
   if (value < 0) return -1;
   if (value > 16) return -1;
   if (value <= 9) return (char)value;
   value -= 10;
   return (char)('A' + value);
}


/* Function asciiToHexadecimal() converts a given character (inputChar) to
 * its hexadecimal (base 16) equivalent, stored as a string of
 * hexadecimal digits in hexString. This function will be used in menu
 * option 1.
 */
void asciiToHexadecimal(char inputChar, char *hexString)
{
   int i = 0;
   int remainders[2];
   int result = (int)inputChar;
   while (result) {
      remainders[i++] = result % 16;
      result /= (int)16;
   }
   int j = 0;
   for (i = 2; i >= 0; --i) {
      char c = getHexValue(remainders[i]);
      *(hexString + (j++)) = c;
   }
}

The char *hexString is the pointer to the string of characters which I need to output to the screen (eventually). The char inputChar parameter that I need to convert to hex (which is why I never need to convert values over 256).

If there is a better way to do this, which still uses the void asciiToHexadecimal(char inputChar, char *hexString) function, I am all ears, other than that, my debugging seems to indicate the values are ok, but the output comes out like \377 instead of the expected hexadecimal alphanumeric representation.

Sorry if there are any terminology or other problems with the question itself (or with the code), I am still very new to the world of C.

Update:
It just occurred to me that it might be relevant to post the way I am displaying the value in case its the printing, and not the conversion which is faulty. Here it is:

char* binaryString = (char*) malloc(8);
char* hexString = (char*) malloc(2);
asciiToBinary(*(asciiString + i), binaryString);
asciiToHexadecimal(*(asciiString + i), hexString);
printf("%6c%13s%9s\n", *(asciiString + i), binaryString, hexString);

(Everything in this code snip-pit works except for hexString)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

神仙妹妹 2024-10-28 05:28:28
char getHexValue(int value)
{
   如果(值<0)返回-1;
   如果(值> 16)返回-1;
   if (值 <= 9) 返回 (char)值;
   值-= 10;
   return (char)('A' + 值);
}

您可能希望为您感兴趣的每个值打印出调用此例程所获得的字符。:)(printf(3) 格式 %c

)如果您使用 0 到 9 之间的数字调用 getHexValue(),则在 ASCII 控制字符范围。当您使用 10 到 15 之间的数字调用 getHexValue() 时,您将返回 65 到 75 之间的 ASCII 字母范围内的数字。

讲道?如果您编写以下测试,单元测试可以为您节省几个小时的时间在你编写代码的同时。

有些人喜欢先编写测试。虽然我从来没有长期坚持这种方法的纪律,但知道您必须编写测试将迫使您编写更容易测试的代码。更容易测试的代码是较少耦合(或“更加解耦”) ,这通常会导致更少的错误!

尽早并经常编写测试。 :)

更新:在包含输出代码后,我也必须对此发表评论:)

char* 二进制字符串 = (char*) malloc(8);
char* hexString = (char*) malloc(2);
asciiToBinary(*(asciiString + i), 二进制字符串);
asciiToHexadecimal(*(asciiString + i), hexString);
printf("%6c%13s%9s\n", *(asciiString + i), 二进制字符串, 十六进制字符串);

hexString 分配的一个字节太小,无法成为 C 字符串 - 您忘记为 ASCII NUL '\0' 字符留出空间。如果您通过 %c 格式说明符打印 hexString,或者使用 memcpy(3) 构建更大的字符串,可能没问题,但您的 printf() 调用将 hexString 视为字符串。

一般来说,当你看到一个

char *foo = malloc(N);

调用时,要害怕 - C 习惯用法是

char *foo = malloc(N+1);

+1 是你向其他人(以及两个月后的你自己)发出的信号,表明你已经为 NUL 留出了空间。如果您在另一个计算中隐藏该 +1,那么您就错过了记住每次阅读代码时都可以捕获这些错误的模式的机会。 (老实说,两天前我就通过这个确切的模式在SO上找到了其中一个。:)

char getHexValue(int value)
{
   if (value < 0) return -1;
   if (value > 16) return -1;
   if (value <= 9) return (char)value;
   value -= 10;
   return (char)('A' + value);
}

You might wish to print out the characters you get from calling this routine for every value you're interested in. :) (printf(3) format %c.)

When you call getHexValue() with a number between 0 and 9, you return a number between 0 and 9, in the ASCII control-character range. When you call getHexValue() with a number between 10 and 15, you return a number between 65 and 75, in the ASCII letter range.

The sermon? Unit testing can save you hours of time if you write the tests about the same time you write the code.

Some people love writing the tests first. While I've never had the discipline to stick to this approach for long, knowing that you have to write tests will force you to write code that is easier to test. And code that is easier to test is less coupled (or 'more decoupled'), which usually leads to fewer bugs!

Write tests early and often. :)

Update: After you included your output code, I had to comment on this too :)

char* binaryString = (char*) malloc(8);
char* hexString = (char*) malloc(2);
asciiToBinary(*(asciiString + i), binaryString);
asciiToHexadecimal(*(asciiString + i), hexString);
printf("%6c%13s%9s\n", *(asciiString + i), binaryString, hexString);

hexString has been allocated one byte too small to be a C-string -- you forgot to leave room for the ASCII NUL '\0' character. If you were printing hexString by the %c format specifier, or building a larger string by using memcpy(3), it might be fine, but your printf() call is treating hexString as a string.

In general, when you see a

char *foo = malloc(N);

call, be afraid -- the C idiom is

char *foo = malloc(N+1);

That +1 is your signal to others (and yourself, in two months) that you've left space for the NUL. If you hide that +1 in another calculation, you're missing an opportunity to memorize a pattern that can catch these bugs every time you read code. (Honestly, I found one of these through this exact pattern on SO just two days ago. :)

始终不够爱げ你 2024-10-28 05:28:28

目标是纯十六进制的,还是函数应可参数化。如果它被限制为十六进制,为什么不利用一个十六进制数字恰好编码四位的事实呢?

我就是这样做的:

#include <stdlib.h>

#include <limits.h> /* implementation's CHAR_BIT */

#define INT_HEXSTRING_LENGTH (sizeof(int)*CHAR_BIT/4)
/* We define this helper array in case we run on an architecture
   with some crude, discontinous charset -- THEY EXIST! */
static char const HEXDIGITS[0x10] = 
    {'0', '1', '2', '3', '4', '5', '6', '7',
     '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
void int_to_hexstring(int value, char result[INT_HEXSTRING_LENGTH+1])
{
    int i;
    result[INT_HEXSTRING_LENGTH] = '\0';

    for(i=INT_HEXSTRING_LENGTH-1; value; i--, value >>= 4) {
        int d  = value & 0xf;
        result[i] = HEXDIGITS[d];
    }

    for(;i>=0;i--){ result[i] = '0'; }
}
int main(int argc, char *argv[])
{
    char buf[INT_HEXSTRING_LENGTH+1];

    if(argc < 2)
        return -1;

    int_to_hexstring(atoi(argv[1]), buf);
    puts(buf);
    putchar('\n');

    return 0;
}

Is the target purely hexadecimal, or shall the function be parametizable. If it's constrained to hex, why not exploit the fact, that a single hex digit encodes exactly four bits?

This is how I'd do it:

#include <stdlib.h>

#include <limits.h> /* implementation's CHAR_BIT */

#define INT_HEXSTRING_LENGTH (sizeof(int)*CHAR_BIT/4)
/* We define this helper array in case we run on an architecture
   with some crude, discontinous charset -- THEY EXIST! */
static char const HEXDIGITS[0x10] = 
    {'0', '1', '2', '3', '4', '5', '6', '7',
     '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
void int_to_hexstring(int value, char result[INT_HEXSTRING_LENGTH+1])
{
    int i;
    result[INT_HEXSTRING_LENGTH] = '\0';

    for(i=INT_HEXSTRING_LENGTH-1; value; i--, value >>= 4) {
        int d  = value & 0xf;
        result[i] = HEXDIGITS[d];
    }

    for(;i>=0;i--){ result[i] = '0'; }
}
int main(int argc, char *argv[])
{
    char buf[INT_HEXSTRING_LENGTH+1];

    if(argc < 2)
        return -1;

    int_to_hexstring(atoi(argv[1]), buf);
    puts(buf);
    putchar('\n');

    return 0;
}
乖乖哒 2024-10-28 05:28:28

我制作了一个库来进行十六进制/十进制转换,而不使用 stdio.h。使用非常简单:

char* dechex (int dec);

这将使用 calloc() 返回一个指向十六进制字符串的指针,这样可以优化内存使用量,所以不要忘记使用 free( )

这里是github上的链接:https://github.com/kevmuret/libhex/

I made a librairy to make Hexadecimal / Decimal conversion without the use of stdio.h. Very simple to use :

char* dechex (int dec);

This will use calloc() to to return a pointer to an hexadecimal string, this way the quantity of memory used is optimized, so don't forget to use free()

Here the link on github : https://github.com/kevmuret/libhex/

尴尬癌患者 2024-10-28 05:28:28
#include<stdio.h>

char* inttohex(int);
main()
{
    int i;
    char *c;
    printf("Enter the no.\n");
    scanf("%d",&i);
    c=inttohex(i);
    printf("c=%s",c);
}

char* inttohex(int i)
{
    int l1,l2,j=0,n;
    static char a[100],t;

    while(i!=0)
    {
    l1=i%16;
    if(l1>10)
    {
        a[j]=l1-10+'A';
    }

    else
        sprintf(a+j,"%d",l1);

    i=i/16;
    j++;
    }
    n=strlen(a);
    for(i=0;i<n/2;i++)
    {
        t=a[i];
        a[i]=a[n-i-1];
        a[n-i-1]=t;
    }

    //printf("string:%s",a);
    return a;
    //
}
#include<stdio.h>

char* inttohex(int);
main()
{
    int i;
    char *c;
    printf("Enter the no.\n");
    scanf("%d",&i);
    c=inttohex(i);
    printf("c=%s",c);
}

char* inttohex(int i)
{
    int l1,l2,j=0,n;
    static char a[100],t;

    while(i!=0)
    {
    l1=i%16;
    if(l1>10)
    {
        a[j]=l1-10+'A';
    }

    else
        sprintf(a+j,"%d",l1);

    i=i/16;
    j++;
    }
    n=strlen(a);
    for(i=0;i<n/2;i++)
    {
        t=a[i];
        a[i]=a[n-i-1];
        a[n-i-1]=t;
    }

    //printf("string:%s",a);
    return a;
    //
}
终陌 2024-10-28 05:28:28

您已经非常接近了 - 进行以下两个小更改,它将运行良好,足以让您完成它:

(1) 将:更改

if (value <= 9) return (char)value;

为:(

if (value <= 9) return '0' + value;

您需要转换 0..9值到一个字符,而不仅仅是转换它)。

(2) 将:更改

void asciiToHexadecimal(char inputChar, char *hexString)

为:

void asciiToHexadecimal(unsigned char inputChar, char *hexString)

(inputChar 被视为有符号,这会导致 % 产生不良结果)。

一些提示:

  • 对于无效输入,让 getHexValue 返回 '?' 而不是 -1(使调试更容易)

  • 编写用于调试的测试工具,例如

    int main(void)
    {
        字符十六进制字符串[256];
    
        asciiToHexadecimal(166, hexString);
    
        printf("hexString = %s = %#x %#x %#x ...\n", hexString, hexString[0], hexString[1], hexString[2]);
    
        返回0;
    }
    

You're very close - make the following two small changes and it will be working well enough for you to finish it off:

(1) change:

if (value <= 9) return (char)value;

to:

if (value <= 9) return '0' + value;

(you need to convert the 0..9 value to a char, not just cast it).

(2) change:

void asciiToHexadecimal(char inputChar, char *hexString)

to:

void asciiToHexadecimal(unsigned char inputChar, char *hexString)

(inputChar was being treated as signed, which gave undesirable results with %).

A couple of tips:

  • have getHexValue return '?' rather than -1 for invalid input (make debugging easier)

  • write a test harness for debugging, e.g.

    int main(void)
    {
        char hexString[256];
    
        asciiToHexadecimal(166, hexString);
    
        printf("hexString = %s = %#x %#x %#x ...\n", hexString, hexString[0], hexString[1], hexString[2]);
    
        return 0;
    }
    
跨年 2024-10-28 05:28:28

作为对其他好的答案的补充......

如果这些十六进制或十进制字符串表示的数字很大(例如数百位数字),它们将不适合 long long (或其他任何形式)您的 C 实现提供的最大整数类型)。然后你需要bignums。我建议不要编写自己的实现(制作一个高效的实现是很棘手的),而是使用现有的实现,例如 GMPlib

In complement of the other good answers....

If the numbers represented by these hexadecimal or decimal character strings are huge (e.g. hundreds of digits), they won't fit in a long long (or whatever largest integral type your C implementation is providing). Then you'll need bignums. I would suggest not coding your own implementation (it is tricky to make an efficient one), but use an existing one like GMPlib

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文