求助:如何将字节数组转换为十六进制字符串再转为十进制整数
现在有一个字节数组,例如 char AA={a,f,1,e,6,c} 代表的就是十六进制的 AF 1E 6C如何把这个数组转换为十六进制的字符串,即 0xAF1E6C?
再怎么把它转为十进制的整数,即 11476588 ?
谢谢!
哈哈,你例子是一个伪命题,你那个定义AA方法是不存在的。
只有可能是下面两种情况:
第一种:char AA={0x0a,0x0f,0x01,0x0e,0x06,0x0c};第二种:char AA={'a','f','1','e','6','c'};第一种:
移位就行了
unsigned long CharArrayToNumber( unsigned char *p_pBuff, int p_iSize )
{
if( NULL != p_pBuff && p_iSize > 0 && p_iSize <= 8 )
{
unsigned long ulRet = 0;
p_iSize -= 1;
for(int i=0;i<=p_iSize;++i)
{
ulRet |= ((unsigned long)(p_pBuff))<<((p_iSize-i)<<2);
}
return ulRet;
}
else
{
// arduino 有没有 throw 我不知道,异常肯定就挂了,怎么调试我也不知道
//throw "CharArrayToNumber: arg error";
return 0;
}
}
你的例子就写成:
char AA={0x0a,0x0f,0x01,0x0e,0x06,0x0c};
unsigned long ulVal = CharArrayToNumber(AA,6);
第二种:
就比较麻烦了,需要一个字符到数字的转换,估计你想要这个的可能性大
inline unsigned long CharToNumber( unsigned char p_ucVal )
{
switch(p_ucVal)
{
case '0':
return 0;
case '1':
return 1;
case '2':
return 2;
case '3':
return 3;
case '4':
return 4;
case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
case 'A':
return 10;
case 'B':
return 11;
case 'C':
return 12;
case 'D':
return 13;
case 'E':
return 14;
case 'F':
return 15;
case 'a':
return 10;
case 'b':
return 11;
case 'c':
return 12;
case 'd':
return 13;
case 'e':
return 14;
case 'f':
return 15;
default:
// arduino 有没有 throw 我不知道,异常肯定就挂了,怎么调试我也不知道
//throw "CharToNumber: arg error";
return 0;
}
}
这么写为了速度快,当然为了好看可以把 A 和 a 写一起,但写一起编译器恐怕不能优化成跳转,AVR的汇编我不了解,哪位了解可以看一下反汇编确定一下。
如果不确定,又追求效率,可以自己优化,给个思路:
inline unsigned long CharToNumber( unsigned char p_ucVal )
{ // 如果要用,具体 0 的数目对不对最好自己数清楚一下。。。
static const unsigned char __TransferArray[] = {0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,11,12,13,14,15};
if( p_ucVal >= '0' && p_ucVal <= 'f' )
{ // 意思就是这一步在自己的代码里就保证了肯定是指针跳转
return __TransferArray;
}
else
{
//throw "CharToNumber: arg error";
return 0;
}
}
unsigned long CharArrayToNumber( unsigned char *p_pBuff, int p_iSize )
{
if( NULL != p_pBuff && p_iSize > 0 && p_iSize <= 8 )
{
unsigned long ulRet = 0;
p_iSize -= 1;
for(int i=0;i<=p_iSize;++i)
{
ulRet |= CharToNumber(p_pBuff)<<((p_iSize-i)<<2);
}
return ulRet;
}
else
{
//throw "CharArrayToNumber: arg error";
return 0;
}
}
你的例子就写成:
char AA={'a','f','1','e','6','c'};
unsigned long ulVal = CharArrayToNumber(AA,6);
=========================================================
ulVal 既是 0xAF1E6C 也是 11476588
printf("ulVal=0x%X\n", ulVal);
printf("ulVal=0x%ld\n", ulVal);
// 输出:
ulVal=0xAF1E6C
ulVal=11476588
不过你这个需求真的很奇怪,一个 char 的范围本身就是 0x00-0xFF 了
你那个AA为什么不是 char AA={0x00,0xaf,0x1e,0x6c} ?
如果是大端系统就可以直接:
unsigned long ulVal = *((unsigned long *)AA);
小端系统0、3字节1、2字节交换后,就和上面一样直接强转。
大致就这么几种,根据你的情况用吧。总的来说 arduino 对性能的要求比较苛刻,
但效率主要取决于设计思路,具体代码的优化只能是毛毛雨。
arduino 是大端还是小端系统我还真没注意,测一下很简单:
void TestEndian()
{
static union {
char _c;
unsigned long _l;
} __endian_test = { 'l', '0' ,'0', 'b'};
if( 'b' == ((char)__endian_test._l) )
printf("是大端系统\n");
else
printf("是小端系统\n");
}
膜拜一楼大神 补充一楼大神的,先上一段代码char s[]="0xA";
int i;
i = strtol(s, NULL, 16);
printf("%d", i);使用strtol可以直接转化成十进制,百科中查下这个函数。你可以直接把AA作为参数放进来,楼主的AA定义是错的,得用1楼的第二种方式定义。
另外你要把AA变成0x开头的可以这样char tmpdata;
sprintf(tmpdata,"0x%s",AA);
//tmpdata中就是0xAF1E6C字符串了
// 继续用strtol转换行了
int i= strtol(tmpdata,NULL,16);sprintf scanf memset memcpy 这四个函数还是比较有用的,前两个是对字符串操作,后两个是直接对内存数据操作,可以百科看一下 本帖最后由 lilho_e 于 2014-2-27 11:20 编辑
非常感谢 jytong ,转角 两位兄弟的回复。
我先消化一下,回头再来请教!
谢谢你们二位!
我的字符数组确实是类似
char AA={'a','f','1','e','6','c'};这样的,里面只包含0-9 a-f,字母都是小写的。
实际上我得到的最原始的数据是 string 的字符串,就是类似 string data= "af1e6c........" 这样的,有100多个字符在里面,我自己再转换为char数组的。
这些数据是从传感器上传回的一系列的参数,一些参数占用1位(类似 c2 这样),一些参数占用2位 (类似 a3 c4),还有参数占用4位(类似 e3 c5 a2 22)
我想实现的功能就是用最快的速度,从一个 string 的字符串中,取出其中的某几位的数据 例如 "e3c5a222"来还原出十进制的数值(3821380130)。
顺带再请教一下,比如我要把这个数组清零,准备接收下组数据,语句是什么样的?
还有一个问题是:我现在是在开头就定义好数组的个数 ,比如 char data,如果定义成空的 char data[] ,程序运行第一次的时候,开始的几个参数总是存不进去。不知道是什么原因? lilho_e 发表于 2014-2-27 11:00 static/image/common/back.gif
非常感谢 jytong ,转角 两位兄弟的回复。
我先消化一下,回头再来请教!
谢谢你们二位!
数组清零你可以用memset函数memset(aa,0,aa占用的内存大小);
//这句是把AA数组所用内存全部设置为0C语言中数组定义不能没有长度,必须指定长度。如果你想用个变长的字符串的话可以使用char* 这是指针,不建议新手使用,不及时释放会造成内存泄漏 另外你要截取字符串中间的某几位数据的话可以使用strncpy函数char data[]= "af1e6c........";//这里直接赋值时候是可以不写数组长度的,编译器会自动指定data长度的
//要从第12位开始截取4个字符,出租是从0开始的还记得吧
char dest;//要定义5个字符的长度才能保存4个字符 切记
strncpy(dest,data+12,4);现在dest中就是你想要的数据了。别忘记字符串是用'\0'标识结束的,所以要定义5个内存中保存的数据举例: a3c4\0这就是内存中保存的数据 转角 发表于 2014-2-27 12:02 static/image/common/back.gif
另外你要截取字符串中间的某几位数据的话可以使用strncpy函数现在dest中就是你想要的数据了。别忘记字符串是 ...
兄弟,非常感谢你耐心的回复,真是太谢谢了!
我来试一下! 再次感谢楼上两位兄弟的回复。
现在找到一个简单的函数解决了:
unsigned long ulVal =strtol(data, NULL, 16);
data 是一个 char的数组,里面的内容类似 {"af1e6c........"} 只包含 0-9 a-f
这个函数的作用:直接将这个数组里的十六进制字符串转换为对应的十进制数值。 lilho_e 发表于 2014-2-27 16:03 static/image/common/back.gif
再次感谢楼上两位兄弟的回复。
现在找到一个简单的函数解决了:
unsigned long ulVal =strtol(data, NULL ...
看来data数组中不需要加上0x开头是吧? 转角 发表于 2014-2-27 16:51 static/image/common/back.gif
看来data数组中不需要加上0x开头是吧?
是的,直接字符串就可以。
还有个问题想请教你一下:
strncpy(dest,data+12,4);
我现在有个数组 类似int Index={14,2,25,3,35,2,60,4}这样
其中 index 代表要取值的位置,index 代表要取值的个数
用index来代替原来的 12 4 ,应该怎么写? 4好像可以直接用index 来代替,12直接代替了要出错。
谢谢! strncpy(dest,data+12,4);
这个data+12是表示从数组起始地址开始偏移12个字节。
data是数组名,+12是便宜12个字节。如果只写data的话就是访问的这个数组的起始地址(就是数组的第一个元素的地址)。
char data[]="abcdefghigkl"; // data长度是13
data其实就是"abcdefghigkl"的首地址,只写data得到的是'a'所在的内存地址值是0x3432dbac data 这就是取值,会得到‘a' .
data+3相当于0x3432dbac+3 这是'd'的内存地址了。同理data+12你就从你的数组头部往后数12个单位就是了。
回到strncpy(dest,data+3,4); 中,就是把‘d’所在的地址作为第二个参数传进去,截取4个单位的长度
执行完之后 dest的值就是“defg"
你那边12代替进去出错,你检查一下data的长度有index+index 那么长吗?还有dest可用空间大小有没有小于index +1
下面付上strncpy的源码char *strncpy(char *dest, const char *src, int n)
{
char c;
char *s = dest;
if (n >= 4)
{
size_t n4 = n >> 2;
for (;;)
{
c = *src++;
*dest++ = c;
if (c == '\0')
break;
c = *src++;
*dest++ = c;
if (c == '\0')
break;
c = *src++;
*dest++ = c;
if (c == '\0')
break;
c = *src++;
*dest++ = c;
if (c == '\0')
break;
if (--n4 == 0)
goto last_chars;
}
n -= dest - s;
goto zero_fill;
}
last_chars:
n &= 3;
if (n == 0)
return s;
for (;;)
{
c = *src++;
--n;
*dest++ = c;
if (c == '\0')
break;
if (n == 0)
return s;
}
zero_fill:
while (n-- > 0)
dest = '\0';
return s;
} 早上好,转角!感谢你如此详细的回复!希望以后能多多请教你!我的编程只是小白水平
你的回复让我对基本的概念又清晰了一些,我今天来学习一下指针的基本概念并试着运用一下。
很奇怪,我昨天用index数组来代替不行,今天早上可以了!可能是昨天哪里有错误没发现。
lilho_e 发表于 2014-2-28 10:15 static/image/common/back.gif
早上好,转角!感谢你如此详细的回复!希望以后能多多请教你!我的编程只是小白水平
你的回复让我对基本的 ...
我是程序员,刚开始接触单片机,好多硬件的东西不太懂需要摸索,互相学习吧 学习C语言基础,建议你使用vc2005 或者vc6也可以,这编译器可以调试程序,让你能看到各个变量在运行时候都是什么值,也能查看内存、堆栈非常好用。目前最高版可能是vs2014了你没必要用那么高的版本,占用资源太大还慢
页:
[1]
2