Reputation: 33
First post here. I've been trying to write a very simple Knock Knock joke. It goes as follows:
Knock! Knock!
[user input]
Banana!
[user input]
Knock! Knock!
[user input]
Banana!
[user input]
... So on and so forth. It's a never ending joke. My problem comes from the scanf statements inside the while loop. If I type in 'a' for the first input nothing happens. If I then type ' a' (space in front), it comes up with Banana! If I type in 'a' for Banana!, it will continue the joke correctly.
However, if I type in "whos there" for the Knock! Knock! prompt it will go on to Banana! correctly; however, if I type in "banana who" for the Banana! prompt, if ends up saying "Knock! Knock!" and immediately "Banana!" not allowing input for the "Knock! Knock!" prompt the second time through the loop.
Here's a picture of those inputs: Picture
Am I missing something? I've tried adding getchar() statements. I've tried fflush(stdin). I've tried making the scanf a funtion and even adding a getchar() to that function. I've changed scanf("%s") to scanf("%s\n"), that helped but still doesn't function properly. It appears as though the second scanf is trying to take the whitespace as a terminating character and continue from there, but I am at a loss. I just want to make a simple never ending Knock Knock joke.
Am I just an idiot? What am I doing wrong?
Here's the code.
#include <stdio.h>
int main(void)
{
while(1)
{
//Begin Joke
printf("Knock! Knock!\n");
scanf(" %s\n"); //Who's there?
//Second Part of Joke
printf("Banana!\n");
scanf(" %s\n"); //Banana who?
}
}
~Knob
Upvotes: 0
Views: 685
Reputation: 153338
2 main problems: No place to save input and "\n"
after "%s"
.
Use fgets()
instead.
Let us tear scanf(" %s\n");
apart:
A. The " "
directs scanf()
to read and consume optional white-space (tabs, space, '\n'
, etc.). This continues until non-white-space is found. That char
is put back into stdin
.
B. "%s"
directs scanf()
to 1) read and consume optional white-space 2) read and save endless amounts of non-white-space in to oops a missing character array. 3) Upon encountering a white-space, put that char
back into stdin
, append a null character to oops a missing character array.
C. The "\n"
directs scanf()
to read and consume optional white-space (tabs, space, '\n'
, etc.). This continues until non-white-space is found. That char
is put back into stdin
. (Just like step A.)
So 1) we have undefined behavior because there is no character array to save data. 2) Even with a character array like below, scanf()
does not return until non-white-space is entered (see step C.) after the the first run of non-white-space. Since stdin
is line buffered, keyboard input occurs a line at a time. That 2nd word will not be seen by the first scanf()
until 2 lines are entered.
char buf[100];
scanf(" %s\n", buf); // better, but still not so good
If anything code could have been the below, but even that has issues as it does not consume a line of input.
char buf[100];
if (scanf("%99s", buf) != 1) Handle_Error(); // better
Instead use fgets()
char buf[100];
if (fgets(buf, sizeof buf, stdin) == NULL) Handle_Error(); // best
// lop off potential trailing \n if desired
buf[strcspn(buf, "\n")] = '\0';
Upvotes: 1
Reputation: 1025
From cplusplus.com:
The additional arguments should point to already allocated objects of the type specified by their corresponding format specifier within the format string.
So provide it with an argument:
while (1)
{
char buffer[255];
//Begin Joke
printf("Knock! Knock!\n");
scanf(" %s\n", buffer); //Who's there?
//Second Part of Joke
printf("Banana!\n");
scanf(" %s\n", buffer); //Banana who?
}
Please note:
This function is unsafe and like already mentioned may break. Again consider using fgets
.
Upvotes: -2
Reputation: 3459
%s
is not a good idea if you want to read entire lines; it'll normally break on any whitespace character. Some dirty hacks exist to circumvent this, but I suggest you just use fgets
instead:
#include <stdio.h>
#define MAX_LINE_LEN 200
int main(void)
{
char buf[MAX_LINE_LEN];
while (1)
{
//Begin Joke
printf("Knock! Knock!\n");
fgets(buf, sizeof(buf), stdin); //Who's there?
//Second Part of Joke
printf("Banana!\n");
fgets(buf, sizeof(buf), stdin); //Banana who?
}
}
Output:
Note that what you were doing in your code (scanf(" %s\n");
) is undefined behavior - %s
requires a valid char
buffer (of sufficient length!), but you were providing none. In general scanf
is best avoided due to its poor error handling capabilities.
Upvotes: 4