C语言中字符串比较_c语言字符串比较-程序员宅基地

技术标签: c语言  C语言学习笔记  字符串  串口  处理  STM8学习笔记  STM32学习笔记  命令  

       在 单片机串口实现字符串命令解析 这篇文章中分析了在串口通信中如何去解析字符串命令,这篇文章就来讨论下字符串比较的方法都有哪些?

      说起比较运算,肯定第一时间想到了C语言中关于比较的相关运算符 “>、<、!=、>=、<=、==”,那么要比较两个字符串是否相等是不是直接用“==”比较就行了。下面就来看看这种方法行不行?

    先看一个例子

void main( void )
{
    char s1[] = "abc";
    char s2[] = "abc";    
    __asm( "sim" );                             //禁止中断
    SysClkInit();
    delay_init( 16 );
    LED_GPIO_Init();
    BEEP_GPIO_Init();
    Uart1_Init( 9600 );
    __asm( "rim" );                             //开启中断
    while( 1 )
    {
        if( s1 == s2 )
        {
            printf( "equal" );
        }
        else
        {
            printf( "Not equal" );
        }
    }
}

有两个字符串s1和s2,内容都是"abc",在if语句中通过"=="运算符进行比较。

         运行结果是s1和s2不相等,那为什么是不相等呢,通过右边的观察窗口可以看到,s1和s2是内部的两个存储空间,地址不一样,但是地址中的内容是一样的。那么用“ if( s1 == s2 )”这行语句去比较的时候,其实比较的是s1和s2的地址,不是比较地址中的内容,而s1和s2的地址是不相同的。

要比较内容的话,代码需要修改一下。

  if(( s1[0] == s2[0] )&&( s1[1] == s2[1] )&&( s1[2] == s2[2] ))
        {
            printf( "equal" );
        }
        else
        {
            printf( "Not equal" );
        }

将代码修改为依次比较字符串中的内容

通过字符串的每一位依次比较,这样的比较方式,就可以判断出字符串相等。

将字符串数组改为指针看看

        将s1和s2改为指针,可以看到通过"=="比较,结果是相等的。通过右边的观察窗口可以看出s1和s2的地址是相同的,也就是这两个字符串指向了同一个地址空间。说明此时比较的还是地址,而不是地址中的内容。我们需要比较的是内容。

将代码修改为获取指针的内容,发现比较结果也是相等的。那么能不能说明这种比较方法是可以的。将字符串内容修改一下在看看。

内容改变后,指针的地址也发生了改变,此时"s1==s2"语句就不成立了。

但是这时候"*s1==*s2"依然是相等的,这是为什么呢?通过右侧的观察窗口可以看到,此时*s1和*s2的内容是"a",而不是整个字符串的内容。说明这行代码比较的是字符串的第一个字符,而不是整个字符串。那么要比较整个内容的话,还得每个字符挨个比较。

通过上面的分析可能会有一个疑问,为什么用"=="运算符比较单个字符的时候比较的就是内容,而比较字符串的时候,比较的却是地址?

        这就要说下一字符串在C语言中比较特殊的一点,在C语言中处理一般的变量如整形、字符型、浮点型时,直接操作的是变量的值,比如 int a,b; a=b;在执行这行代码的时候,是将b的值拷贝一份然后复制给a。比较运算符“==”在使用的时候,也直接比较的是变量的值。而C语言在使用字符串的时候,是通过地址引用而不是值引用来操作的。

       通过数组定义的字符串,系统分配的是两个不同的地址,虽然内容相同,但是实际上地址是不相同的,通过相等运算符"=="比较时,比较的是s1和s2本身的值,s1和s2本身的值是一个地址,这两个地址不同,所以比较结果就不相等。

        用指针定义的两个字符串,系统分配的是同一个地址空间,说明虽然他们的名字不一样,但是实际上是共用了同一个地址。通过相等运算符"=="比较时,比较的是s3和s4本身的值,s3和s4本身的值是一个地址,这两个地址相同,所以比较结果相等。

通过上面的分析,发现在处理字符串的时候不能直接用"=="运算符去比较,那么要如何去比较呢?

可以直接使用 C 库函数 int strcmp(const char *str1, const char *str2) 把 str1 所指向的字符串和 str2 所指向的字符串进行比较。

该函数返回值如下:

  • 如果返回值小于 0,则表示 str1 小于 str2。
  • 如果返回值大于 0,则表示 str1 大于 str2。
  • 如果返回值等于 0,则表示 str1 等于 str2。

strcmp函数实际上是对字符的ASCII码进行比较,实现原理如下:首先比较两个串的第一个字符,若不相等,则停止比较并得出两个ASCII码大小比较的结果;如果相等就接着 比较第二个字符然后第三个字符等等。

这个函数其实就是相当于把上面例程中对字符串每个字符独立比较方法的一个封装,内部函数实现方式类似于下面这样。

由于字符串在C语言中的处理比较特殊,所以C语言提供了一个专门操作字符串的库。关于字符串的操作在"string.h"这个头文件中可以看到。

有字符串增加,字符串删除,字符串拷贝,字符串比较,字符串查找等等各种功能的函数封装,这样在处理字符串的时候就可以直接调用库函数来实现。

比如在处理串口命令的时候,如果串口命令为字符串,就可以直接用字符串比较命令去实现。

 if ( strcmp( uartRecStr, "led1 on" ) == 0 )
            {
                led1_on();
            }
            else if ( strcmp( uartRecStr, "led1 off" ) == 0 )
            {
                led1_off();
            }
            else if ( strcmp( uartRecStr, "led2 on" ) == 0 )
            {
                led1_off();
            }
            else if ( strcmp( uartRecStr, "led2 off" ) == 0 )
            {
                led1_off();
            }

将接收到字符串和指定的字符串比较,如果字符串相等,就调用相关的函数,这样通过if语句就可以简单的处理串口的指令。

不过通过if语句比较的话,程序的分支太多,程序看起来比较臃肿,能不能用switch语句去实现呢?但是switch语句中不支持字符串的比较直接比较,那要怎么实现?

char *cmdStr[] = {"led1 on", "led1 off", "led2 on", "led2 off"};  //字符串命令数组
len = sizeof( cmdStr ) / sizeof( cmdStr[0] );       //计算字符串个数
         for( i = 0; i < len; i++ )
            {
                if( strcmp( uartRecStr, cmdStr[i] ) == 0  )
                {
                    switch( i )//分支语句不支持字符串,通过字符串数组的下标确定是哪个字符串。
                    {
                    case 0:
                        led1_on();
                        break;
                    case 1:
                        led1_off();
                        break;
                    case 2:
                        led2_on();
                        break;
                    case 3:
                        led2_off();
                        break;
                    default:
                        break;
                    }
                }
            }

可以将字符串存储在数组中,通过数组的下标去调用不同的字符串,然后使用字符串比较函数去判断字符串,这样switch语句的分支判断就可以转换为字符串的下标。

通过这种方法就可以直接在串口中处理简单的通信命令了。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_20222919/article/details/109442687

智能推荐

C语言/C++常见习题问答集锦(三十二)之六种图案的字母金字塔_c++字母金字塔-程序员宅基地

文章浏览阅读5.7k次,点赞20次,收藏114次。字母金字塔图案1、A BBB CCCCC DDDDDDD图案2、A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 0 1 2 3 4 5 6 7 8 9图案3、A ABA ABCBA ABCDCBA图案4、A BB CCC DDDD EEEEE FFFFFF图案5、A BAB CBABC DCBABCD EDCBABCDE空心字母金字图案6、A B B C C D D EEEEEEEEE_c++字母金字塔

如何点击IE窗口上方的“X关闭符号”,弹出提示窗口呢? -程序员宅基地

文章浏览阅读972次。url:http://www.cnblogs.com/zhangzs8896/archive/2005/12/17/298899.html New Document function test() { return ""; } onbeforeunload="return test();"> _关闭符号

天坑的:Fatal Python error: init_sys_streams: can‘t initialize sys standard streams解决方案_fatal python error: init_sys_streams: can't initia-程序员宅基地

文章浏览阅读1.6w次,点赞7次,收藏18次。【问题描述】今天用pycharm新建工程突然提示:编译环境有问题,简单写了两行代码测试一直有问题, 报错如下:Fatal Python error: init_sys_streams: can’t initialize sys standard streams【原因分析】找了很多解决方案,结合错误提示,还是问题发生在虚拟环境下lib目录中的io.py身上,网上有好多老铁说改文件名字,然而证明并没有什么用,认真看下文件信息和内容发现并无区别,最后突然发现io.py的生成日期不对,恒新鲜,不是新建环境_fatal python error: init_sys_streams: can't initialize sys standard streams

7-4 稀疏矩阵加法 (20 分) pta_稀疏矩阵加法pta-程序员宅基地

文章浏览阅读1.9k次,点赞2次,收藏2次。7-4稀疏矩阵加法(20分)给定两个矩阵A和B,求其和矩阵C=A+B。输入格式:第一行包含两个数Row和Col,分别表示矩阵的行数和列数,A和B的维度是一致的。第二行只有一个数N​1​​,表示接下来要输入的A中的非零元素的个数。接下来是N​1​​行,每一行都是ijA[i,j]这样的形式,表示的A中第i行第j列的元素A[i,j],为了与大多数编程语言保持一致,它..._稀疏矩阵加法pta

【Android 安全】DEX 加密 ( Java 工具开发 | 解压 apk 文件 | 加密生成 dex 文件 | 打包未签名 apk 文件 | 文件解压缩相关代码 )_dex加密-程序员宅基地

文章浏览阅读1.9k次。一、解压 apk 文件、二、加密生成 dex 文件、三、打包未签名 apk 文件、四、完整代码示例、五、文件解压缩相关代码、六、执行结果_dex加密

kafka数据不丢失不重复_Kafka 之 如何保证数据不丢失?不重复?-程序员宅基地

文章浏览阅读217次。数据不丢失1)从生产端:acks = -1,(ack应答机制)从生产端到节点端,当所有isr集合里的节点备份完毕后返回成功;2)从节点端:每个partition至少需要一个isr节点(同步)存活保证数据安全3)从消费端:关闭自动提交,使用手动提交。数据不重复消费1)生产端生产者幂等性实现:PID和Sequence Number为了实现Producer的幂等性,Kafka引入了Producer ID..._kafka保证 不重复的pid

随便推点

解决php因内存不足httpd.exe错误方法!_httpd.exe重启不起来-程序员宅基地

文章浏览阅读246次。1,修改 php.ini将memory_limit由 8M 改成 16M(或更大),重启apache服务2,在PHP 文件中 加入 ini_set(”memory_limit”,”100M”);注意:为了系统的其它资源的正常使用 请您不要将 memory_limit设置太大,其中-1为不限3,修改.htaccess 文档(前提是该目录支持.htaccess)在文档中新增一句:p_httpd.exe重启不起来

分布式系统设计_分布式系统的设计审查清单-程序员宅基地

文章浏览阅读201次。分布式系统设计This article was originally published on my website — https://kislayverma.com/programming/design-review-checklist-for-distributed-systems/ 本文最初发布在我的网站上-https: //kislayverma.com/programming/desi...

数字图像处理-几何变换_冈萨雷斯 图像几何变换在第几章呢-程序员宅基地

文章浏览阅读2.4k次。本程序实现图像处理图像几何变换,基本原理参考冈萨雷斯《数字图像处理》(第二版)第五章中第十一小节。程序需要先调用cal_coef函数计算出来系数,然后调用Image_TransAffine函数得到几何变换后的图像。////////////////////////////////////////////////////////////////////////////函数名称:cal_coef//传入_冈萨雷斯 图像几何变换在第几章呢

IP-Guard如何清除安全密码?_agt3tool-程序员宅基地

文章浏览阅读972次。1、在开始->运行中,输入命令agt3tool ocularadv,调出客户端工具;如果是win7以上的电脑,需要在目录C:\Windows中,找到客户端工具Agt3Tool.exe,右键以管理员身份运行。2、在客户端工具界面上勾选“清除加密安全密码”,并生成操作码;3、在控制台上,工具 → 客户端工具 → 确认码计算器,将客户端上生成的操作码在此输入,进行解析;4、解析完成后会生成操作码,将操作码导入至客户端即可执行清除动作。..._agt3tool

iOS使用Charles(青花瓷)抓包并篡改请求头的数据_charles的请求头-程序员宅基地

文章浏览阅读2.7k次。第一步:编辑要修改的头部信息如图所示第二步:修改完重新执行接口如图所示_charles的请求头

python 一组数据 正态分布散点图_如何在SPSS、Python、R中用Q-Q图检验数据是否服从正态分布?...-程序员宅基地

文章浏览阅读505次。正态分布广泛存在于自然现象、生产、生活的方方面面,例如试卷命题难度,产品的使用寿命、农作物产量、气温、降水量、工资收入、人类的身高体重肺活量,甚至颜值……关于正态分布的数学定义及各种性质,不在此赘述。简单理解,就是“两头小,中间大”,比如长相奇丑无比和倾国倾城的人都是少数,绝大多数人都属于大众脸。很多时候,在进行数据分析工作时,首先要看的就是数据是服从何种概率分布,而正态分布则是最重要的一种概率分..._怎么制作散点图表示采样个体在全部个体中的分布位置

推荐文章

热门文章

相关标签