2017-01-26 6 views
0

2桁を超えると失敗します....16進数を整数に変換するCプログラム

例:入力:0xf出力:15
しかし、入力:0xFF出力:-1

char s[20],hexdigit=0,i=0,deci=0; 
scanf("%[^\n]",s); 
if(s[0]=='0' && (s[1]== 'X' || s[1]=='x')) 
    i=2; 
for(;s[i]!='\0';i++){ 

    if(s[i]>='0' && s[i]<='9') 
     hexdigit=s[i]-'0'; 
    else if(s[i]>='a' && s[i]<='f') 
     hexdigit=s[i]-'a'+10; 
    else if(s[i]>='A' && s[i]<='F') 
     hexdigit=s[i]-'A'+10; 
    else 
     break; 
    deci=(16*deci)+hexdigit; 
} 
    printf("\n%d",deci); 
+4

http://ericlippert.com/2014/03/05/how-to-debug-small-programs/ – Biffen

+1

:コードは次のようになります... – John3136

+4

'deci'はちょうど' char'です - あなたはそれを適切な 'int'型にする必要があります。 –

答えて

5

タイプは、システム上のchar-128+127間の値のみを保存することができます。より広い範囲を取得するには、別のデータ型を使用します。代わりに、このタイプの意志もオーバーフローが、ずっと後

char deci = 0; 

書き込み

int deci = 0; 

。通常は2147483647です。より大きな値を解析しようとすると、の動作は定義されていません

あなたは、このタイプは、4294967295でオーバーフローするまでのことはここで0はありません未定義の動作を再び開始します

unsigned int deci = 0; 

を書き込むことによって、1ビットさらに行くことができます。

+3

は符号なしの型を使用することを提案しています。なぜなら、コードでは負の値が読み取られるだけで、整数のオーバーフローが回避されるからです。UB –

+0

提案を追加しました。 –

+0

人評判が高い人は評判が高いですが、それがどれほどうまくいっても、私の答えにはこのような多くのアップフォースはありませんでした。 –

0

charを使用していて、値は-128+127の間しか格納できません。代わりに他のデータ型を使用して、より大きな範囲を取得します。

ので、代わりの

char deci = 0; 

使用int

int deci = 0; 

、それがオーバーフローした場合でも、あなたはunsigned int(あなたのコードだけ読むと非負値)を使用することができます

unsigned int = 0; 

Cスタンドdは、charが少なくとも8ビット幅であり、shortintは少なくとも16ビット幅で、longは少なくとも32ビット幅で、さらにsizeof (char) <= sizeof (short) <= sizeof (int) <= sizeof (long)でなければなりません(これらのタイプの符号なしバージョンでも同じです)。

intは、プラットフォームに応じて16〜64ビットの幅を持つことができます。

また、今後コードの実行に失敗する可能性のある問題があります。

あなたの配列添字icharで、コンパイラがあなたに

警告を与えている必要があります。配列の添字は、「文字」を入力しています。

タイプcharには、コンパイラが署名したり、署名を付けたりすることができないので、これが与えられています。 charが署名されている場合は、iが負である可能性があります。負の配列インデックスにアクセスすると、未定義の動作になります。 今後の共通の落とし穴を避けるために、このanswerを見ることを強くお勧めします。

ヒント:常にコードをフォーマットする適切に視覚化したり、問題を見つけようとしている他の人にも役立ちます。

Downvoter Care To Explainなぜ彼はdownvoted。

+0

これは、署名されていない、私は様々なデータ型のこの男の限界を説明するためのドキュメントに適切なテキストを見つけることが含まれていませんでした。 –

+0

@RadLexusこれは、署名のない、加えて私は様々なデータ型のこの男の限界を説明するためのドキュメントに適切なテキストを見つける –

0

最初に、変換するときに、16進数がどのように表されるかを考慮する必要があります。リトルエンディアンなので、文字列の右端から始める必要があります。

次に、各ステップで、16進数の変換には16進数(16進の変換であるため)が必要です。

その後、あなたは他のASCII表現(単なるバイナリ)を減算する方法を決定しなければならないので、例えば:

  1. 'E' - 'A' を生成します1110(E) - 1010(A) = 0100(減算4又は小数値 )
  2. 小数範囲AFのオフセットので、10を追加:0100(EA)+ 1010(10)= 14
  3. 乗算16のベース電力によって所定の位置に(そう0)

このアルゴリズムを適用して、あらゆる場合に16進変換を得ることができます。あなたがそこに持っているchar型の変数の多くTha'ts

#include <stdio.h> 
#include <math.h> 
int htoi(char s[]); 
int my_strlen(char s[]); 


int main(int argc, char **argv) { 
    unsigned long int val; 
    val = htoi("0x4E"); //Check N 
    if (val > 0) 
     printf("Value val: %lu", val); 
    else 
     printf("improperly formatted"); 
    return 0; 
} 

//Coded for example 
int htoi(char s[]) { 
    int i, j; 
    unsigned long int z; 
    i = z = 0; 
    j = my_strlen(s) - 1; 

    if(j < 2) return z; 
    if (s[i++] != '0') return z; 
    if (s[i] != 'X' && s[i] != 'x') return z; 

    //Reset i to represent position 
    i = 0; 
    //Convert hexidecimal to integer 
    for(i = 0; s[j] != 'x' && s[j] != 'X'; j--, i++) { 
     if(s[j] >= '0' && s[j] <= '9') 
      z = z + (s[j] - '0') * pow(16, i); 
     else if(s[j] >= 'a' && s[j] <= 'f') 
      z = z + ((s[j] - '0') + 1) * pow(16, i); 
     else if(s[j] >= 'A' && s[j] <= 'F') 
      z = z + ((s[j] - 'A') + 10) * pow(16,i); 
     else 
      continue; 
    } 
    return z; 
} 

//Coded for example 
int my_strlen(char s[]) { 
    int i = 0; 
    while(s[i] != '\0') 
     i++; 
    return i; 
} 
関連する問題