將字節流轉換成十六進制字符串

今天的在閱讀項目代碼的時候遇到的問題。

在研究之後,終於確定每次看到這樣的轉換問題都會搞不懂,每次都需要花時間繞來繞去的原因。

我在之前沒能弄清轉換的過程中,字符的計算機存儲方式和字符的輸出方式的區別,總是出現很多想當然的想法,所以總是在想問題的過程中沒頭沒腦的。

先說轉換的要求:

將字節流轉換成十六進制字符串。字節流,就是一個一個的字符組成的流,每個字符佔一個字節。十六進制字符串,也是由一個個字符組成的。

舉例將字節流“AB”轉換成十六進制字符串,最後得到的結果應該是“4142”

這是因爲字符‘A’就是十六進制的41即0x41,字符‘B’就是十六進制的42,即0x42。

下面來看一些知識。

一個字節在內存中的表現形式:

從0000 0000
到1111 1111


按十進制輸出:

從0
到255


按16進制輸出:

從0x00

到0xFF


如果‘A'以二進制輸出則得到0100 0001

    以十進制輸出則得到65

    以十六進制輸出得到41

如果‘B'以二進制輸出則得到0100 0010

    以十進制輸出則得到66

    以十六進制輸出得到42


下面我們談談怎樣將上面已知的轉化爲一個“4142”這樣的字符串

我們可以利用二進制和十六進制的轉換關係進行運算:

我們將一個字符的二進制表示劃分爲兩部分,其中前面半部分就是十六進制數的第二位,後半部分就是十六進制數的第一位。

<span style="white-space:pre">	</span>unsigned char c = 'A';
	unsigned char pre = c >> 4;
	unsigned char suf = c & 0x0F;
我們通過位移運算就可以得到‘A’的二進制表示的前半部分,通過與運算就可以得到‘A’的二進制表示的後半部分。

我們得到這些之後並不意味着轉換的結束,因爲我們得到的緊緊是十六進制表示爲4的字符,和十六進制表示爲1的字符,字符本身並不是我們想要的數值。如果我們將這些字符按照ascii字符輸出,他們並不是我們想要的結果,我們想要的結果是他們的字符表示是0~9和A~F。

下面我們就還需要進行轉換:

在上面的代碼中字符變量變量pre的十六進制表示是0x04,而實際的字符‘4’的十六進制表示是0x34,他們之間相差0x30.(在asc中所有的十六進制數與它所對應的ascii字符都相差0x30,所以只需要在原來的字符變量上加上0x30即可,0~9是這樣)

下面再看看例外:如果pre的十六進制表示是0x0A,此時是怎樣的呢?在ascii嗎表中,字符‘a’的十六進制表示是0x41,則需要在原來的字符變量上加上0x37.(A~E)

需要注意的內容大概就在上面這些了,下面看完整代碼(如有需要自行改動):

#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
int main()
{
	unsigned char c = 'A';
	cout << "轉換前" << endl;
	unsigned char pre = c >> 4;
	printf("以十六進制輸出:0x%02x\n",pre);
	printf("以ascii輸出:%c\n",pre);
	unsigned char suf = c & 0x0F;
	printf("以十六進制輸出:0x%02x\n",suf);
	printf("以ascii輸出:%c\n",suf);
	
	pre += 0x30;
	if(pre >0x39)
	{
		pre += 0x07;
	}
	suf += 0x30;
	if(suf >0x39)
	{
		suf += 0x07;
	}
	
	cout << "轉換後" << endl;
	printf("以十六進制輸出:0x%02x\n",pre);
	printf("以ascii輸出:%c\n",pre);
	printf("以十六進制輸出:0x%02x\n",suf);
	printf("以ascii輸出:%c\n",suf);
	
	
	string s;
	s += pre;
	s += suf;
	cout << "轉化後的十六進制字符串" << s;
	return 0;
}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章