1

16 進数形式「0d76」の char 配列があり、それを 10 進数形式に変換したいのですが、エラーが発生します。

incompatible types in assignment of 'int' to 'char [(((sizetype)(((ssizetype)size) + -1)) + 1)]'

これが私のコードです:

const char input[] = "0d76";
int size = strlen(input);
char hex_array[size];
for(int i = 0; i < size; i++)
{
   if ('0' <= input[i] && input[i] <= '9') 
   {
       hex_array = input[i] - '0';
   } 
   if ('a' <= input[i] && input[i] <= 'f') 
   {
       hex_array = 10 + (input[i] - 'a');
   } 
   if ('A' <= input[i] && input[i] <= 'F') 
   {
       hex_array = 10 + (input[i] - 'A');
   } 
}

望ましい出力は、0D76を入力した場合、10 進形式で3446が得られることです。

同様に、誰かがライブラリ関数を使用せずに char 配列を 16 進数から 10 進数に変換するより良い方法を持っている場合、私はそれを感謝します。

4

4 に答える 4

1

私は... これに対する他の多くの回答の質について非常に確信が持てません.

基本的な問題は単純です。配列は C では割り当て可能なオブジェクトではなく、配列に直接割り当てることはできません。

二次的な問題は、16 進数の文字列を 10 進数の文字列に変換する方法になります。通常、予想される最善の方法は、もちろん、ライブラリ関数を使用することです。ライブラリ関数は、既に作成、デバッグ、テストされており、他のプログラマーによく知られており、コードをより理解しやすくするのに役立ちます。

ライブラリ作成者の足跡をたどりたい場合や、手を汚して自分で低レベルの変換を行いたい場合は、もちろん問題ありません。2つのステップで、これを行う方法は次のとおりです。

  1. 16 進文字列を (バイナリ) 整数 [strtoul()ライブラリ内] に変換します。
  2. 整数を 10 進文字列 [ライブラリ: snprintf()] に変換します。

コード:

unsigned long hex_to_ulong(const char *hex)
{
  unsigned long x = 0;

  while(isxdigit((unsigned int) *hex))
  {
    const unsigned int here = tolower((unsigned int) *hex++);
    x *= 16;
    if(isdigit(here))
      x += here - '0';
    else if(here == 'a') /* NOTE: Don't assume anything about the a-f encoding. */
      x += 10;
    else if(here == 'b')
      x += 11;
    else if(here == 'c')
      x += 12;
    else if(here == 'd')
      x += 13;
    else if(here == 'e')
      x += 14;
    else if(here == 'f')
      x += 15;
  }
  return x;
}

そして、2 番目の部分のコードは通常、次のようになります。

/* Create decimal string version of x in the given buffer, returning pointer to
 * the first digit, which is *not* necessarily at out[0].
*/
char * ulong_to_dec(char *out, size_t out_max, unsigned long x)
{
    char *put = out + out_max;
    *--put = '\0';
    do {
      if(put == out)
        return NULL;
      *--put = '0' + (x % 10);
      x /= 10;
    } while(x != 0);
    return put + 1;
}

次に、問題は基本的に次のようになります。

const char input[] = "0d76";
const unsigned long x = hex_to_ulong(input);
char dec_array[10];
char *dec = ulong_to_dec(dec_array, sizeof dec_array, x);
puts(dec);

:上記のコードはテストされておらず、やや面倒なので、バグがある可能性がありますが、アイデアは得られます。

于 2013-10-04T07:12:27.177 に答える
1

ここで実装が間違っており、割り当て中のchar配列の使用も

hex_array を整数配列として宣言します

   int hex_array[size]; 


  if ('0' <= input[i] && input[i] <= '9') 
   {
       hex_array[i] = input[i] - '0'; // this converts  , Ascii digit to integer digit
               //^^ make change here
   } 
   if ('a' <= input[i] && input[i] <= 'f') 
   {
       hex_array[i] = 10 + (input[i] - 'a'); // here this convers d==>13   
   } 
   if ('A' <= input[i] && input[i] <= 'F') 
   {
       hex_array[i] = 10 + (input[i] - 'A'); //this convers D ==>13 and assigns to array  
   } 

あなたが入力を与える場合

"0D76"

hex_array[0]=0,hex_array[1]=13, hex_array[2]=7,hex_array[4]=6.

これで、16 進文字の 10 進値が得られました。

次に、ループを使用して、hex_array の各値を基数 16 の位置の値で乗算します。

       double decimal=0; 
       int i;
       for(i = 0; i < size; i++)
       decimal=decimal+hex_array[i]*pow(16,size-1-i);

10 進数の構成、16 進数入力の 10 進数値。

于 2013-10-04T03:03:05.990 に答える
0

これはおそらくここで何百万回も尋ねられてきましたが、これは を介し​​た単純な一般的な解決策でありinttolower()(大文字または小文字のいずれかを主張することで回避できます) およびstrlen()(きれいに回避するのは困難であり、とにかくあなたのコードで使用してください):

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

int st_to_int(char * st, int base);
void int_to_st(int n, char * buffer, int base);
void reverse_string(char * buffer);

int main(void) {
    char input[] = "0D76";

    int n = st_to_int("0D76", 16);
    printf("Hex string '%s' converted to an int is %d.\n", input, n);

    char buffer[100];
    int_to_st(n, buffer, 10);
    printf("%d converted to a decimal string is '%s'.\n", n, buffer);

    int_to_st(n, buffer, 16);
    printf("%d converted to a hex string is '%s'.\n", n, buffer);

    return EXIT_SUCCESS;
}

int st_to_int(char * st, int base) {
    static const char digits[] = {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
        'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
        'u', 'v', 'w', 'x', 'y', 'z'
    };

    int result = 0;

    while ( *st ) {
        result *= base;
        for ( int i = 0; i < (int) sizeof(digits); ++i ) {
            if ( digits[i] == tolower(*st) ) {
                result += i;
                break;
            }
        }
        ++st;
    }

    return result;
}

void int_to_st(int n, char * buffer, int base) {
    static const char digits[] = {
        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
        'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
        'u', 'v', 'w', 'x', 'y', 'z'
    };

    int i = 0;
    while ( n > 0 ) {
        int next_digit = n % base;
        n = n / base;
        buffer[i++] = digits[next_digit];
    }
    buffer[i] = 0;

    reverse_string(buffer);
}

void reverse_string(char * buffer) {
    int buflen = strlen(buffer) + 1;
    char revbuf[buflen];

    int i;
    for ( i = 0; i < buflen - 1; ++i ) {
        revbuf[i] = buffer[buflen - 2 - i];
    }
    revbuf[i] = 0;

    for ( i = 0; i < buflen; ++i ) {
        buffer[i] = revbuf[i];
    }
}

出力が得られます:

paul@local:~/src/c/scratch/strconv$ ./strconv
Hex string '0D76' converted to an int is 3446.
3446 converted to a decimal string is '3446'.
3446 converted to a hex string is 'd76'.
paul@local:~/src/c/scratch/strconv$

このコードは、バッファ オーバーフローや無効な入力 (英数字以外の入力など) をチェックしません。演習として残します。同様に、負の数や 0 は処理しません。変更するのは簡単ですが、「複雑/長い」ことは避けたいと考えていました。

于 2013-10-04T03:55:09.800 に答える
0

以下は、時期尚早に最適化された例です。

int h2i(int c){             /* use bit hacks to hex char -> int */
    if ((unsigned)c-'0'<10) return(c-'0');
    if (((unsigned)c|32)-'a'<6) return(((unsigned)c|32)-'a'+10);
    return -1;
}

int s2i(char *s){
    int i,ret=0;
    while(*s=='0'||*s=='x')*s++;    /* handle 0000ff... and 0xff... */
    while(*s){
        i=h2i(*s);
        if (i==-1) return 0;
        else ret=(ret<<4)|i;
    }
  return ret;
}

char *i2s(int n){
    static char buf[(sizeof(int)<<1)+1]={0};
    int i=0;
    while(i<(sizeof(int)<<1)+1){    /* mask the ith hex, shift it to lsb */
//      buf[i++]='0'+(0xf&(n>>((sizeof(int)<<3)-i<<2))); /* less optimizable ??? */
        buf[i++]='0'+(0xf&((n&(0xf<<((sizeof(int)<<3)-i<<2)))>>((sizeof(int)<<3)-i<<2)));
        if(buf[i-1]>'9')buf[i-1]+=('A'-'0'-10); /* handle A-F */
    }
    for(i=0;buf[i++]=='0';)
        /*find first non-zero*/;
    return (char *)buf+i;
}


#include <stdio.h>
int main(void){
    printf("%s\n",i2s(0xf768cbaf));
    return printf("%X\n",s2i("0xf768cbaf"));
}
于 2013-10-04T03:25:09.393 に答える