0

I am learning C from the book Head First C, and I tried one of the examples, and despite having the same code, my code won't run like the example in the book. The code aims to use the strstr() function to find a string within another string, but after running my code, it only asks for my input, and displays "Program ended with exit code: 0"

Below is my code:

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

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",
};

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

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

The result after running the code is:

Search for: (my input)
Program ended with exit code: 0

Help!

melpomene
  • 84,125
  • 8
  • 85
  • 148

3 Answers3

2

If your input was entered with a newline, fgets() includes the newline in the resulting search_for string. On the other hand, if you terminate your input with EOF (usually ctrl+D) then it doesn't contain the newline, and your program works as intended.

You can find techniques for avoiding this issue in this question and its answers.

jtbandes
  • 115,675
  • 35
  • 233
  • 266
2

That code is wrong; fgets reads a full line, leaving the newline character in the target buffer (unless you provided exactly 79 characters). For that reason, find_track will look for a string with a terminating newline, which of course cannot be found.

A possible fix can be to remove the last character from the input string, just after the fgets.

if(*search_for) search_for[strlen(search_for) -1] = 0;

or to use a different input function, which does not read the newline.

Matteo Italia
  • 123,740
  • 17
  • 206
  • 299
  • Could you help me understand your code? I don't understand what its function does (I'm having trouble converting that code into spoken English) – QuantumDust Jun 05 '17 at 05:48
  • `if(*search_for)` is a compact way to say `if(search_for[0]!=0)`, which is a way to check if the string is at least one character long (if a string is zero-length the first character must be the NUL terminator). `search_for[strlen(search_for -1] = 0;` replaces the last character of the string with the NUL terminator, thus dropping the last character (in your case, the stray newline from the string). – Matteo Italia Jun 05 '17 at 05:54
  • Thank you! Very comprehensive – QuantumDust Jun 05 '17 at 06:04
  • This doesn't quite work because `fgets` doesn't *always* produce a newline; only if there was one in the input. If the input was simply `abc[EOF]`, then this searches too generously for `ab`. – jtbandes Jun 05 '17 at 06:12
  • @jtbandes: that's a tradeoff between simplicity and comprehensiveness. The use case here is interactive console usage, where it's virtually impossible to produce an EOF without a newline first. Even in text files (if you were to redirect input) it's expected that the last line of the file contains a newline on itself (and virtually any editor enforces this). The other possibility to read a line without a newline is if it is exactly 79 characters long, but I just moved the problem one character before, so it's not a big deal. Still, if these scenarios are important the fix is trivial. – Matteo Italia Jun 05 '17 at 06:30
0

search_for[strlen(search_for)-1] = 0; fgets(search_for, 80, stdin);

fgets() adds a newline

Sriram
  • 78
  • 1
  • 2
  • 10
  • 3
    Corner concern: Without testing `search_for[0] != 0`, `search_for[strlen(search_for)-1]` is an exploitable hack should the first character read be a _null character_. – chux - Reinstate Monica Jun 05 '17 at 05:33