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;
}
getchar
中,因为取决于您使用的平台,
int
可能无法表示值
char
,您可能无法将值与有效字符代码的值区分开。
仅在确定
char
没有返回值EOF
的情况下,将
EOF
的返回值存储在
getchar
char
更改为
getchar
.。 由于您的输入是
EOF
,ch
正在被线路消耗
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;
}
}
中,我也做过。这还将删除一些代码重复。我还做了其他一些更改,这可能对您来说可能是或不可能的,具体取决于您确切想要完成的工作。