问题
I'm using with a smaller piece of code to test functionality for a larger (beginner) program, but I have a problem displaying the token I've pulled out of a string.
I found and used:
#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);
}
and this works fine, prints the tokens one at a time as strings.
Then when I try and move to a user entered string:
#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);
}
I get a seg fault on the printf("%s\n",found);
line. I'm getting the hang of basics of pointers, arrays and strings, but clearly I'm missing something, and would love for someone to tell me what it is!
Also - if I change the argument of printf("%s\n",found);
e.g. to printf("%i\n",found);
I get some randomness returned, but always the correct amount, e.g. If I enter 1/2/3
I get three lines of junk, entering 1111/2222
gives two lines. I tried %c, %i, %d, %p and they all do the same, but %s seg faults.
I'm completely stumped.
回答1:
The segfault is because you're missing braces around your while
. You'll keep printing "Test 1" until strsep
returns NULL
, then you try to print that result (and segfault).
With several warning flags (probably -Wall
), gcc helps out here:
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);
^~~~~~
With braces added around the while
, the program works as expected:
./sep
Enter string: abc/def
Original string: 'abc/def'
Test 1abc
Test 1def
回答2:
This is the problem:
while((found = strsep(&cp,"/,-")) != NULL )
printf("Test 1"); /*To pinpoint where the seg fault arises*/
printf("%s\n",found);
and you think you are doing both printf
s inside the loop, but in reality this
code is equivalent to
while((found = strsep(&cp,"/,-")) != NULL )
{
printf("Test 1"); /*To pinpoint where the seg fault arises*/
}
printf("%s\n",found);
that means, printf("%s\n",found);
is basically doing printf("%s\n",NULL);
which is undefined behaviour and may cause a segfault.
Note that in C indentation does not matter to the compiler. So you would need to
use {
and }
around the code:
while((found = strsep(&cp,"/,-")) != NULL )
{
printf("Test 1"); /*To pinpoint where the seg fault arises*/
printf("%s\n",found);
}
Doing that I get
$ ./a
Enter string: aa/bb/cc/dd
Original string: 'aa/bb/cc/dd'
Test 1aa
Test 1bb
Test 1cc
Test 1dd
Also note that your first code is leaking memory, you are not freeing the
allocated memory returned by strdup
. You would have to save a pointer to that:
#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;
}
edit
Neither Stephen Newell nor me seems to have the same problem with the corrected version of the code. The OP provided a link to onlinegdb.com showing that the corrected version ends with a segfault.
I tried the same code on ideone.com and I also got the segfault. That seemed
strange to me, so I opened my man page of strsep
and found this:
man strsep
SYNOPSIS
#include <string.h> char *strsep(char **stringp, const char *delim);
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
strsep()
:Since glibc 2.19: _DEFAULT_SOURCE Glibc 2.19 and earlier: _BSD_SOURCE
The important part is this here: Since glibc 2.19: _DEFAULT_SOURCE
So if you add
#define _DEFAULT_SOURCE
before including any standard C header file, then it works on onlinegdb.com and ideone.com.
So the code should be:
#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);
}
See:
- corrected onlinegdb.com version
- corrected ideone.com version
来源:https://stackoverflow.com/questions/49394350/string-token-from-strsep-not-printing-seg-fault