问题
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 printfs 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