简体   繁体   English

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

[英]How to manually convert decimal value to hexadecimal string in C?

nb 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. 我知道这个问题之前已经在各种不同的方式和情况下被问到了StackOverflow,但是我寻找的答案的搜索对我的具体案例并没有多大帮助。 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? 所以虽然这看起来像是一个问题的副本,例如如何将整数转换为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). 我知道stdlib.h和printf有一些节拍技巧,但这是一项大学任务,我需要手动完成(教授的命令)。 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". 使用好的旧“除以16并将余数转换为十六进制并反转值”获取十六进制字符串的方法,但是我的代码中必定存在一个大错误,因为它不会让我回来,例如“BC”表示十进制值“188”。

It is assumed that the algorithm will NEVER need to find hex values for decimals larger than 256 (or FF). 假设算法永远不需要为大于256(或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). 虽然参数的传递可能不是最佳或理想的,但我们已经被告知要使用它(虽然我可以修改getHexValue函数,因为我自己编写了这个函数)。

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). char *hexString是指向我需要输出到屏幕(最终)的字符串的指针。 The char inputChar parameter that I need to convert to hex (which is why I never need to convert values over 256). 我需要转换为十六进制的char inputChar参数(这就是我永远不需要将值转换为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. 如果有一个更好的方法来做这个,它仍然使用void asciiToHexadecimal(char inputChar, char *hexString)函数,我都是耳朵, void asciiToHexadecimal(char inputChar, char *hexString) ,我的调试似乎表明值是正常的,但输出结果喜欢\\377而不是预期的十六进制字母数字表示。

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. 对不起,如果问题本身(或代码)有任何术语或其他问题,我仍然是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 ) (此代码hexString所有内容都可以工作,但hexString除外)

 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 .) 您可能希望打印出您为每个感兴趣的值调用此例程所获得的字符。:)( 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. 当您使用0到9之间的数字调用getHexValue()时,将在ASCII控制字符范围内返回0到9之间的数字。 When you call getHexValue() with a number between 10 and 15, you return a number between 65 and 75, in the ASCII letter range. 当您使用10到15之间的数字调用getHexValue()时,将在ASCII字母范围内返回65到75之间的数字。

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. hexString已被分配一个字节太小而不能成为C字符串 - 您忘记为ASCII NUL '\\0'字符留出空间。 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. 如果您使用%c格式说明符打印hexString ,或者使用memcpy(3)构建更大的字符串,则可能没问题,但是您的printf()调用将hexString视为字符串。

In general, when you see a 一般来说,当你看到一个

char *foo = malloc(N);

call, be afraid -- the C idiom is 打电话,害怕 - C成语是

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. +1是你向其他人(以及你自己,在两个月内)发出的信号,表明你为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. 如果你在另一个计算中隐藏了那个+1 ,那么你就错过了一个记忆模式的机会,这种模式可以在你每次阅读代码时捕获这些错误。 (Honestly, I found one of these through this exact pattern on SO just two days ago. :) (老实说,我在两天前通过SO的确切模式找到了其中一个。:)

I made a librairy to make Hexadecimal / Decimal conversion without the use of stdio.h . 我做了一个librairy来进行十六进制/十进制转换而不使用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() 这将使用calloc()来返回指向十六进制字符串的指针,这样就可以优化使用的内存量,所以不要忘记使用free()

Here the link on github : https://github.com/kevmuret/libhex/ 这里是github上的链接: https//github.com/kevmuret/libhex/

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;
}
#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;
    //
}

In complement of the other good answers.... 补充其他好的答案....

If the numbers represented by these hexadecimal or decimal character strings are huge (eg hundreds of digits), they won't fit in a long long (or whatever largest integral type your C implementation is providing). 如果由这些十六进制或十进制字符串表示的数字很大(例如数百个数字),则它们将不适合long long整数(或C实现提供的任何最大整数类型)。 Then you'll need bignums . 然后你需要bignums I would suggest not coding your own implementation (it is tricky to make an efficient one), but use an existing one like GMPlib 我建议不要编写自己的实现(制作一个有效的实现是很棘手的),但是使用像GMPlib这样的现有实现

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: (1)改变:

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). (您需要 0..9值转换为char,而不仅仅是转换它)。

(2) change: (2)改变:

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 % ). (inputChar被视为已签名,这会产生不良结果% )。

A couple of tips: 一些提示:

  • have getHexValue return '?' getHexValue返回'?' rather than -1 for invalid input (make debugging easier) 而不是-1表示无效输入(使调试更容易)

  • write a test harness for debugging, eg 写一个测试工具进行调试,例如

     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; } 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM