首頁 > 軟體

C語言實現十六進位制與二進位制的相互轉換

2022-11-11 14:00:17

本文中的程式碼可以將檔案中的十六進位制儲存與二進位制儲存相互轉換。

十六進位制->二進位制

原理是:每兩位儲存為一個字元(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("-------> %cn", 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語言 十六進位制二進位制互轉內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com