0

So I have a very simple code to ask the user if they agree or not (i'm just starting out). Currently I have the loop set up to allow the user to answer with 'y' or 'n', and to tell them "only y/n please" if they enter a different character. So far, everything works almost perfectly, however, upon entering a character other than 'y' or 'n', the correction message displays twice. any advice?

code:

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    char answer = get_char("Do You Agree? y/n \n"); // prompt user to answer question

    do{
        scanf("%c", &answer);

        if (answer == 'y')
        {
            printf("Great!\n");
            break;
        }
        else if(answer == 'n')
        {
            printf("That's unfortunate\n");
            break;
        }
        else
        {
            printf("only y/n please.\n"); // prompt user for acceptable character
        }
    }while (answer != 'y' || answer != 'n');
}

And here is what it returns:

Do You Agree? y/n 
a
a
only y/n please.
only y/n please.
a
only y/n please.
only y/n please.
a
only y/n please.
only y/n please.
s
only y/n please.
only y/n please.
y
Great!
Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
jaudiola
  • 1
  • 1
  • 2
    When the user enters 'y', they are (probably) typing a `y` followed by the enter key. Your program checks the key they enter, and then the newline. – William Pursell Jul 25 '22 at 22:01
  • just count: how many non-y/n keys do you press when answering "a"? – Stefan Paul Noack Jul 25 '22 at 22:02
  • I'm not sure what the canonical duplicate is, but one solution is to add whitespace in the format string and use `scanf(" %c");` – William Pursell Jul 25 '22 at 22:03
  • Note that you *must* check the value returned by `scanf`. If your input stream closes or if there is an error reading the input your program may be in an infinite loop continuously printing `only y/n please.\n` – William Pursell Jul 25 '22 at 22:04
  • 1
    Why are you doing `scanf()` after you already asked for the input with `get_char()`? – Barmar Jul 25 '22 at 22:06
  • https://stackoverflow.com/questions/14419954/reading-a-single-character-in-c/14419972#14419972 – William Pursell Jul 25 '22 at 22:07
  • 1
    `answer != 'y' || answer != 'n'` should use `&&`, not `||`. See https://stackoverflow.com/questions/26337003/why-non-equality-check-of-one-variable-against-many-values-always-returns-true – Barmar Jul 25 '22 at 22:07

3 Answers3

2

You don't need to use scanf(), you already asked for the input with get_char(). Just move that inside the loop in place of the scanf().

You don't need to check answer in the while() condition, since you break out of the loop when it's y or n.

int main(void)
{
    char answer;

    while (1) {
        answer = get_char("Do You Agree? y/n \n"); // prompt user to answer question

        if (answer == 'y')
        {
            printf("Great!\n");
            break;
        }
        else if(answer == 'n')
        {
            printf("That's unfortunate\n");
            break;
        }
        else
        {
            printf("only y/n please.\n"); // prompt user for acceptable character
        }
    }
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
1

The CS50 function get_char will extract a whole line of input from the input stream and then return the first character of that input., assuming that there was only a single character on the line. Otherwise, it will reprompt the user for input.

The function call

scanf("%c", &answer);

on the other hand will only extract a single character from the input stream, not a whole line, without performing any input validation. The character that scanf extracts can also be a '\n' newline character, which marks the end of the line.

The sequence of events that are occurring is the following:

  1. You call get_char, which extracts 'a' and '\n' from the input stream, and returns 'a'.
  2. You call scanf, which extracts 'a' from the input stream, but leaves '\n' on the input stream.
  3. Your program detects that the user did not enter 'y' or 'n', so it prints "only y/n please.\n".
  4. You call scanf again, which simply extracts the '\n' that was left over by the previous call to scanf, so scanf does not obtain any new input from the user.
  5. Your program incorrectly thinks that the user entered '\n' instead of 'y' or 'n', so it prints another error message.

In order to solve the problem, I recommend that you only use get_char and don't mix it with scanf. In contrast to scanf, the function get_char will never return a '\n' character. Therefore, the function get_char is much easier to use.

Since you want to call get_char more than once if necessary, you should move that function call inside the loop, so that it replaces the call to scanf.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
1

After it was pointed out that get_char() is safer and more suitable than scanf(), I've revised the code of my comment...

char c;
while( ( c = get_char( "Do You Agree? y/n " ) ) != 'y' && c != 'n' )
    printf("only y/n please.\n");

if ( c == 'y' )
    printf( "Great!\n" );
else
    printf( "That's unfortunate\n" );
Fe2O3
  • 6,077
  • 2
  • 4
  • 20
  • I don't think it is appropriate to tell OP to stop using the CS50 function [`get_char`](https://cs50.readthedocs.io/libraries/cs50/c/#c.get_char) and to use `scanf` instead. The advantages of using `get_char` are that it always reads an entire line of input and automatically reprompts the user if not exactly one character was entered. Using `scanf` with the `%s` format specifier also has the disadvantage that if the user enters two words on the same line, the program will treat that line as two separate inputs and therefore print two error messages. – Andreas Wenzel Jul 25 '22 at 22:44
  • Your input has been taken on board. Thank you! – Fe2O3 Jul 26 '22 at 04:33
  • Thank you! This worked perfectly! I like how this not only tells the user to input either y/n, but then follows up by asking "Do you agree?" again, making it a much more fluid program. Thanks again! – jaudiola Jul 26 '22 at 16:21