getChar()在输入后继续等待 - 仅在再次按Enter;

问题描述 投票:0回答:1
Edit:问题已经解决 - 感谢所有人的提示! 这个问题是

getchar();

函数开头的
play_game();
声明,我试图清除缓冲区,但没有足够的知识如何正确执行此操作。
我的程序在使用GetChar()之后等待输入时遇到问题。我使用循环清除缓冲区,并且在程序中出现了四次相同的功能,但是只有在两个实例上,循环就会陷入困境,我不明白为什么。
在两个工作实例中,唯一的区别是丢失的语句,但是当我从非工作实例中删除它时,问题没有解决,他们仍然陷入了等待第二次输入。

如果我输入“ y”或“ y”以外的其他内容,我会收到“无效的输入”消息,然后我再次要求输入,以便此功能有效。但是,当我输入“ y”或“ y”时,然后输入时,出现了一条新线,什么也不会发生。如果我再次输入无效的输入,我将收到“无效的输入”消息,并且使用正确的输入,我仍然会得到一条新行,什么也不会发生。仅在正确输入后一秒钟输入后,代码仍应按照应有的延续。

非工作实例:

else if

工作实例:

printf("Play a game? (Y/N): "); while (!is_valid) { user_choice = getchar(); char ch; while ((ch = getchar()) != '\n' && ch != EOF) {} // clear the buffer if (user_choice == 'y' || user_choice == 'Y') { is_valid = true; play_game(); } else if (user_choice == 'n' || user_choice == 'N') break; else { printf("Invalid input. Try again.\n"); } }

Full代码:

    printf("Roll dice ('R')\n");
    while (!is_valid) {
        first_roll = getchar();     
        char ch;
        while ((ch = getchar()) != '\n' && ch != EOF) {} // clear the buffer

        if (first_roll == 'r' || first_roll == 'R') {
            is_valid = true;
        }
        else {
            printf("Invalid input. Try again.\n");
        }
    } 

你能给我一个暗示我做错了什么吗?

函数

#include <stdio.h> #include <stdbool.h> #include <stdlib.h> // For rand() /* 2025-02-19 RULES Come-Out Roll: You roll two dice. - If the sum is 7 or 11, you win right away. - If the sum is 2, 3, or 12 (called “craps”), you lose immediately. - If the sum is 4, 5, 6, 8, 9, or 10, that number becomes your point. Point Phase: Once a point is set, you keep rolling the dice. - If you roll the point number again before rolling a 7, you win. - If you roll a 7 before the point, you lose. */ int roll_dice(void); bool play_game(void); int main() { int roll = 0; char user_choice; bool is_valid = false; // Game loop printf("Play a game? (Y/N): "); while (!is_valid) { // In this loop it waits for a second ENTER user_choice = getchar(); char ch; while ((ch = getchar()) != '\n' && ch != EOF) {} // clear the buffer if (user_choice == 'y' || user_choice == 'Y') { is_valid = true; play_game(); } else if (user_choice == 'n' || user_choice == 'N') break; else { printf("Invalid input. Try again.\n"); } } return 0; } int roll_dice(void) { // Generate 2 random numbers 1-6 int dices = (rand() % 12 + 1); // Sum the numbers return dices; } bool play_game(void) { bool result = false; bool is_valid = false; bool game_has_ended = false; char first_roll; char user_choice; int roll_result; getchar(); // One dice roll printf("Roll dice ('R')\n"); while (!is_valid) { // This loop goes fine first_roll = getchar(); char ch; while ((ch = getchar()) != '\n' && ch != EOF) {} // clear the buffer if (first_roll == 'r' || first_roll == 'R') { is_valid = true; } else { printf("Invalid input. Try again.\n"); } } roll_result = roll_dice(); int roll = 1; int point = 0; // Evaluate roll if (roll == 1) { switch (roll_result) { // Immediate win case 7: { result = true; point = 0; break; }; case 11: { result = true; point = 0; break; }; // Immediate lose case 2: { result = false; break; }; case 3: { result = false; break; }; case 12: { result = false; break; }; // Point case 4: { roll = 2; point = 4; result = true; break; }; case 5: { roll = 2; point = 5; result = true; break; }; case 6: { roll = 2; point = 6; result = true; break; }; case 8: { roll = 2; point = 8; result = true; break; }; case 9: { roll = 2; point = 9; result = true; break; }; case 10: { roll = 2; point = 10; result = true; break; }; } } // Roll 1 results if (result == false) { printf("Roll 1: %d\n", roll_result); printf("You lose!\n"); game_has_ended = true; } else if (result == true && roll == 1 && point == 0) { printf("Roll 1: %d\n", roll_result); printf("You win!\n"); game_has_ended = true; } else { // Roll 2 if (roll == 2 && point > 0) { printf("Point: %d\n", roll_result); char roll_2; bool is_valid = false; while (!is_valid) { // This loop goes fine printf("Press 'R' to roll again.\n"); roll_2 = getchar(); char ch; while ((ch = getchar()) != '\n' && ch != EOF) {} if (roll_2 == 'r' || roll_2 == 'R') { is_valid = true; } else { printf("Invalid input. Try again.\n"); } } // Roll 2 results switch (roll_dice()) { case 7: { result = false; printf("Roll 2: %d\n", roll_dice()); printf("You lose!\n"); game_has_ended = true; break; } default: { result = true; printf("Roll 2: %d\n", roll_dice()); printf("You win!\n"); game_has_ended = true; break; } } } } // Recursion is_valid = false; printf("Play another game? (Y/N): "); while (!is_valid) { // In this loop it waits for a second ENTER user_choice = getchar(); char ch; while ((ch = getchar()) != '\n' && ch != EOF) {} if (user_choice == 'y' || user_choice == 'Y') { is_valid = true; play_game(); } else if (user_choice == 'n' || user_choice == 'N') return game_has_ended; else { printf("Invalid input. Try again.\n"); } } return game_has_ended; }

返回类型的值。您不应将该函数的返回值存储在a
getchar
中,因为取决于您使用的平台,

c getchar
1个回答
0
投票
int

可能无法表示值

char
您可能无法将值与有效字符代码的值区分开。
仅在确定
char

没有返回值
    EOF
  • .
    的情况下,将
    EOF
    的返回值存储在
    getchar
  • 中才是安全的。
  • 请参阅以下问题以获取更多信息:
  • 为什么必须将用于保存getchar返回值的变量称为int?
要解决此问题,您要做的就是将数据类型从

char

更改为
getchar
.
由于您的输入是
EOF

ch

正在被线路消耗

char 在函数

int

中,

y\n
被以下行所消耗:
y
在函数

user_choice = getchar();
中,您将再次致电

main

,而无需先打印提示,询问用户进一步输入。这意味着用户将必须在不看到任何输入提示的情况下输入附加的输入行,这可能会使用户非常困惑。这个对
\n
的呼叫没有意义,尤其是因为该功能调用是在丢弃其读取的字符。
为了防止此类问题,我建议您不要直接从C标准库中调用输入功能。我建议您创建自己的功能,该功能总是从用户读取整个输入。此功能还应提示用户获取输入,如果由于某种原因,如果先前的输入无效,则将自动重复输入以获取输入。这将使处理程序的主要逻辑的代码更简单,更清洁,因为它不必处理处理用户输入的详细信息。 我为此创建了一个函数

while ((ch = getchar()) != '\n' && ch != EOF) {}
。此功能使用我的功能
play_game

从我的答案到另一个问题

。我修改了您的程序以使用这些功能:
getchar()

该程序具有以下行为:
getchar()

I还通过删除递归和大量code重复
对本递归的重复来简化了您的程序。在这种情况下,使用递归通常不是一个好主意,因为例如用户播放1000款游戏,那么该功能
get_char_from_user
将在记忆中1000次(除非编译器执行
tail-call optimization demiatizan fiptrization the Compiler theCommiatization
),这意味着该功能的所有变量都将在记忆中1000次,这将是记忆的大量浪费。因此,我修改了您的程序以使用迭代而不是递归。

此外,移动代码似乎很有意义,该代码提示用户输入

get_line_from_user

将骰子滚动到功能

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> int roll_dice( const char *prompt ); void play_game( void ); char get_char_from_user( const char *prompt ); void get_line_from_user( const char *prompt, char *buffer, int buffer_size ); int main( void ) { char *prompt = "Play a game? (Y/N): "; // Game loop for (;;) // infinite loop { char user_choice = get_char_from_user( prompt ); if ( user_choice == 'y' || user_choice == 'Y' ) { play_game(); prompt = "Play another game? (Y/N): "; continue; } if (user_choice == 'n' || user_choice == 'N') { break; } printf("Invalid input. Try again.\n"); } } int roll_dice( const char *prompt ) { // repeat until input is valid for (;;) { char roll = get_char_from_user(prompt); if ( roll == 'r' || roll == 'R' ) { break; } printf("Invalid input. Try again.\n"); } // NOTE: The comments below seem incorrect, and were taken // over from the original code // Generate 2 random numbers 1-6 int dices = (rand() % 12 + 1); // Sum the numbers return dices; } void play_game( void ) { bool result = false; bool game_has_ended = false; int roll_result; // One dice roll roll_result = roll_dice( "Roll dice with 'R': " ); int roll = 1; int point = 0; // Evaluate roll if (roll == 1) { switch (roll_result) { // Immediate win case 7: { result = true; point = 0; break; }; case 11: { result = true; point = 0; break; }; // Immediate lose case 2: { result = false; break; }; case 3: { result = false; break; }; case 12: { result = false; break; }; // Point case 4: { roll = 2; point = 4; result = true; break; }; case 5: { roll = 2; point = 5; result = true; break; }; case 6: { roll = 2; point = 6; result = true; break; }; case 8: { roll = 2; point = 8; result = true; break; }; case 9: { roll = 2; point = 9; result = true; break; }; case 10: { roll = 2; point = 10; result = true; break; }; } } // Roll 1 results if (result == false) { printf("Roll 1: %d\n", roll_result); printf("You lose!\n"); game_has_ended = true; } else if (result == true && roll == 1 && point == 0) { printf("Roll 1: %d\n", roll_result); printf("You win!\n"); game_has_ended = true; } else { // Roll 2 if (roll == 2 && point > 0) { printf("Points: %d\n", roll_result); roll_result = roll_dice( "Enter 'R' to roll again: " ); // Roll 2 results switch ( roll_result ) { case 7: { result = false; printf("Roll 2: %d\n", roll_result); printf("You lose!\n"); game_has_ended = true; break; } default: { result = true; printf("Roll 2: %d\n", roll_result); printf("You win!\n"); game_has_ended = true; break; } } } } } // This function will attempt to read one "char" from the user. This // "char" must be by itself on its own line. If the input is invalid, // it will automatically reprompt the user, until the input is valid. char get_char_from_user( const char *prompt ) { // loop forever until user enters a single "char" for (;;) { char buffer[1024]; // get one line of input from the user as a string get_line_from_user( prompt, buffer, sizeof buffer ); // verify that line is not empty if ( buffer[0] == '\0' ) { printf( "Error: Line should not be empty.\n" ); continue; } // verify that line contains not more than one character if ( buffer[1] != '\0' ) { printf( "Error: Please enter only a single character!\n" ); continue; } return buffer[0]; } } // 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 ); // 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; } }

中,我也做过。这还将删除一些代码重复。
我还做了其他一些更改,这可能对您来说可能是或不可能的,具体取决于您确切想要完成的工作。
	
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.