The condition
while((c = getchar()) != 'Y' || (c = getchar()) != 'y')
will always be true. You probably mean:
while((c = getchar()) != 'Y' && (c = getchar()) != 'y')
Also, you are usually calling getchar 3 times per loop iteration. Since every call of getchar attempts to read exactly one character, calling getchar 3 times per loop iteration would only make sense on input lines which contain 3 characters (including the newline character).
Therefore, you should instead first call getchar once in order to determine whether this first character is valid input. If it appears valid, then you should call getchar a second time to also consume the newline character, but you should also verify that it is indeed the newline character.
If you determine that the input is invalid and you have not yet consumed the newline character, then you should consume and discard the remainder of the line as well as the newline character.
Another problem with your code is that your program will treat all input that is not Y or y as a "no", even if the user did not enter N or n. It would probably be more appropriate to reprompt the user for input if the user did not answer the question properly.
Also, the function getchar returns an int, not a char. So you should generally not store it in a char. Otherwise, if getchar returns the value EOF, you may have trouble distinguishing this value from an actual character value. See this answer of mine to another question for further information.
After doing all of the above, and making a few other minor changes, your code should look like this:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main( void )
{
const char *prompt = "Is your number %d? ";
int guess = 1;
printf( "The program guesses the number between 1 and 100.\n" );
printf( "Respond with Y if the guess is correct and N if the guess is wrong.\n" );
// repeat until user answers "no"
for (;;)
{
int c1, c2;
// print guess and prompt for input
printf( prompt, guess );
// read first character of the input line
c1 = getchar();
if ( c1 == EOF )
{
printf( "Input error!\n" );
exit( EXIT_FAILURE );
}
// verify that input line is not empty
if ( c1 == '\n' )
{
printf( "Invalid input: Please enter a charater!\n" );
continue;
}
// read second character of the input line
c2 = getchar();
if ( c2 == EOF )
{
printf( "Input error!\n" );
exit( EXIT_FAILURE );
}
// verify that the second character is the newline character
if ( c2 != '\n' )
{
printf( "Please enter only a single character of input!\n" );
// discard remainder of the input line
while ( (c1=getchar()) != EOF && c1 != '\n' )
;
continue;
}
// test whether guess was correct
if ( c1 == 'Y' || c1 == 'y' )
{
break;
}
// test whether guess was incorrect
if ( c1 == 'N' || c1 == 'n' )
{
// guess a different number in the next loop iteration
guess++;
// change prompt for next loop iteration
prompt = "Well, is it %d then? ";
continue;
}
// if we reach this line, then the input character
// was invalid
printf( "Input invalid: Invalid character!\n" );
}
// gloat to user
printf( "I knew it was %d!\n", guess );
return EXIT_SUCCESS;
}
This program has the following behavior:
The program guesses the number between 1 and 100.
Respond with Y if the guess is correct and N if the guess is wrong.
Is your number 1?
Invalid input: Please enter a charater!
Is your number 1? sdfhkih
Please enter only a single character of input!
Is your number 1? q
Input invalid: Invalid character!
Is your number 1? n
Well, is it 2 then? y
I knew it was 2!
However, when dealing with line-based user input, it is generally advisable not to call the input functions of the C standard library (such as getchar) directly, but rather to use your own function which always reads exactly one line of user input at once. An example of such a function is my function get_line_from_user from this answer of mine to another Stack Overflow question. In your case, I would recommend wrapping (a slightly modified version of) this function in a function present_guess_to_user, which always reads an entire line of user input at once, but returns the bool value true if the user ansered "yes", and returns the value false if the user answered "no". If the user did not provide a valid answer, the function should automatically reprompt the user for input. Using this function makes your code in the function main a lot cleaner and easier to understand:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdarg.h>
bool present_guess_to_user( const char *question, int guess );
void get_line_from_user( const char *prompt, char *buffer, int buffer_size, ... );
int main( void )
{
const char *question = "Is your number %d? ";
int guess = 1;
printf( "The program guesses the number between 1 and 100.\n" );
printf( "Respond with Y if the guess is correct and N if the guess is wrong.\n" );
// repeat until user answers "yes"
while ( ! present_guess_to_user( question, guess ) )
{
// guess a different number in the next loop iteration
guess++;
// change question for next loop iteration
question = "Well, is it %d then? ";
}
// gloat to user
printf( "I knew it was %d!\n", guess );
return EXIT_SUCCESS;
}
// This function will present the guess to the user and if
// the user responds with
// - Y/y, then it will return true,
// - n/n, then it will return false.
// Otherwise, the input is invalid and the function will
// automatically reprompt the user.
bool present_guess_to_user( const char *question, int guess )
{
// repeat until input is valid
for (;;)
{
char line[1024];
// get one line of input from user
get_line_from_user( question, line, sizeof line, guess );
// verify that user entered exactly one character
if ( line[0] == '\0' || line[1] != '\0' )
{
printf( "Input invalid: Please enter a single character.\n" );
continue;
}
// test whether guess was correct
if ( line[0] == 'Y' || line[0] == 'y' )
{
return true;
}
// test whether guess was incorrect
if ( line[0] == 'N' || line[0] == 'n' )
{
return false;
}
// if we reach this line, then the character was invalid
printf( "Input invalid: Invalid character!\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)
{
va_list vl;
char *p;
// prompt user for input
va_start( vl, buffer_size );
vprintf( prompt, vl );
va_end( vl );
// explicitly flushing the output stream
// may be necessary on some platforms
fflush( 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 code has very similar behavior as the previous version of my code.
getchar(). Please try those changes and describe the changes to behaviour.(c = getchar()) != 'Y' || (c = getchar()) != 'y'will read another character if you entered'y'.while((c = getchar()) != 'Y' && c != 'y') {, which continues looping whilecis not equal to'y'AND not equal to'Y', and thegetchar()function is only called once, so that only 1 character typed by the user is read.getchar()in programs that communicate with the user. Users type lines of input. Read lines, one at a time. Process a line before you read the next one.fgets()is your friend.