我正在使用较小的代码来测试较大(初学者)程序的功能,但是我在显示已从字符串中拉出的令牌时遇到问题。
我找到并使用了:
#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("%i\n",found);
我得到一些随机性,但总是正确的金额,例如如果我输入1/2/3
我得到三行垃圾,输入1111/2222
会得到两行。我尝试了%c,%i,%d,%p,它们都做了同样的事情,但%s seg故障。
我完全被难倒了。
答案 0 :(得分:3)
段错是因为你错过了while
周围的大括号。您将继续打印“测试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);
^~~~~~
在while
周围添加大括号,程序按预期工作:
./sep
Enter string: abc/def
Original string: 'abc/def'
Test 1abc
Test 1def
答案 1 :(得分:2)
这是问题所在:
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的链接 显示更正的版本以段错结束。
我在ideone.com上尝试了相同的代码,我也得到了段错误。那似乎
对我来说很奇怪,所以我打开了strsep
的手册页,发现了这个:
man 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);
}
请参阅: