OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 17180|回复: 15

字符串形式的十六进制转换为其对应的十进制数字。

[复制链接]

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
发表于 2017-10-20 12:37:25 | 显示全部楼层 |阅读模式
本帖最后由 zuozhongkai 于 2017-10-20 12:41 编辑

遇到有客户问道这个问题,这是个典型的字符串处理问题,为什么要单独将这个问题列出出来,因为字符串转数字是非常常见的,很多C语言基础不扎实的开发者就会束手无策!我花了点时间做了一下,一共三个函数:
int charhex_to_dec(char *chr)    //此函数是可以直接调用的API函数,参数chr就是要转换的字符串,返回值就是将字符串转换完成的int形数值,比如字符串”0x16“转换出来就是十进制的22。
u8 chrtodec(char chr)               //此函数用来将单个的字符转换为其所对应的十进制数值,比如字符”A“或者”a“的十进制就是10,此函数要考虑处理大小写的问题。
int cal16match(u8 n)                //此函数用来计算16的n次方,也即是n个16相乘,n为次方数或者16相乘的个数,为什么是16呢?因为是十六进制!!!!!
函数charhex_to_dec()会调用chrtodec()和cal16match()


总共只需这三个函数即可完成题目的功能,程序不长,加上注释基本就60行,只是测试的示例代码,代码如下:
[mw_shl_code=applescript,true]//将字符'0' ~ 'D'转换为相应的数字
//返回值:字符转换完成一会对应的数值
u8 chrtodec(char chr)
{
        u8 value=0;
        
        //先全部将小写转换为大写
        if((chr>='a')&&(chr<='z'))
                chr=chr-32;
        
        //将字符转化成相应的数字
        if((chr>='0')&&(chr<='9'))
                value=chr-48;
        else if((chr>='A')&&(chr<='Z'))
                value=chr-65+10;
        
        return value;
}

//计算n个16相乘
//n:16相称的次数
//返回值:计算出来的结果
int cal16match(u8 n)
{
        u8 i=0;
        int value=1;
        
        for(i=0;i<n;i++)
                value*=16;

        return value;
}

//将字符串格式的十六进制转换为数字型,
//如字符串“0x16”转换为int型的22。
//参数 chr: 要转换的字符串,不区分大小写!!!!
//返回值:参数chr转换完成以后的十进制数值
int charhex_to_dec(char *chr)
{
        u8 i,chrlen;
        u8 sta=0; //标记要转换的字符串是否以0x,或者0X开头
        int chrtoint=0;
        int value=0;
        
        chrlen=strlen(chr);
        
        //检查字符串是否是以0x或者0X开头的。
        if((chr[0] == '0') && ((chr[1]=='x') || (chr[1] == 'X')))
        {
                sta=2;        //标记以0x,0X开头
                chrlen=chrlen-2;
        }

        //计算
        for(i=0;i<chrlen;i++)
        {
                chrtoint=chrtodec(chr[sta+i]);
                if(i!=(chrlen-1))                //不是最后一位
                        value+=chrtoint*cal16match(chrlen-1-i);
                else if(i==(chrlen-1))         //最后一位
                        value+=chrtoint;
                                
        }
        return value;
}[/mw_shl_code]


程序设计思路

1、提取有用的信息。
     字符串”0x16“里面我们用来在后面参与计算的、真正有效的字符只有”16“,所以要去掉”0x“,"0X",当然了如果你要转换的字符串直接就是”16“的话那就不需要处理了。处理过程在函数charhex_to_dec()里面,处理代码如下:
     [mw_shl_code=applescript,true]//检查字符串是否是以0x或者0X开头的。
        if((chr[0] == '0') && ((chr[1]=='x') || (chr[1] == 'X')))
        {
                sta=2;        //标记以0x,0X开头
                chrlen=chrlen-2;
        }[/mw_shl_code]

2、将单个字符转换为其对应的数值
     字符”16“怎么转换为十进制的22呢?计算公式很简单,就是:1*16 + 6 =22,如果是”0x1f“的话就是:1*16 + f=1*16+15=31。由此可见,要想转换字符串,首先要先将字符串中的每个字符所代表的数值要先计算出来,并且还要考虑到字符:a~f和A~F,还有字符的大小写问题。
这个功能怎么完成呢?ASCII码啊!!!为了计算方便,首先统一将字母转换为大写,这一步也是不区分大小写功能的实现。最后计算字符所对应的数值,字符”0“在ASCII码表上的数值是48,但是它所代表的数值就要减去这个48,即‘0’-48=48-48=0,同理‘0’~‘9’和‘A’~‘Z’都可以这样计算,
此功能是由函数chrtodec()完成的,处理过程如下:
[mw_shl_code=applescript,true]u8 chrtodec(char chr)
{
        u8 value=0;
        
        //先全部将小写转换为大写
        if((chr>='a')&&(chr<='z'))
                chr=chr-32;
        
        //将字符转化成相应的数字
        if((chr>='0')&&(chr<='9'))
                value=chr-48;
        else if((chr>='A')&&(chr<='Z'))
                value=chr-65+10;
        
        return value;
}[/mw_shl_code]

3、拼接!
    我们已经将字符串中的单个字符所对应的数值计算出来了,最后就是将其”拼接“在一起,计算出最终的数值。同样以”0x16“为例,此字符串参与计算的字符只有”16“,即字符长度strlen=2,那么”16“=1*(16^(strlen-1)) + 6*(16^(strlen-2))=1*(16^1) + 6*(16^0)=22。由此可见,需要一个计算16的n次方的函数,也就是
n个16相乘的函数,此函数就是cal16match(),非常简单的一个函数。
[mw_shl_code=applescript,true]int cal16match(u8 n)
{
        u8 i=0;
        int value=1;
        
        for(i=0;i<n;i++)
                value*=16;

        return value;
}[/mw_shl_code]
最后的计算就是由函数charhex_to_dec()中后面的代码来完成了,如下:
[mw_shl_code=applescript,true]        //计算
        for(i=0;i<chrlen;i++)
        {
                chrtoint=chrtodec(chr[sta+i]);
                if(i!=(chrlen-1))                //不是最后一位
                        value+=chrtoint*cal16match(chrlen-1-i);
                else if(i==(chrlen-1))         //最后一位
                        value+=chrtoint;
                                
        }[/mw_shl_code]

4、测试:
    完成以后即可进行一下测试,看一下函数工作是否正常,我的测试如下图所示:
N2]W%MIBHG~3)0Y}FIFEANL.png

结论:
   实际工作中对于字符串的各种处理是非常常见的,本贴讲的还是一个很小的问题,建议那些C语言基础不扎实的同学一定要多做练习,熟练掌握C语言的各种字符串处理。最后附件附上测试代码。





十六进制字符串转十进制数值.zip

864 Bytes, 下载次数: 787

开往春天的手扶拖拉机
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

13

主题

175

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2016-4-30
在线时间
141 小时
发表于 2017-10-20 13:10:32 | 显示全部楼层
回复 支持 反对

使用道具 举报

42

主题

297

帖子

0

精华

高级会员

Rank: 4

积分
994
金钱
994
注册时间
2016-7-22
在线时间
318 小时
发表于 2017-10-20 13:50:23 | 显示全部楼层
本帖最后由 hi我歌月徘徊 于 2017-10-20 14:04 编辑

最近遇到了浮点数如何发送的问题

char buffer【1024】;
float rms1,rms2,rms3;

memcpy(buffer,      &rms1, 4);//float占用4个字节
memcpy(buffer+4,  &rms2, 4);
memcpy(buffer+8,  &rms3, 4);


这么做可以吧 ?
回复 支持 反对

使用道具 举报

13

主题

175

帖子

0

精华

初级会员

Rank: 2

积分
182
金钱
182
注册时间
2016-4-30
在线时间
141 小时
发表于 2017-10-20 16:40:09 | 显示全部楼层
hi我歌月徘徊 发表于 2017-10-20 13:50
最近遇到了浮点数如何发送的问题

char buffer【1024】;

浮点数可以  sprintf(&buffer,“%f”,rms1)最近刚好用过
回复 支持 反对

使用道具 举报

3

主题

26

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
218
金钱
218
注册时间
2018-7-12
在线时间
34 小时
发表于 2018-11-5 15:17:03 | 显示全部楼层
想问下楼主为什么我测试出来的结果只能转换两个字节的16进制,4个字节就不能正确转换了?
回复 支持 反对

使用道具 举报

3

主题

26

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
218
金钱
218
注册时间
2018-7-12
在线时间
34 小时
发表于 2018-11-5 15:26:56 | 显示全部楼层
castle 发表于 2018-11-5 15:17
想问下楼主为什么我测试出来的结果只能转换两个字节的16进制,4个字节就不能正确转换了?

不好意思是我定义错了,问题已经解决了。
回复 支持 反对

使用道具 举报

13

主题

633

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1331
金钱
1331
注册时间
2016-8-1
在线时间
229 小时
发表于 2018-11-5 17:53:36 | 显示全部楼层
本帖最后由 秋天 于 2018-11-5 17:55 编辑

谢谢分享,原来你就是视频里的人
Loto虚拟示波器 官方qq群: 706769836 https://shop296209296.taobao.com/shop/view_shop.htm?tracelog=t
回复 支持 反对

使用道具 举报

88

主题

7377

帖子

5

精华

资深版主

Rank: 8Rank: 8

积分
14980
金钱
14980
注册时间
2013-11-13
在线时间
1823 小时
 楼主| 发表于 2018-11-5 18:17:23 | 显示全部楼层
秋天 发表于 2018-11-5 17:53
谢谢分享,原来你就是视频里的人

对的,是我
开往春天的手扶拖拉机
回复 支持 反对

使用道具 举报

3

主题

26

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
218
金钱
218
注册时间
2018-7-12
在线时间
34 小时
发表于 2018-11-15 16:01:47 | 显示全部楼层
请教一下楼主,假如我有一个数组u16 B[2]={0x1c77,0x1c76};,想把这个数组中的数值转换为十进制,在传入参数的时候做了强制转换charhex_to_dec((char*)B[0]);        为什么转换出来的数值是0啊?
回复 支持 反对

使用道具 举报

0

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
54
金钱
54
注册时间
2019-1-14
在线时间
8 小时
发表于 2019-2-20 10:07:14 | 显示全部楼层
感谢楼主分享
回复 支持 反对

使用道具 举报

4

主题

33

帖子

0

精华

初级会员

Rank: 2

积分
195
金钱
195
注册时间
2014-1-11
在线时间
81 小时
发表于 2019-8-13 14:12:47 | 显示全部楼层
@zuozhongkai   版主您好,

您这段代码最后用什么编译软件测试的?   
回复 支持 反对

使用道具 举报

0

主题

131

帖子

0

精华

初级会员

Rank: 2

积分
175
金钱
175
注册时间
2019-7-1
在线时间
6 小时
发表于 2019-8-13 14:27:59 | 显示全部楼层
谢谢楼主分享
IIS7站长  http://www.iis7.com/
回复 支持 反对

使用道具 举报

7

主题

175

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1327
金钱
1327
注册时间
2019-7-11
在线时间
165 小时
发表于 2019-8-13 14:51:14 | 显示全部楼层
castle 发表于 2018-11-15 16:01
请教一下楼主,假如我有一个数组u16 B[2]={0x1c77,0x1c76};,想把这个数组中的数值转换为十进制,在传入参 ...

楼主做的是字符串转换成数
你这个本身就是数了
直接printf("%d",B[0]);读出来就是十进制了
世界和平
回复 支持 反对

使用道具 举报

7

主题

175

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1327
金钱
1327
注册时间
2019-7-11
在线时间
165 小时
发表于 2019-8-13 14:53:13 | 显示全部楼层
无情公子 发表于 2019-8-13 14:12
@zuozhongkai   版主您好,

您这段代码最后用什么编译软件测试的?

这一段C代码应该平台无关的哦 注意u8是unsigned char u16是unsigned short就好啦
世界和平
回复 支持 反对

使用道具 举报

0

主题

3

帖子

0

精华

初级会员

Rank: 2

积分
76
金钱
76
注册时间
2020-5-12
在线时间
41 小时
发表于 2020-5-15 10:45:05 | 显示全部楼层
chrlen=strlen(chr);这行编译有错误
回复 支持 反对

使用道具 举报

6

主题

21

帖子

0

精华

新手上路

积分
39
金钱
39
注册时间
2021-3-23
在线时间
8 小时
发表于 2021-7-24 16:07:35 | 显示全部楼层
hi我歌月徘徊 发表于 2017-10-20 13:50
最近遇到了浮点数如何发送的问题

char buffer【1024】;

浮点型数据建议使用比例尺进行缩放后再操作
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-25 10:14

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表