代码之家  ›  专栏  ›  技术社区  ›  Josh Bradley

为什么十六进制转换函数关闭了一个?

c
  •  0
  • Josh Bradley  · 技术社区  · 8 年前

    我试图学习c语言,但我不明白为什么我的十六进制到整数转换函数会返回一个关闭的值。

    注:0XAAAA==46390

    #include <stdio.h>
    #include <math.h>
    
    unsigned int hex_to_int(char hex[4]);
    
    int main()
    {
        char hex[4] = "AAAA";
    
        unsigned int result = hex_to_int(hex);
        printf("%d 0X%X\n", result, result);
        return 0;
    }    
    
    unsigned int hex_to_int(char input[4])
    {
        unsigned int sum, i, exponent;
    
        for(i = 0, exponent = 3; i < 4; i++, exponent--) {
            unsigned int n = (int)input[i] - 55;
            n *= pow(16, exponent);
            sum += n;
        }   
        return sum;
    }
    

    输出:

    46391 0XAAAB
    

    更新:我现在意识到“-55”太荒谬了,看到这个我的记忆都快崩溃了:

    if (input[i] >= '0' && input[i] <= '9')
        val = input[i] - 48;
    else if (input[i] >= 'a' && input[i] <= 'f')
        val = input[i] - 87;
    else if (input[i] >= 'A' && input[i] <= 'F')
        val = input[i] - 55;
    
    2 回复  |  直到 8 年前
        1
  •  4
  •   Lundin    8 年前

    您有几个错误,例如字符串没有以null结尾,ASCII到十进制的转换是无意义的(值55?),您不初始化 sum 等等只需这样做:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
      char x[] = "AAAA";
    
      unsigned int sum = strtoul(x, NULL, 16);
      printf("%d 0X%X\n", sum, sum);
      return 0;
    }    
    

    编辑

    如果坚持手动执行此操作:

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    
    unsigned int hexstr_to_uint(const char* str);
    
    int main()
    {
      char x[] = "AAAA";
    
      unsigned int sum = hexstr_to_uint (x);
      printf("%d 0X%X\n", sum, sum);
      return 0;
    }    
    
    unsigned int hexstr_to_uint(const char* str)
    {
      unsigned int sum = 0;
    
      for(; *str != '\0'; str++)
      {
        sum *= 16;
        if(isdigit(*str))
        {
          sum += *str - '0';
        }
        else
        {
          char digit = toupper(*str);
          _Static_assert('Z'-'A'==25, "Trash systems not supported.");
          if(digit >= 'A' && digit <= 'F')
          {
            sum += digit - 'A' + 0xA;
          }
        }
      }
      return sum;
    }
    
        2
  •  0
  •   unwind    8 年前

    您只是在编逻辑,没有一个值可以从十六进制数字字符中减去,将其转换为相应的数字。

    如果您想要可移植,C所需要的只是符号 0 通过 9 在编码中是连续的。这些信件没有这样的保证 A 通过 F .

    还涉及 pow() 这是一个双精度浮点函数,在这个低级整数的工作中,有点刺耳。实现这一点的典型方法是乘法或位移位。

    如果你下定决心自己做转化,我通常会这样做:

    unsigned int hex2int(const char *a)
    {
      unsigned int v = 0;
      while(isxdigit((unsigned int) *a))
      {
        v *= 16;
        if(isdigit((unsigned int) *a))
          v += *a - '0';
        else
        {
          const char highs[] = "abcdef";
          const char * const h = strchr(highs, tolower(*a));
          v += 10 + (unsigned int) (h - highs);
        }
        ++a;
      }
      return v;
    }
    

    上面有点冗长,你可以把十进制数字折叠成字母的字符串,我只是想弄清楚。以上内容适用于任何有效的C字符集编码,而不仅仅是ASCII(而且它的被动攻击性比@Lundin的代码hih:)要小)。