16進制數至字符串轉換


16進制字符串的壓縮存儲

對於秘鑰之類的一些字符串,我們往往都是通過16進制數對應的字符串進行顯示的。然而一個字符串一般情況下要占用一個字節,而一個字節一般能夠表示兩個16進制數,這就造成了空間的浪費。如0xEA,我們就可以用一個字節進行存儲,而用'E','A'存儲則需要花費兩個字節。這里提供了一個方法ZipStr能夠將16進制字符串壓縮為16進制數。調用方法如下:

int main()
{
	int i = 0;
	unsigned char a[10];
	char b[20] = "AbCdEf1234AbCdEf5678";
	
	memset(a,0,sizeof(a));
	
	ZipStr(a,b,20);
	// ZipStr(a,&b[3],11);
	
	for(i = 0;i < 10;i++)
		printf("%x",a[i]);	//如果想要輸出大寫的16進制數使用%X
	printf("\r\n");
}

該調用方法中,第一個參數為16進制數存儲位置,第二個參數指向需要壓縮存儲的字符串,第三個數是是16進制數字符串數。當然我們也可以在字符串b的任意位置開始壓縮,並且壓縮任意個數的字符,就像注釋掉的哪行一樣。執行結果如下:

壓縮字符串

對應函數源代碼如下:

//將一個字符變成16進制數
unsigned char Str2Hex(char ch)
{
	if((ch >= '0')&(ch <= '9'))
		return ch - '0';
	else if((ch >= 'a')&(ch <= 'f'))
		return ch - 'a' + 10;
	else if((ch >= 'A')&(ch <= 'F'))
		return ch - 'A' + 10;
	return 0;
}

//-----------------------------------------------------------------------------
// 函數功能: 將16進制字符串進行壓縮存儲
//-----------------------------------------------------------------------------
// 函數說明:無
//-----------------------------------------------------------------------------
// 輸入參數:	dest -> 存儲壓縮數據的位置,src -> 需要被壓縮的字符串位置
//				srcNum -> 被壓縮的字符串個數
// 輸出參數: 	無
//-----------------------------------------------------------------------------
void ZipStr(unsigned char* dest,char* src,int srcNum)
{
	int i = 0;
	unsigned char temp = 0;
	
	for(i = 0;i < srcNum;i++)
	{
		temp = Str2Hex(src[i]);
		if(i%2)
			dest[i/2] |= temp;
		else
			dest[i/2] = temp<<4;
	}
}

這里為了看的更加清晰,將一個16進制字符串轉數單獨用一個函數Str2Hex寫出來了。事實上這個函數並沒有在多個地方進行調用,因此完全可以將該函數寫到ZipStr當中,這樣可以省去很大一部分函數在調用時的開銷(該函數被循環調用很多次)。當然如果我們寫的是C++代碼,直接將這個函數聲明為inline即可。

16進制數的解壓

和壓縮相反,當我們需要將我們的16進制數打印到窗口,或者通過某個字符串傳遞協議發送時。我們還需要將16進制數轉化為字符串,這里同樣提供了一個UnzipStr用來進行上面函數的逆運算。調用方法如下:

int main()
{
	int i = 0;
	unsigned char a[10];
	char b[20] = "AbCdEf1234AbCdEf5678";
	char c[21];
	
	memset(a,0,sizeof(a));
	memset(c,0,sizeof(c));
	
	ZipStr(a,b,20);
	// ZipStr(a,&b[3],11);
	
	UnzipStr(c,a,20);
	// UnzipStr(c,a+1,11);
	printf("c:%s\r\n",c);
	
	printf("a:");
	for(i = 0;i < 10;i++)
		printf("%x",a[i]);	//如果想要輸出大寫的16進制數使用%X
	printf("\r\n");
}

上面這段代碼是在前一個代碼上增加的,其中c就是a解壓后的字符串。這里為了方便打印字符串c在其后面又多加了一位0表示字符串結束。同樣,就像注釋掉的部分那樣,我們可以從a任意字節開始提取任意多個字符串。代碼執行結果如下:

解壓字符串

對應函數源碼如下:

//在一個字節中提取一個16進制數
//idx = 1表示提取高位,idx = 0表示提取低位
char Hex2Str(unsigned char dat,int idx)
{
	char temp = 0;
	if(idx)
		temp = dat>>4;
	else
		temp = dat&0xf;
	if(temp <= 9)
		return temp + '0';
	else
		return temp - 10 + 'A';		//全部轉化為大寫
	return 0;
}

//-----------------------------------------------------------------------------
// 函數功能: 將16進制數解壓為字符串
//-----------------------------------------------------------------------------
// 函數說明:無
//-----------------------------------------------------------------------------
// 輸入參數:	dest -> 存儲解壓后字符串的位置,src -> 需要被解壓的16進制數位置
//				destNum -> 被解壓的字符串個數
// 輸出參數: 	無
//-----------------------------------------------------------------------------
void UnzipStr(char* dest,unsigned char* src,int destNum)
{
	int i = 0;
	for(i = 0;i < destNum;i++)
	{
		if(i%2)
			dest[i] = Hex2Str(src[i/2],0);
		else
			dest[i] = Hex2Str(src[i/2],1);
	}
}

分析過程和壓縮過程幾乎一樣這里不再進行過多介紹了。需要注意的是這里只能將字符串轉成大寫的16進制數,當然轉成小寫或者通過一個參數進行控制也十分簡單。

文中的源代碼及對應的makefile和shell文件:源代碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM