2013-01-10 73 views
4

今天我只是在玩基本轉換從一個基地到另一個。我注意到一些代碼從十六進制轉換爲八進制,我注意到它大多使用中間轉換爲十進制或二進制,然後回到八進制。它可以寫我自己的函數來將十六進制字符串轉換爲八進制字符串,而不使用任何中間轉換。我也不想使用內置printf選項,如%x%o。感謝您的投入。十六進制到八進制的轉換程序不使用十進制或二進制

+0

http://www.physicsforums.com/showthread.php?t=40575 – 2013-01-10 15:16:57

+1

這是一個有點棘手,因爲你會被轉換的4位組的3位組 - 你可能要一次處理12位數據,即3個十六進制數字到4個八進制數字,然後您必須分別處理剩餘的位。 –

+0

謝謝@保羅R,我仍不滿足你的速度。如果你能詳細說明會有幫助。 – CppLearner

回答

5

當然這是可能的。一個數字是一個數字,不管它是什麼數字系統。唯一的問題是人們習慣於十進制,這就是爲什麼他們更好地理解它。您可以從任何基地轉換爲其他基地。

編輯:關於如何執行轉換的更多信息。

首先注意3個十六進制數字映射到正好4個八進制數字。因此,有十六進制數字的號碼你可以很容易找到的八進制數字的位數:

#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

+0

可否請您詳細說明一些支持代碼段。謝謝 – CppLearner

+0

您期望什麼輸入和輸出?字符數組? –

+0

是的,字符數組字符串的十六進制和字符數組字符串作爲八進制輸出 – CppLearner

1

是的,你可以做得相對容易:四個八進制數字總是轉換爲三個十六進制數字,所以你可以將你的字符串拆分成三個十六進制數字的組,並且從後面處理每個組。如果您沒有足夠的十六進制數字來完成一組三個數字,請添加前導零。

每個十六進制數字給你四位;拿最後三個,並將它們轉換爲八進制。添加接下來的四個,然後再增加三個八進制位。添加最後一組四個 - 現在總共有六位,所以將它們轉換爲兩個八進制數字。

這樣可以避免將整個數字轉換爲二進制數,儘管在轉換數字的過程中會使用「滑動」二進制窗口。

考慮一個例子:將62ABC轉換爲八進制。劃分爲三個數字組:062ABC(注意在62前面添加的零爲3個數字組)。

開始從後面:

  • C,或1100,被切成1100,使得八4,併爲下一步
  • B,或10111額外的位,被剁成10用於下一步,11用於此步驟。所述1來自前一步驟附接在的11右側,使得一個八進制7
  • A,或1010,被切碎成1010。上一步的10附在右側,使得010或八進制2101是八進制5,所以我們有5274到目前爲止。
  • 2變爲20用於下一步;
  • 6變成401用於下一步;
  • 0變成01(因爲01從上一步中被添加)。

最終結果是01425274

+0

謝謝我不符合你的速度。例如5274八進制轉換爲十六進制的ABC。請你詳細說明如何達成解決方案。 – CppLearner

+0

@CppLearner看看這個例子。 – dasblinkenlight

+0

謝謝@dasblinkenlight,但我想要避免這種中間二進制轉換。 – CppLearner

1

計算機內存中的所有數字都是以2爲底的。因此,無論何時您想要使用數值操作(數學運算),您都需要將它們作爲整數,浮點數等。因此,它非常方便,未來通過可計算類型進行轉換。

我會避免直接字符串到字符串轉換,除非值可能太大,以適應數字變量。從頭開始編寫可靠的轉換器是非常困難的。

(使用基地10使得二進制計算機很沒有意義。)

3

這是一個有點棘手,因爲你會被轉換的4位組的3位組 - 你可能會想用12工作位,即3個十六進制數字到4個八進制數字,然後你必須分別處理剩餘的位。

E.g.到5274八進制轉換爲十六進制:

5 2 7 4 
101 010 111 100 

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

1010 1011 1100 
A  B  C 
+0

Thanks @Paul R,但在這種情況下,我們不是將它轉換爲二進制和中間步驟。 – CppLearner

+0

你有一個小的滑動二進制窗口,是的 - 我沒有看到任何替代方案,因爲你需要重新組合這些位。 –

1

似乎是一個非常簡單的任務交給我,你想要一個十六進制字符串,並且希望將其轉換爲一個八進制的字符串。讓我們以ASCII十六進制,並將其轉換爲int類型一起工作:

char hex_value[] = "0x123"; 

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

它仍然是十六進制在這一點上,那麼如果我們想從一個基站轉換到另一個有簡單的數學可以做:

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

這就告訴我們,123 == 443 所以我們要做的就是寫數學爲基本功能,並把最終值回字符串:

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; 
} 

所以這個函數會將一個十六進制(int)值轉換成一個八進制字符串。你可以把它想:

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); 
+0

謝謝@Mike。我喜歡你的方法。但我認爲這是在從十二月到八月的轉變。執行此int值後的原因值= strtol(hex_value,NULL,16);值將包含十進制值。convert_to_oct邏輯將爲十進制到十進制。 – CppLearner

+0

@CppLearner - 完全沒有。 'strtol'函數中的'16'將值保存爲一個十六進制數。如果您在'strol'之後立即將此值作爲十進制'printf(「%d」,value)「輸出,您將看到顯示值爲291(123hex == 291dec)。這裏唯一的轉換是從一個十六進制值的ASCII表示到一個整數十六進制值。 – Mike

+0

@CppLearner - 現在,如果你不想轉換爲整數**這是一個不同的故事......但我沒有看到你的原始文章中的要求。 – Mike

相關問題