2009-09-08 46 views
1

我給出了一個字符串hex_txt,其中包含一個4位十六進制數字,代碼中概括了兩種數組條目。我需要將它轉換爲十進制。以下是我做這件事的方式。將存儲爲字符的十六進制字符串轉換爲十進制C

unsigned char hex_txt[] = "\xAB\xCD"; 
unsigned char hex_num[5]; 
unsigned int dec_num; 

sprintf(hex_num, "%.2x%.2x", (int)hex_txt[0], (int)hex_txt[1]); 
printf("%s\n", hex_num); 
sscanf(hex_num, "%x", &dec_num); 
printf("%d\n", dec_num); 

有沒有更快或更有效的方法呢?這是我目前的臨時解決方案,但我想知道是否有適當的方法來做到這一點。

回答

5
int result = (unsigned char)hex_txt[0] * 256 + (unsigned char)hex_txt[1]; 

字符串hex_txt包含兩個字節;我猜測這個順序是big-endian(如果它是little-endian,則反轉下標)。 hex_txt[0]的字符代碼是0xAB,因爲​​是0xCD。使用無符號字符轉換確保您不會被符號字符搞亂。

或者說,做這一切在一次:

printf("%d\n", (unsigned char)hex_txt[0] * 256 + (unsigned char)hex_txt[1]); 
+0

正是我在找什麼,謝謝。 – v64 2009-09-08 14:28:56

+0

你怎麼能確定(無符號字符)hex_txt [0] * 256不是零? – 2009-09-08 15:00:00

+0

@Mike:hex_txt [0]是0xAB或171; 171 * 256 = 43776.如果'int'是一個16位的數量,那麼這將是一個負的非零結果(或者可能是一個溢出信號,但我還沒有聽說過產生溢出信號的機器用於簽名算術溢出);如果它是一個無符號的16位數量,它仍然是一個非零結果。我無法看到乘法產生零。此外,我的答案並不取決於產生非零結果的乘法 - 讓我對你的問題來自何處感到困惑。 – 2009-09-08 16:04:59

0

這是我做的:

n = 0; 
while (*p){ 
    if (ISDIGIT(*p)) n = n*16 + (*p++ - '0'); 
    else if (ISALPHA(*p)) n = n*16 + (LOWERCASE(*p++) - 'a' + 10); 
    else break; 
} 

和(你會恨這一點,但它適用於ASCII)我騙:

#define LOWERCASE(c) ((c) | ' ') 

新增:對不起,我剛纔重讀你的問題。爲什麼不這樣做:

(unsigned int)(unsigned char)p[0] * 256 + (unsigned int)(unsigned char)p[1] 
+0

使用 'ISALPHA'(爲什麼不 '因而isalpha'?)讓你容易將 'Z'。驗證不夠嚴格。如果我是你,我會刪除你的答案的第一部分,只留下第二部分。另外,'unsigned int'強制轉換不是必需的,儘管它們沒有任何傷害。 – 2009-09-08 14:18:49

+0

@Jonathan:如果你將一個無符號字符乘以256,你沒有得到什麼?如果你將一個有符號的char轉換爲unsigned int,我想確保它不會意外地傳播符號位。 – 2009-09-08 14:56:29

+0

Mike:C中的中間結果總是至少爲「int」 - 如果使用所有的'unsigned char'操作數進行計算,則根據int的相對大小將它們提升爲int或unsigned int,並且'char'。如果將結果存儲回'unsigned char',*結果以「UCHAR_MAX」爲模的結果被減少 - 但在這種情況下結果被存儲到一個'int'中,所以一切正常。 – caf 2009-09-08 22:30:04

0

我可能會咿呀學語,但如果你使用:

char hex_txt[] = "\xAB\xCD"; 

那麼實際上你剛纔定義2個字節:

char hex_txt[] = {0xab, 0xcd}; 

所以要將其轉換爲int,你可以這樣做:

int number = (int) ((short *) *hex_text); 
+0

將「* hex_text」前面的*和第二個e放在裏面。然後你只剩下一個不確定的結果。你可以在一個big-endian機器上得到一個答案,在一個little-endian機器上得到另一個答案。如果編譯器足夠殘酷地將hex_txt放在奇數字節邊界上,並且CPU將從奇數地址讀取短整數,那麼您也容易受到SIGBUS錯誤的攻擊。哦,第一個聲明定義了長度爲3的數組,而不是2. – 2009-09-08 14:10:26

+0

您可以遇到1)endian問題和2)對齊問題,不是嗎? – 2009-09-08 14:11:33

+0

不幸的是,忽略了像這樣的細節引導編譯器在編譯時反對,程序在運行時崩潰或給出錯誤結果。這些都不是好的結果。 – 2009-09-08 14:20:30

0

你可能不需要它,儘管我發佈了一段C++代碼here

1

只需使用strtoul()功能從stdlib.h
請看下面的例子:

const char sHex[] = "AE"; 

unsigned char ucByte = 0; 

ucByte = (unsigned char) strtoul(sHex, NULL, 16); //BASE 16 FOR HEX VALUES 
相關問題