User-defined function without printf, returns hexadecimal value

本小妞迷上赌 提交于 2020-01-06 18:12:54

问题


char decimalToHexadecimal(long int decimalNumber)
{
    long int quotient;
    long int remainder;
    static char hexDecNum[100];
    int i=0;

    quotient = decimalNumber;

    while (quotient != 0)
    {

        remainder = quotient % 16;

        // to convert integer into character
        if (remainder < 10)
        {
            remainder = remainder + 48;
        }
        else
        {
            remainder = remainder + 55;
        }
        hexDecNum[i++] = remainder;
        quotient = quotient / 16;
    }
}

This user defined function will convert decimal number to hexadecimal number. I wanted to make function that will not use any library function like printf,scanf etc. I and to get return hexadecimal value of a decimal number from this function. But, I am confused how to get return hexadecimal number from this function?


回答1:


Read the chapter about strings in your C textbook.

One solution is to return a pointer to char:

char *decimalToHexadecimal(long int decimalNumber)
{
  long int quotient;
  long int remainder;
  static char hexDecNum[100];  // must be static

  quotient = decimalNumber;
  int i = 0;  //               //   <<<< you forgot to declare i
  while (quotient != 0)
  {
    remainder = quotient % 16;

    // to convert integer into character
    if (remainder < 10)
    {
      remainder = remainder + 48;
    }
    else
    {
      remainder = remainder + 55;
    }
    hexDecNum[i++] = remainder;
    quotient = quotient / 16;
  }
  hexDecNum[i] = 0;            //    <<< you forgot the NUL string terminator
  return hexDecNum;            //    <<< you forgot to return something
}

int main() 
{
  printf("%s\n", decimalToHexadecimal(0x1234));
}

The hexDecNum buffer must be static, because you are returning a pointer to this buffer, and this buffer will cease to exist once you have returned from the decimalToHexadecimal function, because it's a local variable. Modern compilers will usually emit a warning if you return the address of a local variable.

The function is still not quite what you want. I leave it as an exercise to correct it.

Edit

Another approach for conversion is this: the decimal number is actually represented as a binary number (as all numbers BTW), so we don't even need division; we just can decompose the number into 4 bit nibbles (0000 to 1111) and transform these nibbles into a hexadecimal digits (0..9, A..F):

char *decimalToHexadecimal(long int decimalNumber)
{
  static char hexDecNum[100];
  int i;   
  for (i = 0; i < sizeof(decimalNumber) * 2; i++)
  {
    int digit = decimalNumber & 0xf;

    if (digit >= 10)
      digit += 'A' - 10;  // better than writing 55
    else
      digit += '0';       // better than writing 48

    hexDecNum[i] = digit;    
    decimalNumber >>= 4;
  }

  hexDecNum[i] = 0;
  return hexDecNum;
}

The function suffers from the same problem as your original function. Improving it is left as an exercise.




回答2:


It's better to use an explicit string of the desired character set, that way you can remove any assumptions about the encoding, which is very good for portability.

Although C requires that the digits 0 through 9 are encoded using adjacent code points (i.e. '1' - '0' must equal 1, and so on), no such guarantee is made for the letters.

Also, returning a string requires heap allocation, a static buffer (which makes the function harder to use), or simply accepting the string from the caller which is often the best choice.

It's important to realize that the typical technique of extracting the remainder from division by 16 (or just masking out the four right-most bits) generates bits "from the right", whereas typical string-building runs from the left. This has to be taken into account as well, or you'd generate "d00f" when given 0xf00d.

Here's how it could look:

char * num2hex(char *buf, size_t buf_max, unsigned long number)
{
   if(buf_max < 2)
     return NULL;
   char * put = buf + buf_max; // Work backwards.
   *--put = '\0';  // Terminate the resulting string.
   do
   {
     if(put == buf)
       return NULL;
     const unsigned int digit = number & 15;
     *--put = "0123456789abcdef"[digit];
     number >>= 4;
   } while(number != 0);
   return put;
}

This function returns the start of the built string (which is "right-aligned" in the provided buffer, so it's not at the start of it), or NULL if it runs out of space.

Note: yeah, this is perhaps a bit too terse, of course the digit set could be extracted out and given a name, but it's also pretty obvious what its purpose is, and indexing a literal is handy (some people don't seem to realize it's doable) and somewhat instructive to show off.



来源:https://stackoverflow.com/questions/44278908/user-defined-function-without-printf-returns-hexadecimal-value

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!