来自`strsep`的字符串标记不打印(seg fault)

我正在使用较小的代码来测试较大(初学者)程序的function,但是我在显示我从字符串中拉出的令牌时遇到了问题。

我找到并使用了:

#include  #include  int main() { char *string, *found; string = strdup ("1/2/3"); printf("Original string: '%s'\n",string); while ((found = strsep(&string,"/")) != NULL ) printf ("%s\n",found); return (0); } 

这工作正常,一次打印一个令牌作为字符串。

然后当我尝试移动到用户输入的字符串时:

 #include  #include  int main() { char string[13]; char *found, *cp = string; fprintf(stderr, "\nEnter string: "); scanf("%12s",string); printf("Original string: '%s'\n",string); while((found = strsep(&cp,"/,-")) != NULL ) printf("Test 1"); /*To pinpoint where the seg fault arises*/ printf("%s\n",found); return(0); } 

我在printf("%s\n",found);上遇到了一个seg错误printf("%s\n",found); 线。 我正在掌握指针,数组和字符串的基础知识,但显然我错过了一些东西,并希望有人告诉我它是什么!

另外 – 如果我更改printf("%s\n",found);的参数printf("%s\n",found); 例如对printf("%i\n",found); 我得到一些随机性返回,但总是正确的数量,例如,如果我输入1/2/3我得到三行垃圾,输入1111/2222得到两行。 我尝试了%c,%i,%d,%p,它们都做同样的事情,但%s seg故障。

我完全难过了。

段错误是因为你在你身边丢失了大括号。 您将继续打印“测试1”,直到strsep返回NULL ,然后您尝试打印该结果(和段错误)。

有几个警告标志(可能是-Wall ),gcc帮助这里:

 sep.c:13:3: warning: this 'while' clause does not guard... [-Wmisleading-indentation] while((found = strsep(&cp,"/,-")) != NULL ) ^~~~~ sep.c:15:5: note: ...this statement, but the latter is misleadingly indented as if it is guarded by the 'while' printf("%s\n",found); ^~~~~~ 

随着大括号的添加,程序按预期工作:

 ./sep Enter string: abc/def Original string: 'abc/def' Test 1abc Test 1def 

这就是问题:

 while((found = strsep(&cp,"/,-")) != NULL ) printf("Test 1"); /*To pinpoint where the seg fault arises*/ printf("%s\n",found); 

并且你认为你在循环中做了两个printf ,但实际上这个代码相当于

 while((found = strsep(&cp,"/,-")) != NULL ) { printf("Test 1"); /*To pinpoint where the seg fault arises*/ } printf("%s\n",found); 

这意味着, printf("%s\n",found); 基本上是做printf("%s\n",NULL); 这是未定义的行为,可能会导致段错误。

请注意,在C缩进中对编译器无关紧要。 所以你需要在代码周围使用{}

 while((found = strsep(&cp,"/,-")) != NULL ) { printf("Test 1"); /*To pinpoint where the seg fault arises*/ printf("%s\n",found); } 

这样做我得到了

 $ ./a Enter string: aa/bb/cc/dd Original string: 'aa/bb/cc/dd' Test 1aa Test 1bb Test 1cc Test 1dd 

另请注意,您的第一个代码是泄漏内存,您没有释放strdup返回的已分配内存。 你必须保存一个指针:

 #include  #include  // for the free function #include  int main() { char *orig = *string, *found; orig = string = strdup ("1/2/3"); printf("Original string: '%s'\n",string); while ((found = strsep(&string,"/")) != NULL ) printf ("%s\n",found); free(orig); return 0; } 

编辑

斯蒂芬纽厄尔和我似乎都没有与更正版本的代码有相同的问题。 OP提供了一个指向onlinegdb.com的链接,显示更正的版本以段错结束。

我在ideone.com上尝试了相同的代码,我也得到了段错误。 这对我来说似乎很奇怪,所以我打开了我的strsep ,发现了这个:

男子strsep

概要

  #include  char *strsep(char **stringp, const char *delim); 

glibc的function测试宏要求(参见feature_test_macros(7)):

strsep()

 Since glibc 2.19: _DEFAULT_SOURCE Glibc 2.19 and earlier: _BSD_SOURCE 

这里重要的部分是: 自glibc 2.19: _DEFAULT_SOURCE

所以,如果你添加

 #define _DEFAULT_SOURCE 

在包含任何标准C头文件之前,它可以在onlinegdb.com和ideone.com上运行。

所以代码应该是:

 #define _DEFAULT_SOURCE // <-- important #include  #include  int main() { char string[13]; char *found, *cp = string; fprintf(stderr, "\nEnter string: "); scanf("%12s",string); printf("Original string: '%s'\n",string); while((found = strsep(&cp,"/,-")) != NULL ) { printf("Test 1"); /*To pinpoint where the seg fault arises*/ printf("%s\n",found); } return(0); } 

看到:

  • 更正了onlinegdb.com版本
  • 更正了ideone.com版本