首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >带有多个分隔符的Strsep :奇怪的结果

带有多个分隔符的Strsep :奇怪的结果
EN

Stack Overflow用户
提问于 2021-05-12 02:20:04
回答 3查看 164关注 0票数 1

我目前在使用带有多个分隔符的strsep时有一些奇怪的结果。我的分隔符包括制表符、空格字符以及><

代码语言:javascript
复制
#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);
}

这是我所期望的输出。

代码语言:javascript
复制
echo 
Hello

但是,只要我为分隔符添加'<‘字符,我就会得到

代码语言:javascript
复制
cho

不知何故,第一个字符被截断了。为什么会发生这种情况,有什么原因吗?

谢谢。

EN

回答 3

Stack Overflow用户

发布于 2021-05-12 02:29:54

strsep的第二个参数delim是一个以null结尾的字符串(与C中的所有字符串一样),因此必须为结尾字符留出空格:

代码语言:javascript
复制
const char delim[5] = "\t ><"; // This does work
//const char delim[] = "\t ><"; // or this

如果您没有结束字符串,它将通过数组探索内存,并找到许多新的分隔字符来使用,这就是在您的示例中发生的情况。

票数 2
EN

Stack Overflow用户

发布于 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

代码语言:javascript
复制
const char delim[4];

有4个字符的空间。

代码语言:javascript
复制
"\t ><"  //contains exactly 4 char

在内存中可以像这样概念化:

代码语言:javascript
复制
|\t| |>|<|?|?|?|  // ? = unknown content, possibly no null termination
         ^end of owned memory

它应该包含以下内容:

代码语言:javascript
复制
|\t| |>|<|\0|?|?|  // null termination  
            ^end of owned memory (5 char wide)

在声明中需要更多空间,例如以下两个选项之一:

代码语言:javascript
复制
const char delim[5] = "\t ><";

代码语言:javascript
复制
const char delim[] = "\t ><";
票数 0
EN

Stack Overflow用户

发布于 2021-05-12 02:57:58

const char delim[4] = "\t ><";没有定义正确的C字符串,因为空终止符没有空格。因此,内存中delim后面的任何非零字节都将是分隔符字符串的一部分。

这当然是未定义的行为,在您的例子中,编译器可以将delim放在buffer之前,而不需要任何填充,有效地将分隔符字符序列与字符串"echo Hello"中的所有字符继续。这会导致第一次调用strsep时返回空字符串。

您可以在此Godbolt instance上检查在32位模式下确实是这样,但在64位模式下不是这样(删除-m32编译器选项)。

这个问题很容易解决。您可以让编译器确定delim数组的长度:

代码语言:javascript
复制
const char delim[] = "\t ><";

也可以使用指向字符串常量的指针:

代码语言:javascript
复制
const char *delim = "\t ><";
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67492332

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档