ASC与HEX之间的转换
ASC与HEX之间的转换
有这么两个函数:
|
函数 |
原型 |
功能 |
返回值 |
参数 |
备注 |
|
hex2asc |
__int16 hex2asc(unsigned char *strhex,unsigned char *strasc,__int16 length); |
字符串转换函数,十六进制字符转换成普通字符 |
成功则返回 0,否则返回非0 |
strhex:要转换的字符 strasc:转换后的字符 length:字符strasc的长度 |
长转短 |
|
asc2hex |
__int16 asc2hex(unsigned char *strasc,unsigned char *strhex,__int16 length); |
字符串转换函数,普通字符转换成十六进制字符 |
成功则返回0,否则返回非0 |
strasc:要转换的字符 strhex:转换后的字符 length:字符strasc的长度 |
短转长 |
我们首先对这两个函数进行的测试如下:
// hex2asc和asc2hex的测试程序
#include "dculd.h"
#include <iostream>
using namespace std; #pragma comment(lib, "dculd.lib") int main()
{
unsigned char strhex[] = "0123456789ABCDEF";
//unsigned char strhex[101] = "0123456789ABCD8";
unsigned char strasc[] = {}; hex2asc(strhex, strasc, ); cout << "strhex: " << strhex << endl;
cout << strlen((const char*)strhex) << endl;
cout << strasc << endl;
cout << strlen((const char*)strasc) << endl; cout << endl << "strasc DEC: ";
for (int i = ; i < strlen((const char*)strasc); ++i)
{
cout << dec << (int)strasc[i] << ' ';
} cout << endl << "strasc HEX: ";
for (int i = ; i < strlen((const char*)strasc); ++i)
{
cout << hex << "0x" << (int)strasc[i] << ' ';
}
cout << endl; cout << endl;
unsigned char strhex_2[] = {};
asc2hex(strasc, strhex_2, );
cout << "strhex_2: " << strhex_2 << endl; return ;
}

hex2asc和asc2hex这两个函数本质上都是字符串转换函数。其中,hex2asc的被转化参数strhex为字符串”0123456789ABCDEF”,该字符串表示的是十六进制的值,每个元素相当于4个bit的值,所以每两位相当于一个byte。该字符串每个元素的取值范围为0~9和A~F,总共16个值,即16进制的16个数字。
转换后的参数strasc为字符串” #Eg壂惋”,该字符串的长度为8,每个元素的ASCII值为:
十进制:1 35 69 103 137 171 205 239
十六进制:0x1 0x23 0x45 0x67 0x89 0xab 0xcd 0xef
具体转换的规则为strhex中的两个元素的字符串所代表的十六进制数,转换为一个byte的ASCII值,然后将其存储到strasc中,所以strhex的长度为strasc长度的两倍。
相应地,asc2hex函数是将strasc字符串中每个元素实际的ASCII值以十六进制的形式转换为字符串,即用strhex存储。
这里的转换是用的十六进制,strhex中的字符串都是以十六进制的形式存在,因为每个元素的值为0~9和A~F,所以hex2asc函数中的转换操作必须是16进制的处理。asc2hex中也必须是十六进制的处理,如果改用十进制、八进制等其他进制操作,转换后的strhex中的字符必定与原来的strhex不同,并且元素个数也有可能不同。
关于为什么使用十六进制,这是我们预先规定的。如果不涉及A~F的字符,完全可以用十进制进行操作。
另一个问题是为什么要进行hex和asc之间的转换?hex更便于程序员自身识别,而asc更便于计算机识别,所以为了使得程序员更好的识别机器指令,在书写的时候才有strhex的形式进行书写,而非直接的strasc形式。机器执行字节码指令的时候必然需要strasc的形式,所以需要hex2asc函数进行相应的转换。asc2hex函数的作用是将机器返回的字节码数据更友好地呈现给程序员识别,所以需要将asc转换为hex的形式。通知hex2asc和asc2hex的转换,既有利于程序员的指令识别,也有利于机器的指令识别。
另外,用字节存储十六进制的字符标识,可以节省空间,一个字节可以存储两个十六进制字符,如果感兴趣,可以阅读《字节存储数据》。
一般情况下,一个指令字节是八位,必然对应于strhex中的2个元素,所以,strhex的长度一般情况下都是偶数的,对于基数的情况上述hex2asc函数会导致转换错误:

对于最后一个单独的元素’8’,hex2asc函数将其转换为字节:0x50,十进制的80,两个strhex元素对应于一个strasc元素,所以当strhex的长度为奇数时会存在这种情况。asc2hex函数不会存在这种问题,因为asc2hex是将strasc中的每个元素转换为strhex中的两个元素,不存在奇偶性的问题。
针对以上奇偶性的问题,我们队hex2asc进行相应的改进,使其可以处理strhex长度为奇数的情况,当然针对字节指令一般情况下不会存在这种问题,因为如果strhex长度为奇数,hex2asc应该返回错误信息。对hex2asc改进的同时,需要对asc2hex进行改进,使其可以处理strhex长度为奇数的情况。
另外,hex2asc和asc2hex第三个参数length是标识了字节指令的字节个数,即strasc和strhex都可以支撑length,也就是说strasc的长度大于等于length,strhex的长度大于等于length*2。在我们的实现代码中,length的意义有所改变,HexToAsc的length参数是指的转换strhex的元素个数,所以length可以为奇数。AscToHex的length参数是指的转换strasc的元素个数,length可以向原来的参数那样可以是偶数也可以是奇数。但是length的值在HexToAsc中需要小于等于strhex的元素个数,在AscToHex中需要小于等于strasc的元素个数,在两个函数中需要同时考虑处理strhex奇数长度的情况。
下面我们对hex2asc和asc2hex进行重新实现,具体代码如下:
// hex2asc和asc2hex的重实现,可以处理strhex长度为奇数的情况
#include <iostream>
using namespace std; // 将a~f转换为A~F
unsigned char ToUpperHex(unsigned char& ch)
{
if (ch >= 'a' && ch <= 'f')
{
ch = 'A' + ch - 'a';
}
return ch;
} // 检测ch是否为十六进制字符
bool IsHex(unsigned char ch)
{
return ch >= '' && ch <= '' || ch >= 'A' && ch <= 'F' || ch >= 'a' && ch <= 'f';
} int HexVal(unsigned char ch)
{
if (ch >= '' && ch <= '')
{
return ch - '';
}
else if (ch >= 'A' && ch <= 'F')
{
return + ch - 'A';
}
else if (ch >= 'a' && ch < 'f')
{
return + ch - 'a';
}
else
{
return -;
}
} unsigned char ValHex(int val)
{
if (val >= && val <= )
{
return val + '';
}
else if (val >= && val <= )
{
return val - + 'A';
}
else
{
return '$';
}
} int HexToAsc(unsigned char* strhex, unsigned char* strasc, int length)
{
//if (length % 2 == 1) // length表示转换strhex的元素个数,如果严格要求只能转换偶数个,这里可以进行判断
//{
// return -1;
//}
if (length > strlen((const char*)strhex))
{
length = strlen((const char*)strhex);
} // 检测strhex是否合法,是否存在非0~9、A~F、a~f字符
for (auto i = ; i != length; ++i)
{
if (!IsHex(strhex[i]))
{
return -;
}
} // 以下for-if结构可以同时处理奇偶的情况
int pos = , i = ;
for (i = ; i < length - ; i += )
{
unsigned char tmp = HexVal(strhex[i]) * + HexVal(strhex[i + ]);
strasc[pos++] = tmp;
}
if (i == length - )
{
unsigned char tmp = HexVal(strhex[i]) * ;
strasc[pos++] = tmp; // 用来标识length的奇偶,这里是奇数
strasc[pos++] = ;
}
else
{
// 用来标识length的就,这里偶数
strasc[pos++] = ;
}
strasc[pos++] = ;
return ;
} int AscToHex(unsigned char* strasc, unsigned char* strhex, int length)
{
length = length <= strlen((const char*)strasc) - ? length : strlen((const char*)strasc) - ; // strasc中的元素不存在合不合法的情况,所以不做检测 int i = , pos = ;
for (i = ; i < length - ; ++i) // 这里先处理length-1个字符,第length个字符后续处理,因为需要考虑奇偶的情况
{
strhex[pos++] = ValHex(strasc[i] / );
strhex[pos++] = ValHex(strasc[i] % );
} if (strasc[strlen((const char*)strasc) - ] == ) // 奇数的情况
{
strhex[pos++] = ValHex(strasc[length - ] / );
}
else if (strasc[strlen((const char*)strasc) - ] == ) // 偶数的情况
{
strhex[pos++] = ValHex(strasc[length - ] / );
strhex[pos++] = ValHex(strasc[length - ] % );
} strhex[pos++] = ;
return ;
} int main()
{
unsigned char strhex[] = "0123456789ABCDEF";
//unsigned char strhex[101] = "0123456789ABCD8";
unsigned char strasc[] = {}; HexToAsc(strhex, strasc, ); // 这里的16标识的是转换strhex的元素个数
//HexToAsc(strhex, strasc, 15); // 这里的15标识的是转换strhex的元素个数 cout << "strhex: " << strhex << endl;
cout << strlen((const char*)strhex) << endl;
cout << strasc << endl;
cout << strlen((const char*)strasc) << endl; cout << endl << "strasc DEC: ";
for (int i = ; i < strlen((const char*)strasc); ++i)
{
cout << dec << (int)strasc[i] << ' ';
} cout << endl << "strasc HEX: ";
for (int i = ; i < strlen((const char*)strasc); ++i)
{
cout << hex << "0x" << (int)strasc[i] << ' ';
}
cout << endl; cout << endl;
unsigned char strhex_2[] = {};
AscToHex(strasc, strhex_2, ); // 这里的8标识的是转换strasc的元素个数
cout << "strhex_2: " << strhex_2 << endl; return ;
}

以上是针对length值为偶数的情况。如果length为奇数,我们有如下测试:

从测试中,我们可以看出,即便是转换奇数个strhex元素的情况,我们也可以照常进行处理。下面是我们对程序的说明:
这是我们的函数原型,其中length参数在HexToAsc中我们指代的是转换strhex的元素个数,既可以是偶数也可以是奇数。AscToHex中的length参数是标识转换strasc的元素个数,可以是偶数也可以是奇数。
int HexToAsc(unsigned char* strhex, unsigned char* strasc, int length);
int AscToHex(unsigned char* strasc, unsigned char* strhex, int length);
程序中我们定义了一下几个函数:
ToUpperHex,用来将a~f转换为A~F,我们并没有用到该函数。
IsHex,用来检测strhex的合法性。
HexVal,用来得到十六进制字符的实际值。
ValHex,用来根据实际值得到十六进制的字符,这里都是转换为A~F字符,而非a~f。
HexToAsc函数中,我们首先检测length的长度,如果大于strhex的长度,则将其更改为strhex的长度,然后检测strhex的合法性。根据for-if-else结构来处理length奇偶数的情况。我们在strasc最后一位设定了一个标识元素,用来标识length的奇偶性。该标识在AscToHex函数转换中也要用到。
AscToHex函数一开始也要检测length的长度,由于strasc最后一个元素是标示了奇偶性,所以我们需要检测length与strasc长度减一的关系。然后我们对0到length-2元素进行诸位转换,针对length-1元素,我们需要判断strasc最后一个元素的标识,根据其标识的奇偶性来进行转换。
通过我们重实现的HexToAsc和AscToHex,我们可以正常的处理转换strhex元素个数为奇数的情况。
需要注意的一点是,length参数标注的是要转换的元素个数,如果大于原来的元素个数,则全部转换,如果小于,则只转换length个元素。
ASC与HEX之间的转换的更多相关文章
- C#中的Byte,String,Int,Hex之间的转换函数。
/// <summary> Convert a string of hex digits (ex: E4 CA B2) to a byte array. </summary> ...
- 基于Poco的UTF8、UTF16、GBK、Hex之间的转换
/******Encoding.h*******/ #include "Poco/UnicodeConverter.h" #include "Poco/Exception ...
- python中unicode, hex, bin之间的转换
python中unicode, hex, bin之间的转换 背景 在smb中有个feature change notify, 需要改动文件权限dacl,然后确认是否有收到notify.一直得不到这个d ...
- C# 16进制与字符串、字节数组之间的转换(转)
1.请问c#中如何将十进制数的字符串转化成十六进制数的字符串 //十进制转二进制 Console.WriteLine("十进制166的二进制表示: "+Convert.ToSt ...
- 《Python CookBook2》 第一章 文本 - 每次处理一个字符 && 字符和字符值之间的转换
文本 - 总结: 什么是文本Python 中的string 类型是不可变类型.文本,一个字符的矩阵,每一个单独的文本快可以被缩进和组织起来. 基本的文本操作①解析数据并将数据放入程序内部的结构中:②将 ...
- Python3 字符串与hex之间的相互转换
在字符串转换上,python2和python3是不同的,在查看一些python2的脚本时候,总是遇到字符串与hex之间之间的转换出现问题,记录一下解决方法. 1. 在Python2.7.x上,hex字 ...
- Python数字与字符之间的转换
Python数字与字符之间的转换 命令 意义 int(x [,base ]) 将x转换为一个整数 long(x [,base ]) 将x转换为一个长整数 float(x ) 将x转换到一个浮点数 co ...
- C# 16进制与字符串、字节数组之间的转换 (转载)
1.请问c#中如何将十进制数的字符串转化成十六进制数的字符串 //十进制转二进制 Console.WriteLine(, )); //十进制转八进制 Console.WriteLine(, )); / ...
- python中进制之间的转换
参考于:http://www.360doc.com/content/14/0428/11/16044571_372866302.shtml 在此非常感谢! ~~~~~~~~~~~~~~~~~~~~~ ...
随机推荐
- 修改php.ini 的timezone
php运行模式有apache 和 cli模式 这里讲cli 模式的php.ini设置 1.查找php.ini位置 php -i | grep php.ini 这样是表示 要改的文件 在/etc/php ...
- linux 根据服务名称批量杀死进程
ps -ef |grep python |awk '{print $2}'|xargs kill -9
- day26 面向对象的常用方法 和 元类的使用
1. 面向对象中的常用方法 ***** isinstance() # 判断某个对象是不是某个类的实例 # 判断stu对象是不是Student类的实例 是不是子类 issubclass() class ...
- 【C++】Mandelbrot集绘制(生成ppm文件)
曼德勃罗特集是人类有史以来做出的最奇异,最瑰丽的几何图形.曾被称为"上帝的指纹". 这个点集均出自公式:Zn+1=(Zn)^2+C.(此处Z.C均为复数)所有使得该公式无限迭代后的 ...
- elasticsearch ik安装
/usr/share/elasticsearch/bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch-ana ...
- for 与 for in
在JavaScript中提供了两种方式迭代对象: (1)for 循环: (2)for..in循环: 使用for循环进行迭代数组对象,想必大家都已经司空见惯了.但是,使用for.. in循环时,大家可要 ...
- Openstack 集群,及常用服务的 高可用 haproxy配置
一.介绍 配置文件位置(yum 安装):/etc/haproxy/haproxy.cfg 全局配置 #------------------------------------------------- ...
- .linearDrag on rigidbody / rigidbody2D in code?
it's rigidbody.drag not .linearDrag 这几天在做一个弹球的游戏,发现小球落下后不会自动停,测试后发现线性阻尼增加后可以 于是加了个触发器不停增加线性阻尼值 priva ...
- ES5之函数的间接调用 ( call、apply )、绑定 ( bind )
call().apply()的第一个实参是函数调用的上下文,在函数体内通过this来获得对它的引用. call()将实参用逗号分隔:apply ()将实参放入数组.类数组对象中. function h ...
- stm32DMA
源和目标地址必须按数据传输宽度对齐 支持循环的缓冲器管理 可编程的数据传输数目:最大为65536 每一个通道都有一组寄存器 DMA_CPARx.DMA_CMARx是没有差别的,它们都可以存放外设的地址 ...