Anonymous
Anonymous

Reputation: 75

strstr function and multi dimensional arrays in c

#include <stdio.h>
#include <string.h>

void find_track(char *search_for);
char tracks[][80] = {
    "I left my heart in Harvard Med School",
    "Newark, Newark - a wonderful town",
    "Dancing with a Dork",
    "From here to maternity",
    "The girl from Iwo Jima"
};

int main() {
    char *to_search_str;
    printf("Search for: ");
    fgets(to_search_str, 80, stdin);
    find_track(to_search_str);
    return 0;
}

void find_track(char *search_for) {
    int i;
    for (i=0; i<5; i++) {
        if (strstr(tracks[i], search_for)) {
            printf("Track %d: '%s'\n", i, tracks[i]);
        }
    }
}

The program is supposed to search for a string in every string in the tracks multi dimensional array but the strstr() function in the find_track is always returning null no matter the input (even if we input the a sub string of a string from tracks multi dimensional array). I don't know why this is happening?

EDIT: After correction

#include <stdio.h>
#include <string.h>

void find_track(char *search_for);
char tracks[][80] = {
    "I left my heart in Harvard Med School",
    "Newark, Newark - a wonderful town",
    "Dancing with a Dork",
    "From here to maternity",
    "The girl from Iwo Jima"
};

int main() {
    char to_search_str[80];
    printf("Search for: ");
    fgets(to_search_str, 80, stdin);
    to_search_str[strlen(to_search_str)-1] = '\0';
    find_track(to_search_str);
    return 0;
}

void find_track(char *search_for) {
    int i;
    for (i=0; i<5; i++) {
        if (strstr(tracks[i], search_for)) {
            printf("Track %d: '%s'\n", i, tracks[i]);
        }
    }
}

Output enter image description here

Upvotes: 1

Views: 282

Answers (4)

Roberto Caboni
Roberto Caboni

Reputation: 7490

You aren't allocating to_search_str pointer, the char * pointer you pass to fgets as the destination buffer. Being it actually uninitialized, this causes undefined behavior that normally ends with a program crash.

You just need to allocate it, statically or dynamically.

The simplest solution consists in just defining a static array in the stack:

#include <string.h>

#define LEN 80

int main() {
    char to_search_str[LEN];

    printf("Search for: ");
    fgets(to_search_str, LEN, stdin);

    /* Remove trailing newline from the string to search */
    to_search_str[strcspn(to_search_str, "\n")] = 0;

    find_track(to_search_str);
    return 0;
}

The size of the array is 80 because you use this number as the size parameter in fgets. Please note the use of a #define for the constant 80, making possible to change it in a easier way.

The dynamic allocation in the heap involves the use of malloc() function (and free() as soon as the array is not needed anymore):

#include <string.h>

#define LEN 80

int main() {
    char * to_search_str = malloc(LEN);

    printf("Search for: ");
    fgets(to_search_str, LEN, stdin);

    /* Remove trailing newline from the string to search */
    to_search_str[strcspn(to_search_str, "\n")] = 0;

    find_track(to_search_str);

    free(to_search_str);
    return 0;
}

Note: since fgets retains trailing newline ``\n'` in the output buffer, we have to remove it. I used the clever oneliner solution described here.

Upvotes: 1

Vlad from Moscow
Vlad from Moscow

Reputation: 311146

This code snippet in main

char *to_search_str;
printf("Search for: ");
fgets(to_search_str, 80, stdin);

invokes undefined behavior because the pointer to_search_str is not initialized and has indeterminate value.

It seems you at least mean

char to_search_str[80];
printf("Search for: ");
fgets(to_search_str, 80, stdin);

The function fgets can append the new line character '\n' to the entered string.

You need to remove it for example the following way

to_search_str[ strcspn( to_search_str, "\n" ) ] = '\0';

The function find_track should be declared at least like

void find_track( const char *search_for);

Though it is a bad idea when a function definition relies on global variables.

Also the approach of finding relevant strings is not good. For example the user can enter a string that contains only one character 'a'. In this case all records will satisfy the condition. You should check that the searched string forms a word (a sequence of characters separated by spaces) in a string in the array.

Upvotes: 0

Sourav Ghosh
Sourav Ghosh

Reputation: 134396

Most likely the issue with input via fgets().

  • You are reading into an uninitialized pointer to_search_str, which does not point to a valid memory location. In this case, you can simply change this to an array, like char to_search_str[80] = {0}; and get done with it.

  • You need to trim the trailing newline that's stored in the input buffer.

    From the man page, (emphasis mine)

fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('\0') is stored after the last character in the buffer.

A quick way of getting that done is to_search_str[strcspn(to_search_str, "\n")] = 0;, but there are more robust ways mentioned in this other answer

Upvotes: 1

mch
mch

Reputation: 9814

char *to_search_str; is an uninitialized pointer, writing to it will result in undefined behavior. You have to allocate memory or use an array instead char to_search_str[100]; for example.

Also don't forget that fgets will also read the newline into the buffer, which you have to remove.

Upvotes: 0

Related Questions