C語言實現(xiàn)十六進制與二進制的相互轉(zhuǎn)換
本文中的代碼可以將文件中的十六進制存儲與二進制存儲相互轉(zhuǎn)換。
十六進制->二進制
原理是:每兩位存儲為一個字符(char)保存。
因為十六進制數(shù)最大為 f,即 15,在內(nèi)存中只需要 4 位就可以表示。而一般情況下一個字符是占一個字節(jié) 8 位,所以正好可以存儲十六進制兩位。
舉個栗子:
在文件中存儲十六進制為ab,ab轉(zhuǎn)換為二進制,就是1010 1011,剛好八位,可以聯(lián)想到ASCII碼,用一個字符可以表示。
注意轉(zhuǎn)為二進制后,前32個為不可見字符,附圖ASCII碼。

(將十六進制轉(zhuǎn)為二進制還會壓縮一倍的空間?因為ab本來占兩個字節(jié),現(xiàn)在轉(zhuǎn)成二進制,即一個char字符,只占用一個字節(jié)大小。但是轉(zhuǎn)換過程中時間消耗,我不太確定是否優(yōu)化了)
#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 字節(jié)數(shù)據(jù)保存在 c
if (fread(&c, 1, 1, in) == 0) {
fclose(in);
fclose(out);
return 0;
}
// 讀到空格或者換行索引需要回退
if (c == ' ' || c == '\n') {
i--;
continue;
}
// 將讀到的十六進制字符轉(zhuǎn)成具體的十進制數(shù)字
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
解釋:
內(nèi)層for循環(huán)為兩次,c讀取兩次:
我們假設(shè)第一次讀到a字符,第二次讀到b字符。
(或運算:參加運算的兩個對象只要有一個為1,其值為1)
| 操作 | 值 |
|---|---|
| 第一次循環(huán)開始 : | d (0000 0000) c(0000 1010) |
| d <<= 4 : | d (0000 0000) c(0000 1010) |
| d |= c : | d (0000 1010) c(0000 1010) |
| 第二次循環(huán)開始: | d (0000 1010) c(0000 1011) |
| d <<= 4 : | d (1010 0000) c(0000 1011) |
| d |= c : | d (1010 1011) c(0000 1011) |
| 兩次循環(huán)結(jié)束 將d寫入文件,轉(zhuǎn)換完成。 |
如果想知道轉(zhuǎn)換是否正確的話,可以用 hexdump -C + 文件名(data) 檢查一下是否正確。(linux命令)
二進制->十六進制
這個就是上邊操作相反的過程,讀取二進制文件,然后轉(zhuǎn)成十六進制字符保存。
#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) {
// 讀取一個字節(jié)
if (fread(&d, 1, 1, in) == 0) {
fclose(in);
fclose(out);
return 0;
}
// 一個二進制字節(jié)轉(zhuǎn)回兩個十六進制字符
char mask = 0xf;
c[0] = d >> 4; // 將低位移走就是該字節(jié)保存的第一個十六進制字符
c[1] = d & mask; // 保留 d 的低位就是該字節(jié)保存的第二個十六進制字符
// 將十進制數(shù)字轉(zhuǎn)回對應(yīng)的十六進制字符(與上一步轉(zhuǎn)換的代碼相反)
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 地址開始讀取兩個字節(jié),寫到 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。
到此這篇關(guān)于C語言實現(xiàn)十六進制與二進制的相互轉(zhuǎn)換的文章就介紹到這了,更多相關(guān)C語言 十六進制二進制互轉(zhuǎn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C/C++連接MySQL數(shù)據(jù)庫詳細圖文教程
在實際開發(fā)中我們經(jīng)常需要對數(shù)據(jù)庫進行訪問,下面這篇文章主要介紹了C/C++連接MySQL數(shù)據(jù)庫的詳細圖文教程,文中通過代碼以及圖文介紹是非常詳細,需要的朋友可以參考下2024-01-01
vs2019配置Qt5開發(fā)環(huán)境(圖文教程)
本文主要介紹了如何使用visual studi2019配置qt5開發(fā)環(huán)境,以及創(chuàng)建qt項目,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2021-12-12
Qt私有信號實現(xiàn)(private signal)
在使用Qt信號槽機制的時候,有時候我們需要一個信號只能由類內(nèi)發(fā)出,而不允許使用該類對象的用戶發(fā)出,此時就需要私有信號的支持,本文主要介紹了Qt私有信號實現(xiàn)(private signal),感興趣的可以了解一下2023-10-10

