没有printf的用户定义函数,返回十六进制值

时间:2017-05-31 07:58:01

标签: c hex ascii

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

此用户定义的函数将十进制数转换为十六进制数。 我想制作不使用任何库函数的函数,如printf,scanf等。我从这个函数中获取十进制数的十六进制值。 但是,我很困惑如何从这个函数获得返回十六进制数?

2 个答案:

答案 0 :(得分:2)

阅读C教科书中关于字符串的章节。

一种解决方案是将指针返回到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));
}

hexDecNum缓冲区必须是静态的,因为您将指针返回到此缓冲区,并且从decimalToHexadecimal函数返回后此缓冲区将不再存在,因为它是一个局部变量。如果返回局部变量的地址,现代编译器通常会发出警告。

这个功能仍然不是你想要的。我把它留作练习来纠正它。

修改

转换的另一种方法是:十进制数实际上表示为二进制数(所有数字都是BTW),所以我们甚至不需要除法;我们可以将数字分解为4位半字节(0000到1111)并将这些半字节转换为十六进制数字(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;
}

该功能遇到与原始功能相同的问题。改进它只是一种练习。

答案 1 :(得分:2)

最好使用所需字符集的显式字符串,这样就可以删除有关编码的任何假设,这对于可移植性非常有用。

虽然C要求使用相邻代码点对数字0到9进行编码(即'1' - '0'必须等于1,等等,但是没有这样的保证信件。

另外,返回一个字符串需要堆分配,一个静态缓冲区(这使得函数更难使用),或者只是接受来自调用者的字符串,这通常是最好的选择。

重要的是要认识到从16除法中提取余数的典型技术(或者只是屏蔽掉最右边的4位)会产生来自右边的#34;而#34;字符串构建从左侧开始。这也必须考虑在内,或者在给定"d00f"时生成0xf00d

以下是它的外观:

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

此函数返回构建字符串的开头(在提供的缓冲区中为&#34;右对齐&#34;因此它不在开头),或NULL如果空间不足。

注意:是的,这可能有点过于简洁,当然数字集可以被提取出来并给出一个名字,但它的目的是非常明显的,并且索引文字是很方便的(有些人似乎并没有意识到这是可行的,而且有点炫耀。