Home > Software design >  How to read a yes / no response from the user?
How to read a yes / no response from the user?

Time:10-08

Taking a beginning programming class and learning C. This is the first significant obstacle I've run into, was at it for 6 hours yesterday and couldn't find a solution, so I gave up and decided to ask for help. Assignment is to build a number guessing game (haven't yet gotten to the random number generation part) with a loop based on a boolean, where the user is prompted after a correct guess to play again and answer y or n. I've tried a bunch of stuff, and the loop either terminates regardless of the option chosen (which is what it does in its current state), or loops endlessly regardless, and I'm not sure what I'm doing wrong. Here's my code. Thanks in advance.

#include <stdio.h>
#include <stdbool.h>

int main()
{
    int num = 5; /* temp placeholder for testing */
    int guess;
    char* response;
    bool running = true;

    while (running)
    {
        printf("Guess a number: ");
        scanf("%d", &guess);
            
        if (guess < num)
        {
            printf("That's too low.\n\n");
        }
        else if (guess > num)
        {
            printf("That's too high.\n\n");
        }
        else
        {
            printf("That is correct.\n\n");
            guess = 0;
            printf("Play again? (y/n): ");
            scanf(" %c", response);
            printf("Response: [%s]", response);
            printf("\n");
            
            if (response == "y")
            {
                running = true;
            }
            else
            {
                running = false;
            }
        }
    }
    return 0;
}

CodePudding user response:

You are confusing strings with a single character. Here you have response declared as a pointer to a char.

 char* response; 

change that to

 char response;

change

 scanf(" %c", response);

to - this is passing in the address of the one character variable. %c accepts one character.

  scanf(" %c", &response);

Change

if (response == "y") 

to

if (response == 'y')

string literals use double-quotes. Also if you actually wanted to compare strings, that is not the correct way either, and you should look at the strcmp() function.

CodePudding user response:

The first issue to be aware of is that == is not defined for strings (or other array types) - response == "y" doesn't work like you'd expect1.

To compare strings, you need to use the strcmp library function:

if ( strcmp( response, "y" ) == 0 ) // strcmp returns 0 if the strings match
{
  // do something
}

The second issue is that you're confusing your types. You declare response as a char *, meaning that it's meant to store the address of another char object, not a character value. However, you never initialize it to point to a char object - its value is indeterminate, and it's pointing somewhere random. When you call scanf with it, you're writing the input value to some random location which in your case just happens to be writable and not "important" (in the sense that it doesn't cause your code to crash immediately).

You most likely want to do it the way OldProgrammer showed - change the type from char * to char, change the scanf call to use &response, and change the test to response == 'y' (single instead of double quotes).

Alternately, you can treat response as a string - in that case, you'd declare it as an array of char, large enough to hold your response plus the string terminator - in this case, 2 elements:

char response[2]; // 'y' or 'n' plus a string terminator

Instead of using scanf (which is prone to buffer overflows if you aren't careful), we'd use fgets instead:

if ( !fgets( response, sizeof response, stdin ) )
  // input operation failed, handle as appropriate
else
  // process response

and then as I said above, you'd use strcmp for the comparison:

if ( strcmp( response, "y" ) == 0 )
  // process yes response
else
  // process no response

Interestingly, you got the format string right for reading a single character (most new C programmers don"t). Unlike most conversion specifiers, %c won't skip over any leading whitespace, and more often than not people wind up reading stray newlines rather than the input they intend. Putting the blank before it in " %c" tells scanf to skip over any leading whitespace.


  1. What it's actually doing is comparing the address value stored in response to the address of the first character of the string literal "y". The only way that expression will ever be true is if response stores the address of the literal "y".
  •  Tags:  
  • c
  • Related