0

16 進数を整数に変換するプログラムを C で作成しようとしています。8 進数を整数に変換するプログラムの作成に成功しました。しかし、文字 (af) を使い始めると問題が発生します。プログラムの私のアイデアは次の広告です。

  1. パラメータは、0x または 0X で始まる文字列である必要があります。

  2. パラメータの 16 進数は、文字列 s[] に格納されます。

  3. 整数 n は 0 に初期化され、ルールに従って変換されます。

私のコードは次のとおりです(K&Rのp37までしか読んでいないので、ポインターについてはあまり知りません):

/*Write a function htoi(s), which converts a string of hexadecimal digits (including an optional 0x or 0X) into its equivalent integer value. The allowable digits are 0 through 9, a through f, and A through F.*/

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ctype.h>

int htoi(const char s[]) { //why do I need this to be constant??
    int i;
    int n = 0;
    int l = strlen(s);
    while (s[i] != '\0') {
        if ((s[0] == '0' && s[1] == 'X') || (s[0] == '0' && s[1] == 'x')) {
            for (i = 2; i < (l - 1); ++i) {
                if (isdigit(s[i])) {
                    n += (s[i] - '0') * pow(16, l - i - 1);
                } else if ((s[i] == 'a') || (s[i] == 'A')) {
                    n += 10 * pow(16, l - i - 1);
                } else if ((s[i] == 'b') || (s[i] == 'B')) {
                    n += 11 * pow(16, l - i - 1);
                } else if ((s[i] == 'c') || (s[i] == 'C')) {
                    n += 12 * pow(16, l - i - 1);
                } else if ((s[i] == 'd') || (s[i] == 'D')) {
                    n += 13 * pow(16, l - i - 1);
                } else if ((s[i] == 'e') || (s[i] == 'E')) {
                    n += 14 * pow(16, l - i - 1);
                } else if ((s[i] == 'f') || (s[i] == 'F')) {
                    n += 15 * pow(16, l - i - 1);
                } else {
                    ;
                }
            }
        }
    }
    return n;
}


int main(void) {
    int a = htoi("0x66");
    printf("%d\n", a);
    int b = htoi("0x5A55");
    printf("%d\n", b);
    int c = htoi("0x1CA");
    printf("%d\n", c);
    int d = htoi("0x1ca");
    printf("%d\n", d);
} 

私の質問は次のとおりです。

1. htoi(s) の引数に const を使用しない場合、g++ コンパイラから次の警告が表示されます。

2-3.c: 関数 'int main()' 内: 2-3.c:93:20: 警告: 文字列定数から 'char*' への非推奨の変換 [-Wwrite-strings] 2-3.c:97 :22: 警告: 文字列定数から 'char*' への非推奨の変換 [-Wwrite-strings] 2-3.c:101:21: 警告: 文字列定数から 'char*' への非推奨の変換 [-Wwrite-strings] 2 -3.c:105:21: 警告: 文字列定数から 'char*' への非推奨の変換 [-Wwrite-strings]

どうしてこれなの?

2.プログラムの実行に時間がかかるのはなぜですか? 私はまだ結果を見ていません。

3. ターミナルで g++ 2-3.c の代わりに cc 2-3.c と入力すると、次のエラー メッセージが表示されるのはなぜですか。

「`pow' への未定義の参照」

累乗関数を使用したすべての行で?

4. 私のプログラムの他のエラー/改善の可能性を指摘してください。

4

6 に答える 6

1

C プログラムのコンパイルに C++ コンパイラを使用しないでください。それがあなたへの私の最初のアドバイスです。

次にconst、 a の関数パラメーターでchar *、プログラマーが誤って文字列を変更しないようにします。

-lm第三に、上記のように数学ライブラリを含める必要があります。

于 2012-10-22T08:43:37.290 に答える
1

私は自分でこの演習を行ったところですが、主なアイデアの 1 つは、文字を整数として比較できるという知識を使用することだったと思います (これについては第 2 章で説明しています)。

参照用の私の関数は次のとおりです。この本には演習の答えが含まれていないので、役に立つかもしれないと思った.

int htoi(char s[]) {
    int i = 0;
    if(s[i] == '0') {
        ++i;
        if(s[i] == 'x' || s[i] == 'X') {
          ++i;
        }
    }

    int val = 0;

    while (s[i] != '\0') {
        val = 16 * val;
        if (s[i] >= '0' && s[i] <= '9')
            val += (s[i] - '0');
        else if (s[i] >= 'A' && s[i] <= 'F') 
            val += (s[i] - 'A') + 10;
        else if (s[i] >= 'a' && s[i] <= 'f')
            val += (s[i] - 'a') + 10;
        else {
            printf("Error: number supplied not valid hexadecimal.\n");
            return -1;
        }           
        ++i;
    }

    return val;
}
于 2012-12-23T00:08:24.027 に答える
1
  1. char[] は、const関数内で変更できないことを意味します。constaから not- へのキャストconstは警告を発します。について語るべきことはたくさんありますconstウィキペディアのページをチェックしてください。
  2. --
  3. おそらく、cc適切なライブラリをリンクしていません。次のビルド コマンドを試してください。cc 2-3.c -lm

改良点:

  1. は使用しないでくださいpow()。処理時間の点でかなりコストがかかります。
  2. 固定の「マジック」ナンバーを使用する代わりに、数字と同じトリックを文字で使用して値を取得します。
  3. else最後の部分は必要ありません。空のままにしておきます (または、これらの文字は許可されていないため、そこにエラー メッセージを入力します)。

幸運を!

pow()呼び出しに関する私の発言について(hexchar_to_int()上記の関数を使用して、これを実装する方法です(エラーチェックなし):

  const char *t = "0x12ab";
  int i = 0, n = 0;
  int result = 0;
  for (i = 2; i < strlen(t); i++) {
   n = hexchar_to_int(t[i]);

   result |= n; 
   result <<= 4;
  } 

  /* undo the last shift */
  result >>= 4;
于 2012-10-22T08:34:30.097 に答える
1

htoi(s) の引数に const を使用しない場合、g++ コンパイラから次の警告が表示されます

ポインターから const を決して型キャストしないことは、適切で適切なプログラミングと見なされるため、const パラメーターはそこにある必要があります。文字列リテラル "..." は定数として扱う必要があるため、const をパラメーターとして使用しない場合、コンパイラーは const 修飾子をキャストしていると見なします。

さらに、内容を変更するつもりのないすべてのポインター パラメーターを const として宣言する必要があります

プログラムの実行に時間がかかるのはなぜですか? 私はまだ結果を見ていません。

私は主にあなたが初期化を間違えたからだと思います。int i;私はごみを含んでいます。それからwhile (s[rubbish_value] != '\0')。この関数は、はるかに優れたものにすることもできます。文字列の先頭にある 0x をチェックすることから始めます。存在しない場合はエラーを通知し (NULL を返しますか?)、そうでない場合は破棄します。その後、1 つのループを開始します。2 つのループは必要ありません。

pow() 関数は浮動小数点数を扱うため、プログラムが少し遅くなることに注意してください。整数のみのバージョンの使用を検討できます。残念ながら、標準 C にはそのような関数がないため、別の場所で見つける必要があります。

また、ctype.h の標準関数である関数 isxdigit() について考えてみましょう。この関数は、0 ~ 9 の数字と 16 進数の文字 AF または af をチェックします。ただし、数字と文字に対して異なる計算を実行する必要があるため、パフォーマンスが向上しない場合があります。

価値があるのは、単一の char を 16 進数の int に変換する方法を示すスニペットです。これは可能な限り最適化されたバージョンではありませんが、読みやすさと移植性を高めるために、利用可能な標準関数を利用しています。

#include <ctype.h>

uint8_t hexchar_to_int (char ch)
{
  uint8_t result;

  if(isdigit(ch))
  {
    result = ch - '0';
  }
  else if (isxdigit(ch))
  {
    result = toupper(ch) - 'A' + 0xA;
  }
  else
  {
    // error
  }

  return result;
}
于 2012-10-22T09:01:47.493 に答える
0

常に変数を初期化してくださいint i=0。そうしないiと、ガベージ値が含まれます。期待どおりに 0 である必要はなく、任意の数値にすることができます。while ステートメントを無限ループで実行しているため、結果を取得するのに永遠に時間がかかります。 i を出力して理由を確認してください。また、文字列が 0x で始まらない場合にブレークを追加すると、ユーザーがランダムな文字列で使用されたときに同じループの問題が回避されます。他の人が言及しているように、関数を含むライブラリをインポートし、警告を取り除くためにpow文字列を宣言する必要があります。const

于 2012-10-22T08:56:43.487 に答える
0

これは、上記の質問に対する私のバージョンのプログラムです。オプションのプレフィックス (0x または 0X) に関係なく、16 進数の文字列を 10 進数に変換します。使用される 4 つの重要なライブラリ関数は、strlen(s)、isdigit(c)、isupper(c)、isxdigit(c)、pow(m,n) です。

コードを改善するための提案は大歓迎です:)

/*Program  - 5d Function that converts hex(s)into dec -*/
#include<stdio.h>
#include<stdlib.h>
#include<math.h>                //Declares mathematical functions and macros
#include<string.h>              //Refer appendix in Page 249 (very useful)
#define HEX_LIMIT 10

int hex_to_dec(char hex[])      //Function created by me :)
{
   int dec = 0;                //Initialization of decimal value
   int size = strlen(hex);     //To find the size of hex array
   int temp = size-1 ;         //Pointer pointing the right element in array
   int loop_limit = 0;         //To exclude '0x' or 'OX' prefix in input

   if(hex[0]=='0' && ((hex[1]=='x')  || (hex[1]=='X')))
   loop_limit = 2;

   while(temp>=loop_limit)
   {
     int hex_value = 0;        //Temporary value to hold the equivalent hex digit in decimal

     if(isdigit(hex[temp]))
       hex_value = (hex[(temp)]-'0') ;
     else if(isxdigit(hex[temp]))
        hex_value =  (toupper(hex[temp])-'A' + 10);
     else{
        printf("Error: No supplied is not a valid hex\n\n");
        return -1;
      }

    dec += hex_value * pow(16,(size-temp-1));        //Computes equivalent dec from hex
    temp--;                    //Moves the pointer to the left of the array
   }
   return dec;
}

int main()
{
char hex[HEX_LIMIT];
printf("Enter the hex no you want to convert: ");
scanf("%s",hex);
printf("Converted no in decimal: %d\n", hex_to_dec(hex));

return 0;
}
于 2015-05-25T00:57:18.230 に答える