在C中有效地将十六进制字符串转换为整数?

时间:2020-03-05 18:39:29  来源:igfitidea点击:

在C语言中,将一串十六进制数字转换为二进制" unsigned int"或者" unsigned long"的最有效方法是什么?

例如,如果我有0xFFFFFFFE,我想要一个int,其base10值为4294967294

解决方案

回答

我们需要strtol或者strtoul。另请参见Unix手册页

回答

试试这个:

#include <stdio.h>
int main()
{
    char s[] = "fffffffe";
    int x;
    sscanf(s, "%x", &x);
    printf("%u\n", x);
}

回答

埃里克

Why is a code solution that works getting voted down? Sure, it's ugly and might not be the fastest way to do it, but it's more instructive that saying "strtol" or "sscanf". If you try it yourself you will learn something about how things happen under the hood.

我真的不认为解决方案应该被否决,但是我对它为什么会发生的猜测是因为它不太实用。投票的想法是,"最佳"答案将浮动到顶部,尽管答案可能对幕后发生的事情(或者可能的发生方式)更具指导意义,但绝对不是解析十六进制数字的最佳方法在生产系统中。

同样,从教育的角度来看,我认为答案没有任何问题,我当然不会(也不会)否决它。不要因为有些人不喜欢答案之一而灰心丧志,停止发布。它发生了。

我怀疑我的回答会使我们对自己的被否决感觉更好,但是当我们问为什么某件事被否决而没有人回答时,我知道这尤其不好玩。

回答

埃里克

I was actually hoping to see a C wizard post something really cool, sort of like what I did but less verbose, while still doing it "manually".

好吧,我不是C专家,但这是我想出的:

unsigned int parseHex(const char * str)
{
    unsigned int val = 0;
    char c;

    while(c = *str++)
    {
        val <<= 4;

        if (c >= '0' && c <= '9')
        {
            val += c & 0x0F;
            continue;
        }

        c &= 0xDF;
        if (c >= 'A' && c <= 'F')
        {
            val += (c & 0x07) + 9;
            continue;
        }

        errno = EINVAL;
        return 0;
    }

    return val;
}

我本来要比比较进行更多的位屏蔽,但是我严重怀疑位屏蔽比在现代硬件上进行比较要快得多。

回答

对于较大的十六进制字符串(如示例中所示),我需要使用strtoul。

回答

Why is a code solution that works
  getting voted down? Sure, it's ugly
  ...

也许是因为它既丑陋又没有教育意义,而且行不通。另外,我怀疑像我一样,大多数人目前没有编辑的能力(并且从不需要的等级来判断)。

数组的使用可以提高效率,但是此代码中未提及。
它还不考虑大小写,因此不适用于问题中提供的示例。 FFFFFFFE

回答

如果没有stdlib,则必须手动进行操作。

unsigned long hex2int(char *a, unsigned int len)
{
    int i;
    unsigned long val = 0;

    for(i=0;i<len;i++)
       if(a[i] <= 57)
        val += (a[i]-48)*(1<<(4*(len-1-i)));
       else
        val += (a[i]-55)*(1<<(4*(len-1-i)));

    return val;
}

注意:此代码假定大写A-F。如果len超出最长的32位或者64位整数,则此方法不起作用,并且对于非法的十六进制字符也没有错误捕获。

回答

目前这仅适用于小写字母,但超级容易使两者同时使用。

cout << "\nEnter a hexadecimal number: ";
cin >> hexNumber;
orighex = hexNumber;

strlength = hexNumber.length();

for (i=0;i<strlength;i++)
{
    hexa = hexNumber.substr(i,1);
    if ((hexa>="0") && (hexa<="9"))
    {
        //cout << "This is a numerical value.\n";
    }
    else
    {
        //cout << "This is a alpabetical value.\n";
        if (hexa=="a"){hexa="10";}
        else if (hexa=="b"){hexa="11";}
        else if (hexa=="c"){hexa="12";}
        else if (hexa=="d"){hexa="13";}
        else if (hexa=="e"){hexa="14";}
        else if (hexa=="f"){hexa="15";}
        else{cout << "INVALID ENTRY! ANSWER WONT BE CORRECT\n";}
    }
    //convert from string to integer

    hx = atoi(hexa.c_str());
    finalhex = finalhex + (hx*pow(16.0,strlength-i-1));
}
cout << "The hexadecimal number: " << orighex << " is " << finalhex << " in decimal.\n";

回答

就像经常发生的那样,问题遇到了严重的术语错误/歧义。通常来说,这并不重要,但是在这个特定问题的背景下,它至关重要。

我们会发现,没有"十六进制值"和"十进制值"(或者"十六进制数"和"十进制数")之类的东西。 "十六进制"和"十进制"是值表示的属性。同时,值(或者数字)本身没有表示形式,因此它们不能为"十六进制"或者"十进制"。例如,C语法中的" 0xF"和" 15"是相同数字的两个不同表示形式。

我想问题就这么说了,这表明我们需要将值(即字符串)的ASCII十六进制表示形式转换为值(另一个字符串)的ASCII十进制表示形式。一种实现方法是使用整数表示形式作为中间表示形式:首先,将ASCII十六进制表示形式转换为足够大小的整数(使用来自strto ...组的函数,例如strtol),然后转换整数转换成ASCII十进制表示形式(使用sprintf)。

如果这不是我们需要做的,那么我们必须澄清问题,因为不可能从提出问题的方式中弄清楚。

回答

尝试将此从十进制转换为十六进制

#include<stdio.h>
    #include<conio.h>

    int main(void)
    {
      int count=0,digit,n,i=0;
      int hex[5];
      clrscr();
      printf("enter a number   ");
      scanf("%d",&n);

      if(n<10)
      {
          printf("%d",n);
      }

      switch(n)
      {
          case 10:
              printf("A");
            break;
          case 11:
              printf("B");
            break;
          case 12:
              printf("B");
            break;
          case 13:
              printf("C");
            break;
          case 14:
              printf("D");
            break;
          case 15:
              printf("E");
            break;
          case 16:
              printf("F");
            break;
          default:;
       }

       while(n>16)
       {
          digit=n%16;
          hex[i]=digit;
          i++;
          count++;
          n=n/16;
       }

       hex[i]=n;

       for(i=count;i>=0;i--)
       {
          switch(hex[i])
          {
             case 10:
                 printf("A");
               break;
             case 11:
                 printf("B");
               break;
             case 12:
                 printf("C");
               break;
             case  13:
                 printf("D");
               break;
             case 14:
                 printf("E");
               break;
             case 15:
                 printf("F");
               break;
             default:
                 printf("%d",hex[i]);
          }
    }

    getch();

    return 0;
}