[英]String token from `strsep` not printing (seg fault)
我正在使用一小段代码来测试较大(初学者)程序的功能,但是在显示从字符串中拔出的令牌时遇到问题。
我发现并使用了:
#include <stdio.h>
#include <string.h>
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 <stdio.h>
#include <string.h>
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);
上遇到段错误printf("%s\\n",found);
线。 我掌握了指针,数组和字符串的基础知识,但显然我缺少了一些东西,希望有人告诉我它是什么!
另外-如果我更改了printf("%s\\n",found);
例如到printf("%i\\n",found);
我得到一些随机性,但总是正确的数量,例如,如果我输入1/2/3
我将得到三行垃圾,输入1111/2222
将得到两行。 我尝试了%c,%i,%d,%p,它们都执行相同的操作,但是出现了%s seg错误。
我完全迷住了。
出现段错误的原因是您while
缺少括号。 您将继续打印“ Test 1”,直到strsep
返回NULL
,然后尝试打印该结果(和segfault)。
使用几个警告标志(可能是-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);
^~~~~~
在while
周围添加大括号,该程序将按预期工作:
./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 <stdio.h>
#include <stdlib.h> // for the free function
#include <string.h>
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;
}
编辑
Stephen Newell和我似乎都没有对纠正后的代码版本有相同的问题。 OP提供了一个指向onlinegdb.com的链接,该链接显示已更正的版本以segfault结尾。
我在ideone.com上尝试了相同的代码,并且也遇到了段错误。 这对我来说似乎很奇怪,因此我打开了strsep
手册页并发现了这一点:
曼斯特雷普
概要
#include <string.h> char *strsep(char **stringp, const char *delim);
glibc的功能测试宏要求(请参阅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 <stdio.h>
#include <string.h>
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);
}
看到:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.