• 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("
    ");
    }
    

    该调用方法中,第一个参数为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
    ",c);
    	
    	printf("a:");
    	for(i = 0;i < 10;i++)
    		printf("%x",a[i]);	//如果想要输出大写的16进制数使用%X
    	printf("
    ");
    }
    

    上面这段代码是在前一个代码上增加的,其中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文件:源代码

  • 相关阅读:
    取指定长度的字符串(包括中英文),以"..."的方式显示
    js 常用函数
    js 规范
    js高级编程笔记2
    js高级编程笔记
    WinJS开发div中元素的水平和垂直居中metro
    WinJS开发iframe中Javascript执行错误metro
    MySql乱码
    正则表达式符号系统
    Java替换字符串中的回车换行
  • 原文地址:https://www.cnblogs.com/yabin/p/6628884.html
Copyright © 2020-2023  润新知