简体   繁体   中英

Why doesn't my final scanf stop and read user input?

Can anyone tell me why my code works fine until I get to the final scant, where I ask the user if they'd like to play again? For some reason, the program seems to ignore this line of code. Please be gentle as I'm new to programming and trying to teach myself Objective-C. This program is typical for noobs, where I generate a random number, ask the user to guess, then ask if they'd like to play again. Thank you.

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[])
{

    @autoreleasepool {

        int randomNumber = arc4random_uniform(100); // This is a random number generator that gens a num betw 0 and 100
        int userNumber;     // This is the number that the user picks intially
        int attempts = 0;   // This is the number of attempts the user makes during each game
        int games = 0;      // This is the number of games the user has played
        char play = 'n';    // This is whether the user wants to play again, intially set to 'y'

        scanf("%c", &play);
        while (play == 'y') {

            NSLog(@"Random number is: %d", randomNumber);
            NSLog(@"Enter a number between 0 and 100");
            scanf("%d", &userNumber);
            games++;    // Increment the number of games the user has played to 1

            if (userNumber == randomNumber) {
                attempts++;
                NSLog(@"Congratulations. You guessed correctly!");
            }

            attempts++;

            while (userNumber != randomNumber) {

                if (userNumber < randomNumber) {    // Guess is too low
                    attempts++;                     // attempt is incremented
                    NSLog(@"Too low. Try again!");  // User tries again
                    scanf("%d", &userNumber);
                }

                if (userNumber > randomNumber) {    // Guess is too high
                    attempts++;                     // attempt is incremented
                    NSLog(@"Too high. Try again!"); // User tries again
                    scanf("%d", &userNumber);
                }
            }
            NSLog(@"Congratulations. You guessed correctly!");
            NSLog(@"It took you %d attempts to guess correctly", attempts);


            NSLog(@"Do you want to play again?");
            scanf("%c", &play); // --------- Here is where things to wrong ---------

        } // while play is yes

    } // autoreleasepool
    return 0;
} // main

Converting comments into answer:

Probably, the final scanf() reads a newline and continues (the numbers don't read the newline). Maybe put a blank before the %c :

 scanf(" %c", &play); 

Check the return value from scanf() , and maybe even check which character was read.

Riposte:

That space before the %c did the trick. How does anyone ever learn things like that? I think it was reading the \\n char rather than what I wanted it to read, which was either 'y' or 'n'. For my understanding, the %d integer doesn't read in the newline, but the %c does? Is that correct? And the way to prevent this is to use a space? I just don't get how I would ever know to do that.

And the response:

By reading the manual page for scanf() very carefully, many times over, or by bitter experience (or by answering lots of questions on SO about it). The scanf() family of functions are extremely powerful and extremely difficult to use accurately. I generally recommend using fgets() to read lines of input:

 char line[4096]; if (fgets(line, sizeof(line), stdin) != 0) { ...use line... } 

combined with sscanf() to parse the data on the line. It generally leads to fewer surprises of the sort you just ran into. You should always check that scanf() made as many conversions as you expected.

The role of white space in scanf() -family format strings is intricate. Most of the conversion specifiers skip leading white space (including newlines) automatically, so a format string "%d%d" will read to integer values where the first may be preceded by an arbitrary amount of white space, and the second may also be preceded by an arbitrary amount of white space. The conversion will stop at the first character that could not be part of the second integer (unless there was an error earlier). If you type 8 and newline as input, then the conversion stops on the newline ( \\n ) and leaves if for the next input to read.

The numeric conversions and the string conversion %s all skip leading white space. The single-character format ( %c ) and the scan set %[az] do not skip leading white space.

When a white space character appears in the format, as in "%d %c" , then it represents an arbitrary amount of white space in the data, including zero. Thus, in each of the following lines, the variable receiving the %c format will get Z each time:

123Z
123 Z
123        Z
123
               Z

(The last two lines are read together for the last input.)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM