C語言實現十六進制與二進制的相互轉換
本文中的代碼可以將文件中的十六進制存儲與二進制存儲相互轉換。
十六進制->二進制
原理是:每兩位存儲為一個字符(char)保存。
因為十六進制數最大為 f,即 15,在內存中隻需要 4 位就可以表示。而一般情況下一個字符是占一個字節 8 位,所以正好可以存儲十六進制兩位。
舉個栗子:
在文件中存儲十六進制為ab,ab轉換為二進制,就是1010 1011,剛好八位,可以聯想到ASCII碼,用一個字符可以表示。
註意轉為二進制後,前32個為不可見字符,附圖ASCII碼。
(將十六進制轉為二進制還會壓縮一倍的空間?因為ab本來占兩個字節,現在轉成二進制,即一個char字符,隻占用一個字節大小。但是轉換過程中時間消耗,我不太確定是否優化瞭)
#include <stdio.h> int main() { FILE * in = fopen("./data.txt", "r"); FILE * out = fopen("./data", "w"); while (1) { char c; unsigned char d = 0; for (int i = 0; i < 2; ++i) { // 從 in 讀取 1 個大小為 1 字節數據保存在 c if (fread(&c, 1, 1, in) == 0) { fclose(in); fclose(out); return 0; } // 讀到空格或者換行索引需要回退 if (c == ' ' || c == '\n') { i--; continue; } // 將讀到的十六進制字符轉成具體的十進制數字 if (c >= '0' && c <= '9') { c -= '0'; } else if (c >= 'a' && c <= 'f') { c -= 'a'; c += 10; } else { printf("error"); } //printf("c -> %d \n", c); d <<= 4; d |= c; } //printf("-------> %c\n", d); fwrite(&d, 1, 1, out); } return 0; }
核心代碼:
d <<= 4 and d |= c
解釋:
內層for循環為兩次,c讀取兩次:
我們假設第一次讀到a字符,第二次讀到b字符。
(或運算:參加運算的兩個對象隻要有一個為1,其值為1)
操作 | 值 |
---|---|
第一次循環開始 : | d (0000 0000) c(0000 1010) |
d <<= 4 : | d (0000 0000) c(0000 1010) |
d |= c : | d (0000 1010) c(0000 1010) |
第二次循環開始: | d (0000 1010) c(0000 1011) |
d <<= 4 : | d (1010 0000) c(0000 1011) |
d |= c : | d (1010 1011) c(0000 1011) |
兩次循環結束 將d寫入文件,轉換完成。 |
如果想知道轉換是否正確的話,可以用 hexdump -C + 文件名(data) 檢查一下是否正確。(linux命令)
二進制->十六進制
這個就是上邊操作相反的過程,讀取二進制文件,然後轉成十六進制字符保存。
#include <stdio.h> int main() { FILE * in = fopen("./data.txt", "r"); FILE * out = fopen("./data", "w"); char space = ' '; char enter = '\n'; int idx = 0; while (1) { char c[2]; unsigned char d = 0; for (int i = 0; i < 4; ++i) { // 讀取一個字節 if (fread(&d, 1, 1, in) == 0) { fclose(in); fclose(out); return 0; } // 一個二進制字節轉回兩個十六進制字符 char mask = 0xf; c[0] = d >> 4; // 將低位移走就是該字節保存的第一個十六進制字符 c[1] = d & mask; // 保留 d 的低位就是該字節保存的第二個十六進制字符 // 將十進制數字轉回對應的十六進制字符(與上一步轉換的代碼相反) if (c[0] >= 0 && c[0] <= 9) { c[0] += '0'; } else { c[0] -= 10; c[0] += 'a'; } if (c[1] >= 0 && c[1] <= 9) { c[1] += '0'; } else { c[1] -= 10; c[1] += 'a'; } // 從 c 地址開始讀取兩個字節,寫到 out fwrite(&c, 1, 2, out); } // 寫空格或者換行 保持格式 idx++; if (idx == 4){ idx = 0; fwrite(&enter, 1, 1, out); } else { fwrite(&space, 1, 1, out); } } return 0; }
mask的二進制是0000 1111。
到此這篇關於C語言實現十六進制與二進制的相互轉換的文章就介紹到這瞭,更多相關C語言 十六進制二進制互轉內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!