Reputation: 31
i'm a beginner,tracks.c:
#include <stdio.h>
#include <string.h>
char tracks[][5] = {
"one",
"two",
"three",
"four",
"five",
"six",
};
void track_search(char search_for[]) {
int i;
puts(search_for);
puts(strstr(tracks[0], search_for));
/*
for (i = 0; i < 6; i++) {
if (strstr(tracks[i], search_for)) {
printf("tracks %i: %s\n", i,tracks[i]);
} else {
puts("Nothing found");
}
}
*/
}
int main() {
char search_for[5];
printf("enter your word: ");
fgets(search_for, 5, stdin);
track_search(search_for);
return 0;
}
$ gcc tracks.c && ./a.out
enter your word: on
on
Segmentation fault
but if I use puts(strstr(tracks[0], "on")); instead of puts(strstr(tracks[0], search_for)); it will works wine,anyone knows where is wrong?
Upvotes: 3
Views: 7461
Reputation: 66234
There are several things wrong with this.
First, your constant array is not declared correctly.
char tracks[][5] = {
"one",
"two",
"three",
"four",
"five",
"six",
};
This says "declare an array of arbitrary length of char[5]
. Stare at that array content very closely, and consider that the length of those strings is actually its character count plus one for the zero-terminator. Anything pop out at you? Perhaps the word "three"
? That would be 5+1, or six chars wide, not five.
Try this:
const char *tracks[] =
{
"one",
"two",
"three",
"four",
"five",
"six"
};
And also modify your for loop like so:
for (i = 0; i < sizeof(tracks)/sizeof(tracks[0]); ++i)
{
if (strstr(tracks[i], search_for))
printf("track[%d]: %s\n", i, tracks[i]);
}
Note: I pulled the redundant "Nothing found" from the loop for my own sanity.
Finally, the string fetched will likely have an end-of-line ('\n'
) tacked on to the end, and you should check and null it if so. I would significantly lengthen the size of your input buffer, then trim the endl out if it is there:
int main()
{
char search_for[64] = {0};
printf("enter your word: ");
if (fgets(search_for, sizeof(search_for), stdin))
{
size_t len = strlen(search_for);
if (len && search_for[len-1] == '\n')
search_for[len-1] = 0;
track_search(search_for);
}
else
{
perror("fgets failed.");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Upvotes: 3
Reputation: 3066
It's because fgets
reads a newline, so "on\n"
is not found in "one"
, thus strstr
returns NULL which causes segmentation fault if it's passed to puts
.
You probably want to remove newline and other whitespace first after reading the input, for example by setting first occurence of newline/space to 0, like
char *p;
if(p = strchr(search_for, '\n')) *p = 0;
if(p = strchr(search_for, ' ')) *p = 0;
(Also char[5]
is not enough for "three"
, because you need additional place for null terminator.)
Upvotes: 3
Reputation: 229158
There's 2 things you must consider:
If the words is not in the list, strstr() returns a NULL pointer and you can't pass that to puts(), so do e.g.
char *found = strstr(tracks[0], search_for);
if (found)
puts(found);
else
puts("The word '%s' was not found\n",search_for);
Once you do that you will realize that fgets also reads the newline you type. So if you input four and hit enter, you will search for "four\n" So you should erase that \n character, e.g. do
char *p;
if ((p = strrchr(search_for, '\n')) != NULL) {
*p = 0;
}
After you read the input with fgets.
Upvotes: 2