Using scanf
with the %s
format specifier will only read a single word. If you want to read an entire line consisting of several words (e.g. "Linus Torvalds\n"
), then I suggest that you use fgets
instead. However, beware of this problem regarding mixing fgets
and scanf
. Also, see this question on how to remove the newline character from the fgets
input. I suggest that you don't use scanf
at all for user input, but instead always use fgets
.
The condition if("Linus Torvalds\n")
does not make sense, as that condition will always be true. If you want to compare the content of name
with "Linus Torvalds\n"
, then you need to use the strcmp
function.
Also, the line
if (strcmp("n", yesno)){
is wrong, because the function strcmp
requires both of its arguments to be a pointer that each point to a string, i.e. to a sequence of characters terminated by a null character. However, yesno
is not a pointer. &yesno
would also be wrong, because such a pointer would only point to a single character, not to a sequence of characters terminated by a null character.
The function strcmp
will return zero if the two strings match, and non-zero if they don't. Therefore, you probably want to compare the return value of strcmp
with zero.
I suggest that you rewrite your program like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void get_line_from_user( const char prompt[], char buffer[], int buffer_size );
int main( void )
{
char input[200];
get_line_from_user(
"Hello adventurer, are you here to learn Linux? (y/n) ",
input, sizeof input
);
if ( strcmp( input, "y" ) == 0 )
{
get_line_from_user(
"Great! What is your name? ",
input, sizeof input
);
if ( strcmp( input, "Linus Torvalds" ) == 0 )
{
printf( "Achievement complete: In God We Trust\n" );
printf( "Nice to meet you! My name is Richard Stallman.\n" );
}
else
{
printf( "Nice to meet you! My name is Linus Torvalds.\n" );
}
}
else if ( strcmp( input, "n" ) == 0 )
{
printf( "Ok! Bye!" );
}
else
{
printf( "That's not an answer.\n" );
}
}
//This function will read exactly one line of input from the
//user. It will remove the newline character, if it exists. If
//the line is too long to fit in the buffer, then the function
//will automatically reprompt the user for input. On failure,
//the function will never return, but will print an error
//message and call "exit" instead.
void get_line_from_user( const char prompt[], char buffer[], int buffer_size )
{
for (;;) //infinite loop, equivalent to while(1)
{
char *p;
//prompt user for input
fputs( prompt, stdout );
//attempt to read one line of input
if ( fgets( buffer, buffer_size, stdin ) == NULL )
{
printf( "Error reading from input!\n" );
exit( EXIT_FAILURE );
}
//attempt to find newline character
p = strchr( buffer, '\n' );
//make sure that entire line was read in (i.e. that
//the buffer was not too small to store the entire line)
if ( p == NULL )
{
int c;
//a missing newline character is ok if the next
//character is a newline character or if we have
//reached end-of-file (for example if the input is
//being piped from a file or if the user enters
//end-of-file in the terminal itself)
if ( (c=getchar()) != '\n' && !feof(stdin) )
{
if ( c == EOF )
{
printf( "Error reading from input!\n" );
exit( EXIT_FAILURE );
}
printf( "Input was too long to fit in buffer!\n" );
//discard remainder of line
do
{
c = getchar();
if ( c == EOF )
{
//this error message will be printed if either
//a stream error or an unexpected end-of-file
//is encountered
printf( "Error reading from input!\n" );
exit( EXIT_FAILURE );
}
} while ( c != '\n' );
//reprompt user for input by restarting loop
continue;
}
}
else
{
//remove newline character by overwriting it with
//null character
*p = '\0';
}
//input was ok, so break out of loop
break;
}
}
This program has the following behavior:
Hello adventurer, are you here to learn Linux? (y/n) y
Great! What is your name? Jimmy
Nice to meet you! My name is Linus Torvalds.
Hello adventurer, are you here to learn Linux? (y/n) y
Great! What is your name? Linus Torvalds
Achievement complete: In God We Trust
Nice to meet you! My name is Richard Stallman.
Hello adventurer, are you here to learn Linux? (y/n) n
Ok! Bye!
Hello adventurer, are you here to learn Linux? (y/n) sdfsdgf
That's not an answer.