In the book Head First C, fist edition, there is this progam:
#include <stdio.h>
#include <string.h>
char tracks[][80] = {
"I left my hearth 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;
}
However, when compiled and tested, you don't get the expected results. After breaking my head for a bit, I decided to look for the documentation for fgets, I discovered that the function reads up to an including a newline character, which is why no matter what I search for, I never get the expected result. However, in the book they say the program works when tested. Is this a book error, or am I missing something?
PS. the error can be easily fixed using scanf, which becomes obvious once you know why the program doesn't work as expected.
PS2. I remember C++ has some syntax to ignore the newline character. Does C have something similar?
I also encountered the error, but the newest version has corrected the error. In fact, the function 'char *fgets(char *s, int size, FILE *stream)
works like what you said. It only read up to size-1
. If it encounters a null character('\0'), it only add ('\0') to the buffer. So when we used the fuction find_track()
, we can't get anything because of search_for
has contained ('\0'). There are some solutions to handle it.
scanf("%79s", search_for)
. Attention, don't only use %s
because you wil encounter the same situation like fgets()
.scanf("%79[^\n]", search_for)
, it has some difference with the former one. The advantage that you can avoid the blank problem.PS: The first one, you can add a new fuction to avoid the blank problem. Like this:
void remove_tail_newline(search_for)
{ size_t len = strlen(str);
if(len > 0 &&str[len-1] =='\n') str[len -1] ='\0';
}
You're right; this is indeed an error in the book.
I recommend against using scanf
for user input. It is hard to use correctly, error detection is non-trivial (if it is possible at all), and error recovery is impossible.
All user input should be done by reading a line first, then analyzing it afterwards (e.g. using strtol
or sscanf
). Reading a line can be done with fgets
, but unfortunately there's no syntax or feature for ignoring the \n
.
What you can do instead is:
if (fgets(line, sizeof line, stdin)) {
line[strcspn(line, "\n")] = '\0'; // remove trailing '\n', if any
do_stuff_with(line);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With