为何C语言程序中scanf函数会意外一次性读取多个输入?
解决剪刀石头布程序中scanf读取换行符导致的流程混乱问题
你的程序出现流程混乱,核心是三个问题:
- scanf读取换行符:输入字符后按回车,回车的
\n会留在输入缓冲区,下一次scanf("%c")会直接读取这个换行符,而非等待用户输入,触发错误提示。 - 条件判断逻辑错误:原代码输入验证用了
||(逻辑或),比如inp1 != 'p' || inp1!='r'|| inp1!='s',这个条件永远为真——一个字符不可能同时是p、r、s,哪怕输入正确字符,也会触发错误提示。 - 循环变量未重置:LOOP2和LOOP3在第一次循环后被设为0,后续外层循环不会再进入输入验证的内层循环,直接跳过输入步骤。
修复后的完整代码
#include <stdio.h> int main(int argc, char* argv[]) { char inp1, inp2, inp3; int LOOP1 = 1; while (LOOP1 == 1) { int LOOP2 = 1, LOOP3 = 1; // 每次外层循环重置循环变量 printf("Player-1 it is your turn!\nPlease enter your choice (p)aper, (r)ock, or (s)cissors: "); while (LOOP2 == 1) { scanf(" %c", &inp1); // 空格跳过空白字符(包括换行) // 修正逻辑:用&&判断输入是否不在合法范围内 if (inp1 != 'p' && inp1 != 'r' && inp1 != 's') { printf("I'm sorry, I do not understand.\nPlease enter your choice (p)aper, (r)ock, or (s)cissors: "); } else { LOOP2 = 0; } } printf("Player-2 it is your turn!\nPlease enter your choice (p)aper, (r)ock, or (s)cissors: "); while (LOOP3 == 1) { scanf(" %c", &inp2); // 同样加空格跳过空白字符 if (inp2 != 'p' && inp2 != 'r' && inp2 != 's') { printf("I'm sorry, I do not understand.\nPlease enter your choice (p)aper, (r)ock, or (s)cissors: "); } else { LOOP3 = 0; } } if (inp2 == 'p') { if (inp1 == 'p') printf("No one wins.\n"); if (inp1 == 'r') printf("Player-2 wins! Paper covers rock.\n"); if (inp1 == 's') printf("Player-1 wins! Scissors cuts paper.\n"); } if (inp2 == 'r') { if (inp1 == 'p') printf("Player-1 wins! Paper covers rock.\n"); if (inp1 == 'r') printf("No one wins.\n"); if (inp1 == 's') printf("Player-2 wins! Rock breaks scissors.\n"); } if (inp2 == 's') { if (inp1 == 'p') printf("Player-2 wins! Scissors cuts paper.\n"); if (inp1 == 'r') printf("Player-1 wins! Rock breaks scissors.\n"); if (inp1 == 's') printf("No one wins.\n"); } printf("Do you wish to continue? (y/n): "); scanf(" %c", &inp3); // 同样加空格处理换行 if (inp3 == 'n') LOOP1 = 0; } return 0; }
关键修改点说明
- 处理换行符:在
%c前加空格" %c",scanf会自动跳过所有空白字符(换行、空格、制表符),只读取有效输入字符,避免缓冲区残留的换行符干扰。 - 修正条件判断:把输入验证的逻辑或
||改成逻辑与&&,只有当输入既不是p、也不是r、也不是s时,才输出错误提示,逻辑正确。 - 重置循环变量:把LOOP2和LOOP3的声明移到外层循环内部,每次外层循环开始时都会重新初始化为1,确保每次输入都能进入验证循环。
- 统一换行格式:将原代码中不规范的换行改为标准的
\n,保证输出格式清晰。
内容的提问来源于stack exchange,提问作者Stephen Freel
相关产品推荐
相关产品推荐

