我目前在使用带有多个分隔符的strsep时有一些奇怪的结果。我的分隔符包括制表符、空格字符以及>和<。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
char buffer[50];
char *curr_str = NULL;
const char delim[4] = "\t >";
//const char delim[4] = "\t ><"; // This does not work
snprintf(buffer, 50, "%s", "echo Hello");
char *str_ptr = buffer;
curr_str = strsep(&str_ptr, delim);
if (curr_str != NULL)
printf("%s\n", curr_str);
curr_str = strsep(&str_ptr, delim);
if (curr_str != NULL)
printf("%s\n", curr_str);
return (0);
}这是我所期望的输出。
echo
Hello但是,只要我为分隔符添加'<‘字符,我就会得到
cho不知何故,第一个字符被截断了。为什么会发生这种情况,有什么原因吗?
谢谢。
发布于 2021-05-12 02:29:54
strsep的第二个参数delim是一个以null结尾的字符串(与C中的所有字符串一样),因此必须为结尾字符留出空格:
const char delim[5] = "\t ><"; // This does work
//const char delim[] = "\t ><"; // or this如果您没有结束字符串,它将通过数组探索内存,并找到许多新的分隔字符来使用,这就是在您的示例中发生的情况。
发布于 2021-05-12 02:38:21
"...the第一个字符被截断。发生这种情况有什么原因吗?“
是的,在C字符串函数中使用非空终止字符数组导致的未定义行为。
如果填充的const char delim[4]不包含空终止,则它将只是一个char数组,而不是C string。它可能会也可能不会表现出奇怪的行为,但如果与任何C string functions (如curr_str = strsep(&str_ptr,delim); )一起使用,它将调用undefined behavior。
const char delim[4];有4个字符的空间。
"\t ><" //contains exactly 4 char在内存中可以像这样概念化:
|\t| |>|<|?|?|?| // ? = unknown content, possibly no null termination
^end of owned memory它应该包含以下内容:
|\t| |>|<|\0|?|?| // null termination
^end of owned memory (5 char wide)在声明中需要更多空间,例如以下两个选项之一:
const char delim[5] = "\t ><";或
const char delim[] = "\t ><";发布于 2021-05-12 02:57:58
const char delim[4] = "\t ><";没有定义正确的C字符串,因为空终止符没有空格。因此,内存中delim后面的任何非零字节都将是分隔符字符串的一部分。
这当然是未定义的行为,在您的例子中,编译器可以将delim放在buffer之前,而不需要任何填充,有效地将分隔符字符序列与字符串"echo Hello"中的所有字符继续。这会导致第一次调用strsep时返回空字符串。
您可以在此Godbolt instance上检查在32位模式下确实是这样,但在64位模式下不是这样(删除-m32编译器选项)。
这个问题很容易解决。您可以让编译器确定delim数组的长度:
const char delim[] = "\t ><";也可以使用指向字符串常量的指针:
const char *delim = "\t ><";https://stackoverflow.com/questions/67492332
复制相似问题