C语言快速互转HEX(16进制)和原始字符串/数组

news2024/11/18 11:26:16

C语言快速互转HEX(16进制)和原始字符串/数组

缘由

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

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

char数组转16进制HEX串

例子:

将如下的量

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

C

Copy

转成

"313233343500""0102030405FF"12

C

Copy

这样的结果

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

0-16对应0-F即可:

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

C

Copy

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

voidto_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];}}12345678

C

Copy

完整测试代码如下:

#include<stdio.h>constchar hex_table[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};voidto_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);return0;}1234567891011121314151617181920

C

Copy

输出结果:31323334

****** 带分隔符的字符串转Hex数组*****

const char hex_table[] = {

'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'

};

//返回实际长度,空间不足返回-1

int to_hex(char *src, int len, char* seg, int slen, char *dst, int dlen)

{

int size = 2*len+(len-1)*slen;

if(dlen < size) {

return -1;

}

while(len--)

{

*(dst+2*len+1+len*slen) = hex_table[(*(src+len))&0x0f];

*(dst+2*len+len*slen) = hex_table[(*(src+len))>>4];

for(int ii=0; ii < slen; ii++) {

*(dst+2*len+(len-1)*slen+ii) = *(seg+ii);

}

}

return size;

}

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即为所需结果

具体实现代码也如下:

voidfrom_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--;}}123456789101112

C

Copy

完整的测试代码:

#include<stdio.h>1

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;

}

C

Copy

输出结果:okok

EOF

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

更新

2020.3.9:Antecer带来了更高效的hex转数组代码

#include<stdio.h>1

void from_hex(char s, int l, char d)

{

while(l–)

{

d = (s>‘9’ ? s+9 : s) << 4;

++s;

d |= (s>‘9’ ? s+9 : s) & 0x0F;

++s;

++d;

}

}

int main () {

char s[]= “6F6B6f6b”;

char d[5];

d[4] = ‘\0’;

from_hex(s,4,d);

printf("%s",d);

return 0;

}

C

Copy

因为传入的指针是临时变量,所以数组转hex也可以按此思路稍微优化下:

#include<stdio.h>constchar hex_table[]={‘0’,‘1’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’,‘8’,‘9’,‘A’,‘B’,‘C’,‘D’,‘E’,‘F’};voidto_hex(chars,int l,chard){while(l–){d = hex_table[s >>4];
d++;d = hex_table[s &0x0f];
s++;
d++;}}int main (){char s[]=“1234”;char d[9];
d[8]=‘\0’;to_hex(s,4,d);printf("%s",d);return0;}1234567891011121314151617181920212223

C

Copy

2020.3.10:稀饭放姜发现内嵌“++”操作比单独写一行运行要快

hex转数组:

#include<stdio.h>1

void from_hex(char s, int l, char d)

{

while(l–)

{

(d++) = ( (s>‘9’ ? (s++)+9 : (s++)) << 4 )

| ( (s>‘9’ ? (s++)+9 : *(s++)) & 0x0F );

}

}

int main () {

char s[]= “6F6B6f6b”;

char d[5];

d[4] = ‘\0’;

from_hex(s,4,d);

printf("%s",d);

return 0;

}

C

Copy

数组转hex:

#include<stdio.h>constchar hex_table[]={‘0’,‘1’,‘2’,‘3’,‘4’,‘5’,‘6’,‘7’,‘8’,‘9’,‘A’,‘B’,‘C’,‘D’,‘E’,‘F’};voidto_hex(chars,int l,chard){while(l–){(d++)= hex_table[s >>4];(d++)= hex_table[(s++)&0x0f];}}int main (){char s[]=“1234”;char d[9];
d[8]=‘\0’;to_hex(s,4,d);printf("%s",d);return0;}1234567891011121314151617181920

C

Copy

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/148281.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java8流式计算相关

目录 lambda 优点 语法介绍 语法格式一 : 语法格式二 : 语法格式三 : 语法格式四 : 语法格式五 : 语法格式六 : 方法引用 stream Stream流的常用方法&#xff1a; 创建动态list 创建固定长度list map filter groupingBy sum list转map&#xff1a; map转li…

谷粒商城学习笔记

docker 安装docker docker官方centos镜像下载地址&#xff1a;https://docs.docker.com/engine/install/centos/ 步骤&#xff1a; 先卸载&#xff0c;如果不是root用户在前边加上sudo sudo yum remove docker \docker-client \docker-client-latest \docker-common \docke…

C 程序设计教程(05)—— C 语言的数据类型(三):指针类型

C 程序设计教程&#xff08;05&#xff09;—— C 语言的数据类型&#xff08;三&#xff09;&#xff1a;指针类型 该专栏主要介绍 C 语言的基本语法&#xff0c;作为《程序设计语言》课程的课件与参考资料&#xff0c;用于《程序设计语言》课程的教学&#xff0c;供入门级用…

MySql中json类型数据的查询以及在MyBatis-Plus中的使用

表结构和初始数据 新建表结构 CREATE TABLE json_test (id int NOT NULL AUTO_INCREMENT,roles json DEFAULT NULL COMMENT 角色,project json DEFAULT NULL COMMENT 项目,PRIMARY KEY (id) ) ENGINEInnoDB;初始数据 INSERT INTO ctts_dev.json_test(id, roles, project) VALU…

SpringBoot 整合 xxl-job

文章目录部署 xxl-jobSpringBoot 配置maven 配置application.yaml配置 XxlJobConfigXxlJobSpringExecutor新建执行任务配置 xxl-job-admin执行器管理任务管理部署 xxl-job K8S 部署 xxl-job 参考文档&#xff1a;https://blog.csdn.net/weixin_42555971/article/details/12489…

【Web开发】Python实现Web服务器(Docker下部署Flask)

&#x1f37a;基于Python的Web服务器系列相关文章编写如下&#x1f37a;&#xff1a; &#x1f388;【Web开发】Python实现Web服务器&#xff08;Flask快速入门&#xff09;&#x1f388;&#x1f388;【Web开发】Python实现Web服务器&#xff08;Flask案例测试&#xff09;&a…

分享112个PHP源码,总有一款适合您

PHP源码 分享112个PHP源码&#xff0c;总有一款适合您 链接&#xff1a;https://pan.baidu.com/s/1MaBtjYZk08o0eJT5_E79aQ?pwduldm 提取码&#xff1a;uldm 下面是文件的名字&#xff0c;我放了一些图片&#xff0c;文章里不是所有的图主要是放不下...&#xff0c;大家下载…

实战丨从0到1搭建结算平台

一、概述我们最开始分享了O2O电商支付清结算体系&#xff0c;接着分享了如何从0-1搭建计费体系&#xff0c;接下来我们分享&#xff1a;各方的钱算完之后怎么付出去&#xff0c;也即结算平台建设的实操与设计思路。1.什么是结算&#xff1f;说结算平台之前&#xff0c;先说一下…

22年 | 年前总结 | 主业谋生存,副业谋发展

22年关键词 复盘 | 极简 | 长期主义 | 阅读 | 斜杠青年 | 一事无成 | … 当然了&#xff0c;2023也会继续延续某些关键词。 一壶清酒&#xff0c;敬这红尘也敬我 很多人都在说&#xff0c;疫情存在的时间比任何一段恋情还要长。 而我想说&#xff0c;我失败的次数还超过了做…

Java设计模式中策略模式是怎么回事/怎么替代繁琐if-else语句/如何优化条件选择语句

继续整理记录这段时间来的收获&#xff0c;详细代码可在我的Gitee仓库SpringBoot克隆下载学习使用&#xff01; 6.3 策略模式 6.3.1 概述 定义了一系列算法&#xff0c;并将每个算法封装起来&#xff0c;使它们可以相互替代&#xff0c;且算法的变化不会影响使用算法的用户属…

【自学Python】Python注释

文章来源嗨客网&#xff08;www.haicoder.net&#xff09; Python注释 Python注释教程 用于注解说明解释程序的文字就是注释&#xff0c;注释提高了代码的阅读性。一旦程序中某部分内容被注释掉&#xff0c;则该内容将会被 Python 解释器忽略&#xff0c;换句话说&#xff0c…

一般颜色直方图

颜色直方图是一种用于图像处理和分析的图表&#xff0c;它可以显示图像中不同颜色的数量。通常&#xff0c;颜色直方图会将颜色分成几个色调区间&#xff0c;每个区间对应一个条形图&#xff0c;其中条形图的高度表示该色调区间中的像素数量。通过颜色直方图&#xff0c;你可以…

Mask RCNN网络源码解读(Ⅰ) --- 语义分割前言与转置卷积

目录 1.什么是语义分割 2.语义分割常见的数据集格式 3.常见的语义分割评价指标 4.转置卷积 1.什么是语义分割 常见分割任务&#xff1a;语义分割、实例分割、全景分割 图一 原始图片图二 语义分割图三 实例分割语义分割&#xff08;例如FCN网络&#xff09;可以理解为一个…

开发与项目经理之间的打情骂俏——数据库篇

&#x1f466;&#x1f466;一个帅气的boy&#xff0c;你可以叫我Love And Program &#x1f5b1; ⌨个人主页&#xff1a;Love And Program的个人主页 &#x1f496;&#x1f496;如果对你有帮助的话希望三连&#x1f4a8;&#x1f4a8;支持一下博主 由数据库引发的一系列探…

小论文写作指南(AI类)

参考b站沃恩智慧课程 论文结构 标题:不要太长或太短,抓住重点,简明扼要。 作者:你的作品一定力争一作,通讯作者是导师/大老板/出资人。 摘要Abstract:点明大背景(如为什么研究微表情识别,对社会有什么价值,拔高立意层次),阐述目标(我们提出模型为了在什么问题上达…

9个时间序列交叉验证方法的介绍和对比

评估性能对预测模型的开发至关重要。交叉验证是一种流行的技术。但是在处理时间序列时&#xff0c;应该确保交叉验证处理了数据的时间依赖性质。在之前的文章中&#xff0c;我们也做过相应的介绍。 在本文中&#xff0c;我们收集了时间序列的常用的9种交叉验证方法。这些包括样…

【博客578】LVS NAT配合MASQUERADE实现FULLNAT的场景,及此场景下net.ipv4.vs.conntrack参数的重要作用

LVS NAT配合MASQUERADE实现FULLNAT的场景&#xff0c;及此场景下net.ipv4.vs.conntrack参数的重要作用 1、LVS基本原理&#xff1a; 流程&#xff1a; 当用户向负载均衡调度器&#xff08;Director Server&#xff09;发起请求&#xff0c;调度器将请求发往至内核空间 PREROU…

第6章 线程通信

6.2.1 管道 管道是一个线性字节数组,类似文件,使用文件读写进行访问&#xff1b;在程序里面,创建管道需要使用popen()或者pipe(); 管道的一个重要特点是使用管道的两个线程之间必须存在某种关系, 例如,使用popen需要提供另一端进程的文件名,使用pipe的两个线程分别隶属于父子进…

Linux常用命令——fgrep命令

在线Linux命令查询工具 fgrep 为文件搜索文字字符串 补充说明 fgrep命令是用来搜索 file 参数指定的输入文件&#xff08;缺省为标准输入&#xff09;中的匹配模式的行。fgrep 命令特别搜索 Pattern 参数&#xff0c;它们是固定的字符串。如果在 File 参数中指定一个以上的…

dp刷题(三)编辑距离(Hard)

编辑距离_牛客题霸_牛客网 描述 给定两个单词word1和word2&#xff0c;请计算将word1转换为word2至少需要多少步操作。 你可以对一个单词执行以下3种操作&#xff1a; a&#xff09;在单词中插入一个字符 b&#xff09;删除单词中的一个字符 c&#xff09;替换单词中的一个字…