来自`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版本