原文发布于:https://www.chenxublog.com/2020/03/08/c-fast-convert-hex-char-array.html

博客园仅供存档,如果有优化余地,也不会进行后续更正

缘由

这个起因是昨晚群里有人在讨论怎么把字符串转成HEX方法最佳,讨论到最后变成哪种方法效率最优了。毕竟这代码是要在MCU上面跑的,要同时考虑到时间和空间的最优解。

当然讨论的是有结果的,具体实现的方法和代码在下面展示。

char数组转16进制HEX串

例子:

将如下的量

char str[] = "12345";
char data[] = {1,2,3,4,5,0xff};

转成

"313233343500"
"0102030405FF"

这样的结果

这个其实很简单,追求速度的话,查表就好了

0-16对应0-F即可:

const char hex_table[] = {
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
};

然后一个个从表里取出来,拼到对应位置即可:

void to_hex(char *s, int l, char *d)
{
while(l--)
{
*(d+2*l+1) = hex_table[(*(s+l))&0x0f];
*(d+2*l) = hex_table[(*(s+l))>>4];
}
}

完整测试代码如下:

#include <stdio.h>
const char hex_table[] = {
'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
};
void to_hex(char *s, int l, char *d)
{
while(l--)
{
*(d+2*l+1) = hex_table[(*(s+l))&0x0f];
*(d+2*l) = hex_table[(*(s+l))>>4];
}
}
int main () {
char s[]= "1234";
char d[9];
d[8] = '\0';
to_hex(s,4,d);
printf("%s",d);
return 0;
}

输出结果:31323334

16进制HEX串转成数值数组

例子:

将类似"AAbb2fFF"的量转成{0xAA,0xBB,0x2F,0xff}这样的结果

这里如果还用查表的话,这个rom占用会浪费掉不少空间,所有查表法直接就被否决掉了(如果是PC上,追求极致速度的话,当然可以用)。

同时,为了通用性,代码需要兼容大小写两种输入数据

在仔细研究数据的结构时,我发现了个规律:

ASCII中的0-9对应了0x30-0x39

ASCII中的A-F对应了0x41-0x46

ASCII中的a-f对应了0x61-0x66

也就是说,只要这一个字符大于0x39,那它一定是字母;同时,在上面的分析也可以发现,如果这个字符是字母,不论大写小写,只需要看低四位就可以直接判断这个字符代表的数是多少

具体逻辑如下:

判断这个字符是否大于0x39

如果不是,直接取这个字符的低四位当作结果

如果是,则为字母,将他的低四位加上9即为所需结果

具体实现代码也如下:

void from_hex(char *s, int l, char *d)
{
while(l--)
{
char* p = s+l;
char* p2 = p-1;
*(d+l/2) =
( (*p>'9'? *p+9 : *p) & 0x0f ) |
( (*p2>'9'? *p2+9 : *p2) << 4 );
l--;
}
}

完整的测试代码:

#include <stdio.h>

void from_hex(char *s, int l, char *d)
{
while(l--)
{
char* p = s+l;
char* p2 = p-1;
*(d+l/2) =
( (*p>'9'? *p+9 : *p) & 0x0f ) |
( (*p2>'9'? *p2+9 : *p2) << 4 );
l--;
}
} int main () {
char s[]= "6F6B6f6b";
char d[5];
d[4] = '\0';
from_hex(s,8,d);
printf("%s",d);
return 0;
}

输出结果:okok

EOF

原文先发布于:https://www.chenxublog.com/2020/03/08/c-fast-convert-hex-char-array.html

如果你有更好的方法,欢迎在原文下面留言讨论

适合MCU用的C语言快速互转HEX(16进制)和原始字符串/数组方法的更多相关文章

  1. 运用C语言将图片转换成16进制的字符串(base64)

    最近在写手机端的性能测试脚本的时候,发现手机在上传图片数据时,先将图片转换成一堆16进制的字符,将字符传输过去,服务器再将字符解码成图片 我们在loadrunner中测试时,就需要用C语言将图片编码. ...

  2. python进制转化函数,10进制字符串互转,16进制字符串互转

    来了老弟,emmmmm,今天想到平时经常用到编码转化,把字符串转化为16进制绕过等等的,今天想着用python写个玩,查询了一些资料,看了些bolg 上面的两个函数是将二进制流转化为16进制,data ...

  3. 使用Apache的Hex类实现Hex(16进制字符串和)和字节数组的互转

    包名称:org.apache.commons.codec.binary 类名称:org.apache.commons.codec.binary.Hex 1.字节数组(byte[])转为十六进制(Hex ...

  4. 实战项目开发细节:C语言分离一个16进制数取出相应的位1或0

    最近在公司开发一个关于钢琴的PCBA项目,项目大概是这样的,完成各种功能的测试,准备去工厂量产的时候可以通过软件快速甄别硬件是否短路,断路等问题. 其中,甄别好坏的方法是通过比如按键,或者其它的操作然 ...

  5. python模块介绍- binascii:二进制和ASCII互转以及其他进制转换

    20.1 binascii:二进制和ASCII互转作用:二进制和ASCII互相转换. Python版本:1.5及以后版本 binascii模块包含很多在二进制和ASCII编码的二进制表示转换的方法.通 ...

  6. WinHex V18.7(16进制编辑器) 多国语言绿色版

    软件名称: WinHex V18.7(16进制编辑器)软件语言: 简体中文授权方式: 免费试用运行环境: Win7 / Vista / Win2003 / WinXP 软件大小: 1.7MB图片预览: ...

  7. C语言dos程序源代码分享(进制转换器)

    今天给大家分享一个dos程序的源代码 这个程序是本人在学习中的经验分享 如果有问题或者建议,欢迎大家一起交流 源代码: /*本程序为一个进制转换器 本程序不作为商业用途,完全为技术交流 喜欢C语言的同 ...

  8. C#数字、16进制字符串和字节之间互转

    转自http://luohonghong.blog.163.com/blog/static/78312058201242632055642/ 如下: .数字和字节之间互转 ; byte[] bytes ...

  9. RGB与16进制色互转

      点击进入新版 <前端在线工具站> CSS, JavaScript 压缩YUI compressor, JSPacker...HTML特殊符号对照表PNG,GIF,JPG... Base ...

随机推荐

  1. 使用ArcGIS实现WGS84经纬度坐标到北京54高斯投影坐标的转换

    [摘 要] 本文针对从事测绘工作者普遍遇到的坐标转换问题,简要介绍ArcGIS实现WGS84经纬度坐标到北京54高斯投影坐标转换原理和步骤. [关键词] ArcGIS 坐标转换 投影变换 1 坐标转换 ...

  2. 关于mysql的符合主键的定义和解释

    DROP TABLE IF EXISTS `v9_vote_data`;CREATE TABLE `v9_vote_data` (  `userid` mediumint(8) unsigned DE ...

  3. Point Estimate|unbiased estimator|Confidence-Interval Estimate

    8.1 Estimating a Population Mean Point Estimate estimate  a single number, or point. 因为:the mean of ...

  4. sqlite基础API

    /* 打开/创建数据库文件 * 如果数据库文件不存在就创建数据库文件. * 数据库操作句柄保存在第二个参数中. * 第一个参数:文件路径及其文件名 * 第二个参数:sqlite3操作句柄 * 返回值: ...

  5. PCIe的事务传输层的处理(TLP)

    主要从以下几个方面解决: 1.TLP基本的概念: 2.寻址定位与路由导向 3.请求和响应机制 4.虚拟通道机制 5.数据完整性 6.i/o,memory,configuration,message r ...

  6. LeetCode Day 4

    LeetCode0011 给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) .在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, ...

  7. tomcat一闪而过

    JAVA_HOME should point to a JDK not a JRE |vista tomcat 有的朋友在启动Tomcat的时候会出现问题. 1例如: 手动点击startup.bat ...

  8. [洛谷P4299] 首都

    题目传送门 还是维护子树信息. 但是这里多了一个找重心的操作. 这里有一个关于树重心的结论,据说可以用反证法证明.反正我不会证 就是:新的重心一定在原来两个重心之间的那条树链上. 这样我们逐步缩小搜索 ...

  9. es6 转载

    1.let命令 1)let和var的区别:let声明的变量只有所在的代码块有效. 2)没有变量的提升,一定要声明后使用.使用let命令声明变量之前,该变量都是不可用的.形成“暂时性死区”. 3)typ ...

  10. SWUST OJ Gold Nuggets Distribution(0490)

    Gold Nuggets Distribution(0490) Time limit(ms): 1000 Memory limit(kb): 65535 Submission: 421 Accepte ...