28

C で、16 進数の文字列をバイナリunsigned intまたはに変換する最も効率的な方法は何unsigned longですか?

たとえば、 がある場合0xFFFFFFFEintbase10 値の が必要です4294967294

4

16 に答える 16

41

あなたがしたいstrtol、またはstrtoulUnix の man ページも参照してください。

于 2008-08-13T20:22:13.357 に答える
33

編集: MSVC、C++、および非 GNU コンパイラと互換性を持つようになりました (末尾を参照)。

問題は「最も効率的な方法」でした。OPはプラットフォームを指定していません。彼は、コード用に256バイトのフラッシュストレージを備えたRISCベースのATMELチップ用にコンパイルしている可能性があります。

記録のために、そして「最も簡単な方法」と「最も効率的な方法」の違いを理解し、学習を楽しむ人々(私のように)のために...

static const long hextable[] = {
   [0 ... 255] = -1, // bit aligned access into this table is considerably
   ['0'] = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // faster for most modern processors,
   ['A'] = 10, 11, 12, 13, 14, 15,       // for the space conscious, reduce to
   ['a'] = 10, 11, 12, 13, 14, 15        // signed char.
};

/** 
 * @brief convert a hexidecimal string to a signed long
 * will not produce or process negative numbers except 
 * to signal error.
 * 
 * @param hex without decoration, case insensitive. 
 * 
 * @return -1 on error, or result (max (sizeof(long)*8)-1 bits)
 */
long hexdec(unsigned const char *hex) {
   long ret = 0; 
   while (*hex && ret >= 0) {
      ret = (ret << 4) | hextable[*hex++];
   }
   return ret; 
}

外部ライブラリは必要なく、驚くほど高速です。大文字、小文字、無効な文字、奇数サイズの 16 進入力 (例: 0xfff) を処理し、最大サイズはコンパイラによってのみ制限されます。

非 GCC または C++ コンパイラー、または派手な hextable 宣言を受け入れないコンパイラー用。

最初のステートメントを次の (より長いがより準拠した) バージョンに置き換えます。

static const long hextable[] = { 
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1, 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
};
于 2012-06-17T04:08:31.780 に答える
24

これを試して:

#include <stdio.h>
int main()
{
    char s[] = "fffffffe";
    int x;
    sscanf(s, "%x", &x);
    printf("%u\n", x);
}
于 2008-08-13T20:25:01.793 に答える
7

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

注: このコードは、大文字の AF を想定しています。len が最長整数の 32 ビットまたは 64 ビットを超えている場合は機能せず、不正な 16 進文字のエラー トラップもありません。

于 2008-09-24T23:18:41.550 に答える
5

よくあることですが、あなたの質問には重大な用語の誤り/あいまいさが含まれています。一般的な会話では、通常は問題になりませんが、この特定の問題のコンテキストでは非常に重要です。

ご覧のとおり、「16 進数」と「10 進数」(または「16 進数」と「10 進数」) というものはありません。「16 進数」と「10 進数」は、値の表現のプロパティです。一方、値 (または数値) 自体には表現がないため、「16 進数」または「10 進数」にすることはできません。たとえば、C 構文では、0xFは同じ数値15の2 つの異なる表現です。

あなたの質問は、それが述べられているように、値のASCII 16進表現(つまり文字列)を値のASCII 10進表現(別の文字列)に変換する必要があることを示唆していると思います。これを行う 1 つの方法は、整数表現を中間表現として使用することです。最初に、ASCII 16 進表現を十分なサイズの整数に変換し (strto...などの group の関数を使用strtol)、次に整数を ASCII 10 進表現に変換します ( を使用sprintf)。

それがあなたがする必要があることではない場合、あなたの質問が定式化された方法からそれを理解することは不可能であるため、あなたはあなたの質問を明確にする必要があります.

于 2010-10-29T17:10:09.480 に答える
2

例のような大きな 16 進文字列の場合は、strtoulを使用する必要がありました。

于 2008-08-14T14:29:34.500 に答える
2

@エリック

機能するコード ソリューションが反対票を投じられるのはなぜですか? 確かに、それは醜く、最速の方法ではないかもしれませんが、「strtol」や「sscanf」と言うよりも有益です。自分で試してみると、フードの下で物事がどのように起こるかについて何かを学ぶことができます.

あなたのソリューションが投票されるべきではなかったとは思いませんが、なぜそれが起こっているのかについての私の推測は、それが実用的ではないからです. 投票のアイデアは、「最良の」答えが一番上に浮かぶということです。あなたの答えは、フードの下で何が起こるか (またはそれが起こる可能性があるか) についてより有益かもしれませんが、16 進数を解析する最良の方法ではないことは間違いありません。生産システムで。

繰り返しますが、教育の観点からあなたの答えに何の問題もないと思います。一部の人があなたの回答を気に入らなかったからといって、がっかりして投稿をやめないでください。それは起こります。

私の答えで、自分の回答が反対票を投じられたことについて気分が良くなるとは思いませんが、何かが反対票を投じられた理由を尋ねても、誰も答えないのは特に楽しくないことはわかっています。

于 2008-08-14T00:21:45.417 に答える
2

16 進数から 10 進数。動作しないため、オンライン コンパイラで実行しないでください。

#include<stdio.h>
void main()
{
    unsigned int i;
    scanf("%x",&i);
    printf("%d",i);
}
于 2011-11-26T22:18:44.030 に答える
2

@エリック

私は実際に、C ウィザードが本当にクールなものを投稿するのを見たいと思っていました。

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

私は当初、比較の代わりにビットマスキングを行っていましたが、ビットマスキングが最新のハードウェアでの比較よりも高速であることを真剣に疑っています。

于 2008-08-14T01:16:16.573 に答える
1

機能するコード ソリューションが反対票を投じられるのはなぜですか? 確かに、それは醜いです...

おそらく、醜いだけでなく、教育的ではなく、機能しないためです。また、私と同じように、ほとんどの人は現在、編集する権限を持っていないと思います (必要なランクから判断すると、決して編集することはありません)。

配列を使用すると効率が向上する可能性がありますが、このコードでは言及されていません。また、大文字と小文字を考慮しないため、質問で提供されている例では機能しません。FFFFFFFE

于 2008-08-23T11:32:17.217 に答える
1
#include "math.h"
#include "stdio.h"
///////////////////////////////////////////////////////////////
//  The bits arg represents the bit say:8,16,32...                                                                                                              
/////////////////////////////////////////////////////////////
volatile long Hex_To_Int(long Hex,char bits)
{
    long Hex_2_Int;
    char byte;
    Hex_2_Int=0;

    for(byte=0;byte<bits;byte++)
    {
        if(Hex&(0x0001<<byte))
            Hex_2_Int+=1*(pow(2,byte));
        else
            Hex_2_Int+=0*(pow(2,byte));
    }

    return Hex_2_Int;
}
///////////////////////////////////////////////////////////////
//                                                                                                                  
/////////////////////////////////////////////////////////////

void main (void)
{
    int Dec;   
    char Hex=0xFA;
    Dec= Hex_To_Int(Hex,8);  //convert an 8-bis hexadecimal value to a number in base 10
    printf("the number is %d",Dec);
}
于 2012-08-04T13:51:38.600 に答える
0

これを試して、10進数から16進数に変換してください

    #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;
}
于 2010-12-19T17:39:45.453 に答える
-4

これは現在小文字でのみ機能しますが、両方で機能させるのは非常に簡単です。

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";
于 2010-10-29T17:01:32.753 に答える