【发布时间】:2018-01-15 00:52:22
【问题描述】:
我目前正在STM32F0 上为智能电表实施 SML 阅读器。
一切正常,但我在使用来自string.h 的strstr 时遇到问题
现状:
我有一个 char 数组数据,其中包含通过 USART 传入的所有数据。它包含十六进制数和一个有效的文本字符串。
在这个字符串的某个地方有这个序列:
{0x01,0x01,0x62,0x1b,0x52,0x00,0x55}.
我想使用strstr 查找此子字符串在数据字符串中的位置。
它适用于这个示例字符串,它始终位于数据字符串的开头:{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;
}
有人知道我做错了什么吗?
【问题讨论】:
-
可能是 0x00 字符的出现是问题所在,strstr 将其解释为字符串终止符。
-
一般来说,将这些来自 USART 的数据视为字符串数据对我来说似乎很愚蠢。一个字符串是“嘿,你好吗?”如果您不能用可打印的 ASCII 字符(或您使用的任何字符编码)表示所有数据,则不应使用字符串函数。如果您接收的数据中嵌入了字符串,如果您想在其上使用字符串函数,请先将其解析出来。处理二进制数据时使用
memcpy和朋友,或者编写自己的解析函数。 -
请注意,您很幸运 0x1b…0x05 'string' 有效,因为您没有用空字节 (0x00) 终止该字符串,并且
strstr()读取超出了范围大批。如果您使用strstr()或字符串处理函数,则必须确保处理的是以空值结尾的字符串。正如(至少)其中一个答案所指出的那样,memmem()函数类似于strstr()用于有限长度的内存工作。然而,它不是一个 POSIX 函数(更不用说标准 C),但它可能比所建议的更广泛可用(Linux、macOS、AIX ……拥有它)。 -
有趣的是,
memmem()的 macOS 文档指出:_ 这个函数在 Linux libc 中被破坏,包括 5.0.9 版和 GNU libc 2.1 版之前。_ 用任何大小处理它一小撮你认为合适的盐。反正它可能不会影响你。 -
只是一个琐碎的想法......这个来自 USART 的文本字符串 - 如果它可以包含任何 char 值,包括 NUL,你怎么知道开始/结束在哪里?跨度>