Slthiess
Slthiess

Reputation: 1

Strstr Returning NULL

I am running into problems trying to use strstr with the following code. Can anyone point out to me why strstr on line 108 (documented in printf() statement) is returning NULL? I used a file as my command line argument (containing three words separated by \n and null terminated), and then used another file as stdin.

For example:

./stream_search word_list.txt < paragraph.txt

Goal: to print out all lines in paragraph.txt that contain the words in word_list.txt

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define INPUTSIZE 1000
#define LINESIZE 100

/*
    Read one line of a given file f into the array buffer.
 */
char* read_line(FILE* f, char buffer[LINESIZE]) {
    //reads line until n-1 char read, \n read, \o read, or EOF reached
    fgets(buffer, LINESIZE-1, f);
    printf("line 38: read line: %s\n", buffer);
    return buffer;
}

/*
   Prints the string in array buff.
*/
void print_buff(char buff[LINESIZE]) {
   printf("print_buff: %s\n", buff);
}

/* 
    Read lines from standard input and store in array p.
*/
char* get_input(char p[INPUTSIZE]) {
    fgets(p, INPUTSIZE-1, stdin);
    printf("line 76: %s\n", p);
    return p;
}

int main(int argc, char* argv[]) {

   char words[LINESIZE];
   char user_input[INPUTSIZE];

   /*
    * Prints error if program was called with 
    * no command line arguments,
    * or with more than one argument.
    */
    if(argc != 2) {
        fprintf(stderr, "Usage: ./stream_search <word list file> \n");
        return 0;
    }

    //assume argv[1] is a filename to open
    FILE* file = fopen (argv[1], "r");

    //Print error if file cannot be opened
    if (file == NULL) {
        fprintf(stderr, "Unable to open word list \n");
        return 0;
    }

    read_line(file, words); //get input from file  
    get_input(user_input); //get input from stdin

    printf("line 98: %s", words);
    printf("line 101: %s", user_input);

    char* a = "hello";
    char* b = "hel";

    printf("line 103: %s\n", strstr(a, b));
    printf("line 108: %s\n", strstr(words, user_input));

    fclose(file);
    return 0;
}

Upvotes: 0

Views: 1673

Answers (1)

Jonathan Leffler
Jonathan Leffler

Reputation: 755064

You have two problems in the code, either of which would prevent it from working as intended.

  1. You don't remove the newline from the end of the word to be searched for (or the 'user input'), so the word would only be found if it appeared at the end of the input.
  2. You call the function strstr() with the arguments in the wrong order. The call needs to be needs to be in the order strstr(haystack, needle), not in the order strstr(needle, haystack) which is used in the code. In other words, the call needs to be strstr(user_input, words) not strstr(words, user_input).

You have a function print_buff() that's not used. You have two very similar functions that could be combined into one quite easily by passing the file stream and buffer size as arguments. This would also give you one place to remove the newline. Note that if the array is char buffer[BUFLEN];, it is perfectly safe and sane to use fgets(buffer, BUFLEN, fp) (and usually better to use fgets(buffer, sizeof(buffer), fp)), specifying the full size of the array.

Putting these changes together yields:

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

#define INPUTSIZE 1000
#define LINESIZE 100

static void read_line(FILE *f, size_t bufsiz, char buffer[])
{
    fgets(buffer, bufsiz, f);
    buffer[strcspn(buffer, "\n")] = '\0';
}

int main(int argc, char *argv[])
{
    char words[LINESIZE];
    char user_input[INPUTSIZE];

    if (argc != 2)
    {
        fprintf(stderr, "Usage: ./stream_search <word list file> \n");
        return 0;
    }

    FILE *file = fopen(argv[1], "r");

    if (file == NULL)
    {
        fprintf(stderr, "Unable to open word list \n");
        return 0;
    }

    read_line(file, sizeof(words), words);
    read_line(stdin, sizeof(user_input), user_input);

    printf("line 98: %s\n", words);
    printf("line 101: %s\n", user_input);
    printf("line 108: %s\n", strstr(words, user_input));
    printf("line 109: %s\n", strstr(user_input, words));

    fclose(file);
    return 0;
}

Be aware that not all implementations of printf() handle null pointers gracefully; they are entitled to crash instead, and IMO it is better if they do. However, I didn't fix that in this code — (un)fortunately, the system I'm using has a printf() that prints (null) instead of crashing when given a null pointer to print as a string.

Given a file words containing the line hel and the file data containing hello world, and calling the program wm13, I get the sample output:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
      -Wold-style-definition -Werror wm13.c -o wm13
$ ./wm13 words < data
line 98: hel
line 101: hello world
line 108: (null)
line 109: hello world
$

Upvotes: 1

Related Questions