4

今日は、あるベースから別のベースへの基本的な変換をいじっていました。16 進数から 8 進数に変換するコードを調べたところ、ほとんどの場合、10 進数または 2 進数に変換してから 8 進数に戻す中間変換が使用されていることに気付きました。また、またはprintfのような組み込みオプションを使用したくありません。ご意見ありがとうございます。%x%o

4

7 に答える 7

5

もちろん可能です。数値は、それがどのような数値システムであっても数値です。唯一の問題は、人々が 10 進数に慣れていることです。任意のベースから別のベースに変換できます。

EDIT:変換を実行する方法の詳細。

最初に、3 桁の 16 進数が正確に 4 桁の 8 進数にマップされることに注意してください。したがって、16 進数の桁数があれば、8 進数の桁数を簡単に見つけることができます。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int get_val(char hex_digit) {
  if (hex_digit >= '0' && hex_digit <= '9') {
    return hex_digit - '0';
  } else {
    return hex_digit - 'A' + 10;
  }
}
void convert_to_oct(const char* hex, char** res) {
  int hex_len = strlen(hex);
  int oct_len = (hex_len/3) * 4;
  int i;

  // One hex digit left that is 4 bits or 2 oct digits.
  if (hex_len%3 == 1) {
    oct_len += 2;
  } else if (hex_len%3 == 2) { // 2 hex digits map to 3 oct digits
    oct_len += 3;
  }

  (*res) = malloc((oct_len+1) * sizeof(char));
  (*res)[oct_len] = 0; // don't forget the terminating char.

  int oct_index = oct_len - 1; // position we are changing in the oct representation.
  for (i = hex_len - 1; i - 3 >= 0; i -= 3) {
    (*res)[oct_index] = get_val(hex[i]) % 8 + '0';
    (*res)[oct_index - 1] = (get_val(hex[i])/8+ (get_val(hex[i-1])%4) * 2) + '0';
    (*res)[oct_index - 2] = get_val(hex[i-1])/4 + (get_val(hex[i-2])%2)*4 + '0';
    (*res)[oct_index - 3] = get_val(hex[i-2])/2 + '0'; 
    oct_index -= 4;
  }

  // if hex_len is not divisible by 4 we have to take care of the extra digits:
  if (hex_len%3 == 1) {
     (*res)[oct_index] = get_val(hex[0])%8 + '0';
     (*res)[oct_index - 1] = get_val(hex[0])/8 + '0';
  } else if (hex_len%3 == 2) {
     (*res)[oct_index] = get_val(hex[1])%8 + '0';
     (*res)[oct_index - 1] = get_val(hex[1])/8 + (get_val(hex[0])%4)*4 + '0';
     (*res)[oct_index - 2] = get_val(hex[0])/4 + '0';
  }
}

また、ここに ideone の例があるので、それで遊ぶことができます: example

于 2013-01-10T15:14:51.073 に答える
3

4 ビットのグループを 3 ビットのグループに変換するので、少し注意が必要です。一度に 12 ビット、つまり 3 桁の 16 進数を 4 桁の 8 進数に変換する必要がある場合は、次のように対処する必要があります。残りのビットは個別に。

たとえば、5274 の 8 進数を 16 進数に変換するには:

5    2    7    4
101  010  111  100

|||/   \\//   \|||

1010   1011   1100
A      B      C
于 2013-01-10T15:31:15.003 に答える
1

私にはかなり簡単な作業のように思えます...16進文字列が必要で、それを8進文字列に変換したいとします。ASCII hex を int 型に変換して操作しましょう。

char hex_value[] = "0x123";

int value = strtol(hex_value,NULL,16);

この時点ではまだ 16 進数です。ある基数から別の基数に変換したい場合は、次の簡単な計算を行うことができます。

123 / 8 = 24 R 3
 24 / 8 =  4 R 4
  4 / 8 =  0 R 4

これは 123 16 == 443 8であることを示しているので、その計算を基本的な関数に書き込んで、最終的な値を文字列に戻すだけです。

char * convert_to_oct(int hex)
{
    int ret = 0, quotient = 0, reminder = 0, dividend = hex, counter = 0, i;
    char * ret_str;   // returned string

    while(dividend > 0){             // while we have something to divide
        quotient = dividend / 0x8;   // get the quotient
        reminder = dividend - quotient * 0x8; // get the reminder

        ret += reminder * pow(10, counter);   // add the reminder (shifted) 
                                              // into our return value
        counter++;            // increment our shift
        dividend = quotient;  // get ready for the next divide operation
    }

    ret_str = malloc(counter);   // allocate the right number of characters
    sprintf(ret_str, "%d", ret); // store the result

    return ret_str;
}

したがって、この関数は 16 進数 (int) 値を 8 進数文字列に変換します。次のように呼び出すことができます。

int main()
{
   char hex_value[] = "0x123";
   char * oct_value;
   int value = strtol(hex_value,NULL,16);

   // sanity check, see what the value should be before the convert
   printf("value is %x, auto convert via printf gives %o\n", value, value);

   oct_value = convert_to_oct(value);
   printf("value is %s\n", oct_value);
于 2013-01-10T19:13:13.437 に答える
1

コンピューターのメモリ内のすべての数値は基数 2 です。そのため、値を実際に処理する (数学演算) 場合は常に、int や float などの値が必要になります。計算可能な型による変換。

値が大きすぎて数値変数に収まらない場合を除き、文字列から文字列への直接変換は避けます。信頼できるコンバーターをゼロから作成するのは驚くほど困難です。

(基数 10 を使用しても、バイナリ コンピューターではほとんど意味がありません。)

于 2013-01-10T15:26:02.497 に答える
1

はい、比較的簡単に実行できます。4 つの 8 進数は常に 3 つの 16 進数に変換されるため、文字列を 3 つの 16 進数のグループに分割し、各グループを後ろから処理できます。3 つのグループを完成させるのに十分な 16 進数がない場合は、先行ゼロを追加します。

各 16 進数は 4 ビットになります。最後の 3 つを取り、それらを 8 進数に変換します。次の 4 ビットを加算し、さらに 3 ビットを 8 進数にします。最後の 4 つのグループを追加します。これで合計 6 ビットになったので、それらを 2 桁の 8 進数に変換します。

これにより、数値全体をバイナリに変換することは回避されますが、数値を変換するプロセスで使用される「スライド」バイナリ ウィンドウが存在します。

62ABC例を考えてみましょう: 8 進数への変換。3 桁のグループに分けます:062およびABC(3 桁のグループを作成するために の前に追加されたゼロに注意してください62)。

後ろから始めます:

  • C、または1100は と に切り刻まれ11008 進数4になり1、次のステップのために余分なビットが作成されます
  • B、またはは、次のステップとこのステップのため1011に切り刻まれます。前のステップの が の右側に付けられ、8 進数になります。10111117
  • A、または1010は、 と に切り刻まれ101ます0。前の10ステップの が右側に付けられ、010、または 8 進数になり2ます。101は 8 進数5なので、ここ5274までです。
  • 2となり20次のステップへ。
  • 6となり401次のステップへ。
  • 00and になります1(01前のステップから追加されるため)。

最終結果は01425274.

于 2013-01-10T15:18:41.257 に答える