振南技术干货集:C语言的一些“骚操作”及其深层理解(3)

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 1个月
简介: 振南技术干货集:C语言的一些“骚操作”及其深层理解(3)

注解目录

第二章《c语言的一些“操作”及其深层理解》

一、字符串的实质就是指针

(如何将 35 转为对应的十六进制字符串”0X23”?)

二 、转义符\

(打入字符串内部的“奸细”。)

三、字符串常量的连接

(字符串常量是双面胶,你知道吗?)

四、长字符串的拆分技巧

(GPS 数据帧 NMEA、Shell 命令行和 AT 指令的解析,是长串拆分的典型应用。)

五、巧取数值的各位数码

(玩多位数码管的必有操作。)

六、printf 的实质与使用技巧

(自认为很了解 printf?那你试过向 3 个 UART 打印吗?或者打印到液晶屏上?)

七、关于浮点数的传输

(浮点只是一种假象,看清它的本质。)

八、关于数据的直接操作

(如何快速计算浮点的相反数,乘以-1.0?再想想。)

九、 浮点的四舍五入与比较

(老师说浮点不能直接判等,为什么?)

十、的 出神入化的 for 循环

(for 循环很熟悉了吧?OK,振南出了几道题,来试试。)

十一、 隐藏的死循环

(我们在明处,有时死循环在暗处。)

十二、 看似多余的空循环

(没用的东西?)

十三、 独立执行体

(这个概念 C 语言里没学过?那就对了,我经常用。)

十四、 多用() 无坏处

(万物皆可加括号。)

十五、== 的反向测试

(把==错写成=,能让你调程序调到吐血。)

十六、 赋值操作的实质

(让数学教授困惑半生的 C 语言赋值操作。)

十七、 关于补码

(摊牌了,CPU 其实不会作减法。)

十八、 关于-1

(-1 就是全 F,全 F 就是-1。)

二十、字节快速位逆序

(时间与空间的相互转化--计算机中的相对论)

二十一、关于 volatile

(有些东西不可优化。)

二十二、关于变量互换

(位操作的奇妙。)

二十三、关于 sizeof

(告诉你关于 sizeof 那些少人关注的问题。)

二十四、memcpy 的效率

(小小的函数也有大大的背景)

二十五、[] 的本质

(你以为[]只是数组下标?)

二十六、# 与##( 串化与连接)

(一个不曾出现在 C 语言教材中的知识点)

1

字符串的实质就是指针

长字符串的拆分技巧

很多时候我们需要进行长字符串的拆分。在振南的研发经历中,使用到这种操作的最典型的应用场合有三个。

1.NMEA 协议数据的解析

NMEA 可能很多人不太了解,但是说到GPS肯定大家都很熟悉。当我们从GPS 模块中读取定位信息的时候,数据就是遵循NMEA协议格式的。图 2.2 为一个标准的GPS数据帧。

图 2.2 一个符合 NMEA 协议标准的 GPS 数据帧

整个数据帧采用ASCII编码,它以 $GP作为开始,后面依次排列的是各项参数,参数之间使用,作为分隔。比如 $GPRMC为推荐定位信息,我当时就是使用这一条数据来获取经纬度信息的(当时是 Intel 杯嵌入式邀请赛需要作一个手持 GPS 跟踪器)。这条数据中N后面是纬度,E后面是经度。我们要作的就是将它们从整个数据帧(一个长字符串)中提取出来。所以,这就涉及到了所谓的“长串拆分”。

2.Shell 命令行的命令解析

在很多项目中,我都习惯于基于串口编写一个后台 Shell 系统,可以起到一个基本的调试作用。从而一定程度上减少修改代码和固件烧录的次数。比如,项目中如果涉及DAC电压经常的调整输出,我就会在后台中设计一个命令SetVn,以便随时灵活的操控DAC。随着项目功能的升级,后台命令也会变得开始复杂。比如 SetArg a b c d e f g h.... ,用于同时设置程序中多个关键参数的值;再比如 SetV channel n freq a,设置某通道第n个信号的输出幅值和频率。

这些命令通过PC上的串口助手或调试终端来发送,比如超级终端、 SecureCRT 或 XShell等。程序中从串口接收到命令之后,将其放入内存的缓冲区中,其形式就是一个字符串。命令字以及后面的若干参数之间使用空格来分隔。程序要匹配命令字,并提取参数,以便执行相应的操作。所以,这也涉及长串的拆分。

3.DTU 模块的 AT 指令解析

AT指令其实和NMEA 是一个道理,它们都是一种通信协议格式,只不过AT指令更多使用在网络通信模块中,比如SIM800 、 ESP8266 、 HC06 蓝牙串口等。举个例子,我们想知道网络信号强度,就可以向模块发送” AT+CSQ\r\n ”,模块会返回” +CSQ:29 , 0\r\n ”。CSQ:后面的 29 就是信号强度。它们都是ASCII编码的,也就是一个字符串。我们需要将 29 从其中提取出来。当然,AT 指令也有比较复杂的,字符串会比较长,包含的参数也会比较多。所以,要想使用这些网络模块实现网络通信,就必须实现对 AT 指令的解析。

说了这么多,都是在说长串拆分很重要。根本问题是如何实现它?很多人可能都会想到使用那个分隔字符,比如空格、逗号。然后去一个个数要提取的参数前面有几个分隔字符,然后后将相应位置上的字符组成一个新的短字符串,如图 2.3 所示

图 2.3 通过分隔字符定位要提取的部分

这种方法固然可行,但是略显笨拙。其实对于这种有明显分隔符的长字符串,我们可以采用“打散”或“爆炸”的思想,具体过程是这样的:将长字符串中的所有分隔符全部替换为’\0 ’,即字符串结束符。此时,长字符串就被分解成了在内存中顺序存放的若干个短字符串。如果要取出第 n 个短字符串,可以用这个函数:

char*substr ( char*str , n )

{

unsigned charlen=strlen ( str );

for (; len ﹥ 0 ; len-- ){if ( str [ len-1 ] ==ˈˈ )str [ len-1 ] =0 ;}

for (; n ﹥ 0 ; n-- )

{

str+= ( strlen ( str ) +1 );

}

returnstr ;

}

很多时候我们需要一次性访问长字符串中的多个短字符串,此时振南经常会这样来作:通过一个循环,将长字符串中的所有分隔符替换为’\0 ’,在此过程中将每一个短字符串首字符的位置记录到一个数组中,代码如下:

好,举个例子:我们要提取”abc 1000 50 off 2500 ”中的” abc ”、” 50 ”和” off ”,可以使用上面的函数来实现。


相关文章
|
6月前
|
算法 编译器 Shell
振南技术干货集:C语言的一些“骚操作”及其深层理解(7)
振南技术干货集:C语言的一些“骚操作”及其深层理解(7)
|
6月前
|
存储 Shell 定位技术
振南技术干货集:C语言的一些“骚操作”及其深层理解(5)
振南技术干货集:C语言的一些“骚操作”及其深层理解(5)
|
6月前
|
缓存 编译器 Shell
振南技术干货集:C语言的一些“骚操作”及其深层理解(9)
振南技术干货集:C语言的一些“骚操作”及其深层理解(9)
|
4月前
|
C语言
C语言100道基础拔高题(2)
【7月更文挑战第26天】
38 2
|
6月前
|
存储 Shell 定位技术
振南技术干货集:C语言的一些“骚操作”及其深层理解(4)
振南技术干货集:C语言的一些“骚操作”及其深层理解(4)
|
6月前
|
算法 Shell Serverless
振南技术干货集:C语言的一些“骚操作”及其深层理解(1)
振南技术干货集:C语言的一些“骚操作”及其深层理解(1)
|
6月前
|
存储 编译器 Shell
振南技术干货集:C语言的一些“骚操作”及其深层理解(8)
振南技术干货集:C语言的一些“骚操作”及其深层理解(8)
|
6月前
|
Shell 定位技术 C语言
振南技术干货集:C语言的一些“骚操作”及其深层理解(10)
振南技术干货集:C语言的一些“骚操作”及其深层理解(10)
|
6月前
|
存储 移动开发 Shell
振南技术干货集:C语言的一些“骚操作”及其深层理解(2)
振南技术干货集:C语言的一些“骚操作”及其深层理解(2)
|
6月前
|
编译器 Shell 定位技术
振南技术干货集:C语言的一些“骚操作”及其深层理解(6)
振南技术干货集:C语言的一些“骚操作”及其深层理解(6)