C 使用strstr时出现奇怪错误

C 使用strstr时出现奇怪错误,c,substring,strstr,C,Substring,Strstr,我目前正在STM32F0上实现智能电表的SML读卡器。 一切正常,但我在使用string.h中的strstr时遇到问题 当前情况: 我有一个字符数组数据,它包含通过USART传入的所有数据。它包含十六进制数和有效的文本字符串 在这个字符串的某个地方有这样一个序列: {0x01,0x01,0x62,0x1b,0x52,0x00,0x55} 我想使用strstrstr查找此子字符串在数据字符串中的位置 它可以很好地处理这个示例字符串,它总是位于数据字符串的最开头:{0x1b,0x1b,0x1b,0x

我目前正在
STM32F0
上实现智能电表的SML读卡器。 一切正常,但我在使用
string.h
中的
strstr
时遇到问题

当前情况:

我有一个字符数组数据,它包含通过USART传入的所有数据。它包含十六进制数和有效的文本字符串

在这个字符串的某个地方有这样一个序列:
{0x01,0x01,0x62,0x1b,0x52,0x00,0x55}

我想使用
strstrstr
查找此子字符串在数据字符串中的位置

它可以很好地处理这个示例字符串,它总是位于数据字符串的最开头:
{0x1b,0x1b,0x1b,0x1b,0x01,0x01,0x01,0x01,0x76,0x05}

但是如果我使用另一个子字符串,它就不起作用了

这是我的密码:

const char needle[] = {0x01,0x01,0x62,0x1b,0x52,0x00,0x55};
    if((needle_ptr = strstr(Data,needle)) == NULL){
        //No Active Power String detected
        flags &= ~NewPowervalue;    //Reset NewPowervalue flag
    }else{

        Powervalue = (needle_ptr[14]<<24) + (needle_ptr[15]<<16) + (needle_ptr[16]<<8) + (needle_ptr[17])/10000;
        //Extract and calculate Powervalue
        flags |= NewPowervalue;     //Set NewPowervalue flag
        Poweroutlets(&Powervalue);
        GPIOC->ODR ^= BLED;
    }
const char needle[]={0x01,0x01,0x62,0x1b,0x52,0x00,0x55};
如果((指针ptr=strstr(数据,指针))==NULL){
//未检测到活动电源串
标志&=~NewPowervalue;//重置NewPowervalue标志
}否则{

Powervalue=(针_ptr[14]当然它不工作,因为0x00是asciiz终止符,
strstr()
比较asciiz终止的字符串,所以它在0x00停止比较

您显示的另一个示例字符串有效,因为它不包含任何0x00s

所以,归根结底,您不希望比较字符串(因为字符串是在C中定义的),而是希望比较内存区域


因此,如果您的运行库中有
memmemmem()
函数,您就必须使用它,或者编写自己的函数,这应该不难。(找到
memmem()
的某些实现的源代码也不难)

可能是出现0x00字符的问题,strstr将其解释为字符串终止符。一般来说,将USART的数据视为字符串数据对我来说是愚蠢的。如果不能用可打印的ASCII字符(或使用的任何字符编码)表示所有数据,字符串就是“嘿,你好吗?”,您不应该使用字符串函数。如果您正在接收的数据中嵌入了字符串,如果您想对其使用字符串函数,请首先解析该字符串。在处理二进制数据时使用和朋友,或者编写您自己的解析函数。请注意,您是(un)幸运的是,0x1b…0x05“string”可以工作,因为您没有使用空字节(0x00)终止该字符串,
strstr()
读取超出数组边界。如果您使用的是
strstr()
或字符串处理函数,则必须确保您正在处理以空结尾的字符串。如(至少)所述答案之一是
memmem()
函数类似于
strstr()
,用于有限长度内存工作。然而,它不是POSIX函数(更不用说标准C了),但它可能比建议的更广泛(Linux、macOS、AIX等等)。有趣的是,
memmem()的macOS文档
notes:u此功能在5.0.9及5.0.9版本之前的Linux libc和2.1版本之前的GNU libc中被破坏。u用您认为合适的任何大小的盐处理它。它可能不会影响您。只是一个琐碎的想法…这个文本字符串不是从USART来的-您如何知道st在哪里art/end是指它是否可以包含任何字符值,包括NUL?非常感谢。使用memmem可以很好地工作!我没有在字符串末尾添加“\0”,因为如果没有它,它也可以工作。所以我不再只使用它