OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 5864|回复: 13

用strcmp比较字符串有时候返回不对

[复制链接]

2

主题

18

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
393
金钱
393
注册时间
2017-4-21
在线时间
61 小时
发表于 2018-4-17 23:46:13 | 显示全部楼层 |阅读模式
5金钱
比较部分的代码如下:
int strcmp(const char *s1,const char *s2)
{
        //区分大小写
        for(;*s1==*s2;++s1,++s2)
        {
            if(*s1=='\0')
            {
                return(0);
            }
        }
        return((*(unsigned char*)s1<*(unsigned char*)s2)?-1:+1);
}

需要比较的字符串我是从串口中接收的,代码如下:
void getSerialData(UINT8 sdata)
{
    *p = sdata;
    ++p;
}
void USART1_IRQHandler(void)
{
    volatile char res;
    if(USART1->SR&(1<<5))
    {
        res = USART1->DR;
        getSerialData(res);
    }
}

调用的时候就是声明一个字符数组和一个指针,然后把数组的地址赋给指针。
类似如下的代码写在主函数里面:
char str[100], *p;
p=str;
strcmp(str, "abcdefg");
串口精灵里面写到串口接收的字符设定死了为“abcdefg”
但是有一定机率比较的时候是不同的。
不知道为什么,有没有坛友遇到过这种情况,怎么解决的。

最佳答案

查看完整内容[请看2#楼]

比较代码是基于'\0'作为字符串结束符,你串口接收的时候显然没有专门处理这块
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

192

帖子

0

精华

高级会员

Rank: 4

积分
582
金钱
582
注册时间
2017-6-2
在线时间
192 小时
发表于 2018-4-17 23:46:14 | 显示全部楼层
比较代码是基于'\0'作为字符串结束符,你串口接收的时候显然没有专门处理这块
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165536
金钱
165536
注册时间
2010-12-1
在线时间
2117 小时
发表于 2018-4-18 01:26:14 | 显示全部楼层
对比之前的两个字符串printf出来,可以辅助分析原因。
回复

使用道具 举报

2

主题

18

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
393
金钱
393
注册时间
2017-4-21
在线时间
61 小时
 楼主| 发表于 2018-4-18 09:41:32 | 显示全部楼层
正点原子 发表于 2018-4-18 01:26
对比之前的两个字符串printf出来,可以辅助分析原因。

基准字符串我是用#define BASE "abcdefg",这样定义的。
也有把待对比的字符串printf出来,字面上看没错。
比较的时候我是把结果放在if里面做判断,if(!strcmp(str, BASE ))这样,不知道会不会影响。
而且加大串口发送的速度的时候出现的频率会升高
回复

使用道具 举报

2

主题

18

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
393
金钱
393
注册时间
2017-4-21
在线时间
61 小时
 楼主| 发表于 2018-4-18 10:32:16 | 显示全部楼层
jkd405 发表于 2018-4-18 10:17
比较代码是基于'\0'作为字符串结束符,你串口接收的时候显然没有专门处理这块

那用strncmp就可以不需要\0了,但是我测试出来的结果是一样的,还是会对比不准确。
如果在串口里加上\0的处理我应该怎么做
回复

使用道具 举报

0

主题

192

帖子

0

精华

高级会员

Rank: 4

积分
582
金钱
582
注册时间
2017-6-2
在线时间
192 小时
发表于 2018-4-18 10:45:15 | 显示全部楼层
自己写比较函数,加一个长度参数,这个最简单,也最不容易出问题,因为不知道你具体要干什么不太好给意见
回复

使用道具 举报

11

主题

1044

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3722
金钱
3722
注册时间
2011-5-23
在线时间
2013 小时
发表于 2018-4-18 10:47:45 | 显示全部楼层
str都没有赋值。。。
里面是什么东西随缘吧!
RT-Thread RTOS 音频,WIFI,蓝牙
回复

使用道具 举报

2

主题

18

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
393
金钱
393
注册时间
2017-4-21
在线时间
61 小时
 楼主| 发表于 2018-4-18 10:55:21 | 显示全部楼层
aozima 发表于 2018-4-18 10:47
str都没有赋值。。。
里面是什么东西随缘吧!

你是说初始化么
回复

使用道具 举报

33

主题

215

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2035
金钱
2035
注册时间
2017-12-11
在线时间
454 小时
发表于 2018-4-18 11:27:44 | 显示全部楼层
以下为个人猜测:
楼主应该没有搞明白字符数组和指向字符串的指针之间的区别。
int strcmp(const char *s1,const char *s2)中++s2是建立在s2是一个字符数组的基础之上的,因为字符数组是存放在ram中的,可以对其中每个字符进行指针操作。
而“abcdefg”是一个指向字符串的指针,这个指针是不能移动的,因为这个字符串是放在flash(或者说是rom)中一个叫做string pool的地方,“abcdefg”是一个编译时期确定的const指针。
回复

使用道具 举报

7

主题

199

帖子

0

精华

高级会员

Rank: 4

积分
711
金钱
711
注册时间
2017-5-20
在线时间
96 小时
发表于 2018-4-18 14:24:46 | 显示全部楼层
一定要连同结束符‘\0’发送或者接受后添加进去。。。否则当然会随机不行。
或者建议使用更安全的strncmp();带长度的比较。
回复

使用道具 举报

2

主题

18

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
393
金钱
393
注册时间
2017-4-21
在线时间
61 小时
 楼主| 发表于 2018-4-18 21:06:40 | 显示全部楼层
本帖最后由 zhiyuan3635 于 2018-4-18 21:19 编辑
bootblack 发表于 2018-4-18 11:27
以下为个人猜测:
楼主应该没有搞明白字符数组和指向字符串的指针之间的区别。
int strcmp(const char *s ...

我先前有把这些基准的字符串都放在一个二维数组里面,但是效果也不是很好。
另外,const char *s2 中const修饰的不是指针,是指针指向的数据。如果是要修饰指针,应该写做char * const s2
回复

使用道具 举报

2

主题

685

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
3448
金钱
3448
注册时间
2017-7-4
在线时间
869 小时
发表于 2018-4-18 21:57:51 | 显示全部楼层
str没赋值,代码有指针的加“空语句”检测啊,养成好习惯!
回复

使用道具 举报

2

主题

18

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
393
金钱
393
注册时间
2017-4-21
在线时间
61 小时
 楼主| 发表于 2018-4-18 23:26:11 | 显示全部楼层
Acuity 发表于 2018-4-18 21:57
str没赋值,代码有指针的加“空语句”检测啊,养成好习惯!

嗯,为了简明扼要,部分代码没有贴出来。
进行处理的时候有进行空语句判断的。
谢谢
回复

使用道具 举报

2

主题

18

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
393
金钱
393
注册时间
2017-4-21
在线时间
61 小时
 楼主| 发表于 2018-4-18 23:31:22 | 显示全部楼层
zhiyuan3635 发表于 2018-4-18 23:26
嗯,为了简明扼要,部分代码没有贴出来。
进行处理的时候有进行空语句判断的。
谢谢

经过调试,应该是串口接收结束判断的问题。
处理方式:
开一个定时器做一个超时判断,超过一段时间没有数据接收,判断接收结束,然后进行数据处理。
连续测试1000个相同数据,发送间隔200ms,处理成功率100%。
定时器中断:
//定时器5中断服务程序         
void TIM5_IRQHandler(void)
{
    static uint16 timeOut=0;
        if(TIM5->SR&TIM_IT_Update)//溢出中断
        {
                TIM5->SR &= ~TIM_IT_Update ;//清除中断标志位
        if(fRcvOver==1)
        {
            if(++timeOut>25)
            {//250us时间判断
                timeOut = 0;
                fRcvOver= 0;
            }
        }
        }                                               
}
接收数据段
void getSerialData(char sdata)
{
    *p = sdata;
    ++p;
    fRcvOver = 1;
}

主循环中进行数据处理
if(!fRcvOver)
{
     StrRUN();
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-9 08:42

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表