今日は、あるベースから別のベースへの基本的な変換をいじっていました。16 進数から 8 進数に変換するコードを調べたところ、ほとんどの場合、10 進数または 2 進数に変換してから 8 進数に戻す中間変換が使用されていることに気付きました。また、またはprintf
のような組み込みオプションを使用したくありません。ご意見ありがとうございます。%x
%o
7 に答える
もちろん可能です。数値は、それがどのような数値システムであっても数値です。唯一の問題は、人々が 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。
4 ビットのグループを 3 ビットのグループに変換するので、少し注意が必要です。一度に 12 ビット、つまり 3 桁の 16 進数を 4 桁の 8 進数に変換する必要がある場合は、次のように対処する必要があります。残りのビットは個別に。
たとえば、5274 の 8 進数を 16 進数に変換するには:
5 2 7 4
101 010 111 100
|||/ \\// \|||
1010 1011 1100
A B C
私にはかなり簡単な作業のように思えます...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);
コンピューターのメモリ内のすべての数値は基数 2 です。そのため、値を実際に処理する (数学演算) 場合は常に、int や float などの値が必要になります。計算可能な型による変換。
値が大きすぎて数値変数に収まらない場合を除き、文字列から文字列への直接変換は避けます。信頼できるコンバーターをゼロから作成するのは驚くほど困難です。
(基数 10 を使用しても、バイナリ コンピューターではほとんど意味がありません。)
はい、比較的簡単に実行できます。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
は と に切り刻まれ1
、100
8 進数4
になり1
、次のステップのために余分なビットが作成されますB
、またはは、次のステップとこのステップのため1011
に切り刻まれます。前のステップの が の右側に付けられ、8 進数になります。10
11
1
11
7
A
、または1010
は、 と に切り刻まれ101
ます0
。前の10
ステップの が右側に付けられ、010
、または 8 進数になり2
ます。101
は 8 進数5
なので、ここ5274
までです。2
となり2
、0
次のステップへ。6
となり4
、01
次のステップへ。0
0
and になります1
(01
前のステップから追加されるため)。
最終結果は01425274
.