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

智能推荐

Spring Boot 获取 bean 的 3 种方式!还有谁不会?,Java面试官_springboot2.7获取bean-程序员宅基地

文章浏览阅读1.2k次,点赞35次,收藏18次。AutowiredPostConstruct 注释用于在依赖关系注入完成之后需要执行的方法上,以执行任何初始化。此方法必须在将类放入服务之前调用。支持依赖关系注入的所有类都必须支持此注释。即使类没有请求注入任何资源,用 PostConstruct 注释的方法也必须被调用。只有一个方法可以用此注释进行注释。_springboot2.7获取bean

Logistic Regression Java程序_logisticregression java-程序员宅基地

文章浏览阅读2.1k次。理论介绍 节点定义package logistic;public class Instance { public int label; public double[] x; public Instance(){} public Instance(int label,double[] x){ this.label = label; th_logisticregression java

linux文件误删除该如何恢复?,2024年最新Linux运维开发知识点-程序员宅基地

文章浏览阅读981次,点赞21次,收藏18次。本书是获得了很多读者好评的Linux经典畅销书**《Linux从入门到精通》的第2版**。下面我们来进行文件的恢复,执行下文中的lsof命令,在其返回结果中我们可以看到test-recovery.txt (deleted)被删除了,但是其存在一个进程tail使用它,tail进程的进程编号是1535。我们看到文件名为3的文件,就是我们刚刚“误删除”的文件,所以我们使用下面的cp命令把它恢复回去。命令进入该进程的文件目录下,1535是tail进程的进程id,这个文件目录里包含了若干该进程正在打开使用的文件。

流媒体协议之RTMP详解-程序员宅基地

文章浏览阅读10w+次,点赞12次,收藏72次。RTMP(Real Time Messaging Protocol)实时消息传输协议是Adobe公司提出得一种媒体流传输协议,其提供了一个双向得通道消息服务,意图在通信端之间传递带有时间信息得视频、音频和数据消息流,其通过对不同类型得消息分配不同得优先级,进而在网传能力限制下确定各种消息得传输次序。_rtmp

微型计算机2017年12月下,2017年12月计算机一级MSOffice考试习题(二)-程序员宅基地

文章浏览阅读64次。2017年12月的计算机等级考试将要来临!出国留学网为考生们整理了2017年12月计算机一级MSOffice考试习题,希望能帮到大家,想了解更多计算机等级考试消息,请关注我们,我们会第一时间更新。2017年12月计算机一级MSOffice考试习题(二)一、单选题1). 计算机最主要的工作特点是( )。A.存储程序与自动控制B.高速度与高精度C.可靠性与可用性D.有记忆能力正确答案:A答案解析:计算...

20210415web渗透学习之Mysqludf提权(二)(胃肠炎住院期间转)_the provided input file '/usr/share/metasploit-fra-程序员宅基地

文章浏览阅读356次。在学MYSQL的时候刚刚好看到了这个提权,很久之前用过别人现成的,但是一直时间没去细想, 这次就自己复现学习下。 0x00 UDF 什么是UDF? UDF (user defined function),即用户自定义函数。是通过添加新函数,对MySQL的功能进行扩充,就像使..._the provided input file '/usr/share/metasploit-framework/data/exploits/mysql

随便推点

webService详细-程序员宅基地

文章浏览阅读3.1w次,点赞71次,收藏485次。webService一 WebService概述1.1 WebService是什么WebService是一种跨编程语言和跨操作系统平台的远程调用技术。Web service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准...

Retrofit(2.0)入门小错误 -- Could not locate ResponseBody xxx Tried: * retrofit.BuiltInConverters_已添加addconverterfactory 但是 could not locate respons-程序员宅基地

文章浏览阅读1w次。前言照例给出官网:Retrofit官网其实大家学习的时候,完全可以按照官网Introduction,自己写一个例子来运行。但是百密一疏,官网可能忘记添加了一句非常重要的话,导致你可能出现如下错误:Could not locate ResponseBody converter错误信息:Caused by: java.lang.IllegalArgumentException: Could not l_已添加addconverterfactory 但是 could not locate responsebody converter

一套键鼠控制Windows+Linux——Synergy在Windows10和Ubuntu18.04共控的实践_linux 18.04 synergy-程序员宅基地

文章浏览阅读1k次。一套键鼠控制Windows+Linux——Synergy在Windows10和Ubuntu18.04共控的实践Synergy简介准备工作(重要)Windows服务端配置Ubuntu客户端配置配置开机启动Synergy简介Synergy能够通过IP地址实现一套键鼠对多系统、多终端进行控制,免去了对不同终端操作时频繁切换键鼠的麻烦,可跨平台使用,拥有Linux、MacOS、Windows多个版本。Synergy应用分服务端和客户端,服务端即主控端,Synergy会共享连接服务端的键鼠给客户端终端使用。本文_linux 18.04 synergy

nacos集成seata1.4.0注意事项_seata1.4.0 +nacos 集成-程序员宅基地

文章浏览阅读374次。写demo的时候遇到了很多问题,记录一下。安装nacos1.4.0配置mysql数据库,新建nacos_config数据库,并根据初始化脚本新建表,使配置从数据库读取,可单机模式启动也可以集群模式启动,启动时 ./start.sh -m standaloneapplication.properties 主要是db部分配置## Copyright 1999-2018 Alibaba Group Holding Ltd.## Licensed under the Apache License,_seata1.4.0 +nacos 集成

iperf3常用_iperf客户端指定ip地址-程序员宅基地

文章浏览阅读833次。iperf使用方法详解 iperf3是一款带宽测试工具,它支持调节各种参数,比如通信协议,数据包个数,发送持续时间,测试完会报告网络带宽,丢包率和其他参数。 安装 sudo apt-get install iperf3 iPerf3常用的参数: -c :指定客户端模式。例如:iperf3 -c 192.168.1.100。这将使用客户端模式连接到IP地址为192.16..._iperf客户端指定ip地址

浮点性(float)转化为字符串类型 自定义实现和深入探讨C++内部实现方法_c++浮点数 转 字符串 精度损失最小-程序员宅基地

文章浏览阅读7.4k次。 写这个函数目的不是为了和C/C++库中的函数在性能和安全性上一比高低,只是为了给那些喜欢探讨函数内部实现的网友,提供一种从浮点性到字符串转换的一种途径。 浮点数是有精度限制的,所以即使我们在使用C/C++中的sprintf或者cout 限制,当然这个精度限制是可以修改的。比方在C++中,我们可以cout.precision(10),不过这样设置的整个输出字符长度为10,而不是特定的小数点后1_c++浮点数 转 字符串 精度损失最小

推荐文章

热门文章

相关标签