在 C 中,为什么检测从递归函数输入的字符会导致它运行多次?

问题描述 投票:0回答:1

我有一个递归函数,它使用

printf()
scanf()
来处理用户输入。如果用户不小心按错了键(不是“y”),它会循环返回。但是,如果用户输入多个字符,该函数会要求用户一次输入多次。
printf()
行的重复次数与输入中的字符一样多。

为什么终端缓冲区中的字符过多会导致这种行为,而不是整个事情崩溃或终端只是忽略以下字符?

int testDetectorWhite(){
    char userConfirmation;
    
    printf("Please place a WHITE disk directly below the detector\n");
    printf("Press 'y' when ready:\n");
    scanf("%c", &userConfirmation);
    printf("\n");
    
    if(userConfirmation != 'y'){
        testDetectorWhite();
    }
    
    //more code
}

我尝试重写代码,用递归 if() 代替 while() 循环,如下所示:

while(userConfirmation != 'y') {
        printf("Please place a WHITE disk directly below the detector\n");
    printf("Press 'y' when ready:\n");
    scanf("%c", &userConfirmation);
}

但是,我仍然遇到完全相同的错误。

我尝试通过使

userConfirmation
成为一个字符串来解决问题,这解决了多个
printf()
函数运行的问题,但导致了更多超出我的问题范围的问题。

c recursion char scanf
1个回答
0
投票

你有两个问题,都与

scanf
功能及其许多不足有关。

  1. 要读取单个非空白字符,正如您在此处尝试执行的那样,格式
    "%c"
    无法按预期工作。您需要使用
    " %c"
    ,其中有一个额外的空间。参见 scanf() 在缓冲区中留下换行符 .
  2. 如果你想编写优雅地处理用户错误的代码,要求用户在发生这种情况时重试,
    scanf
    不是一个好的选择。一般来说,问题是“坏”输入往往会留在输入流中,未读,这意味着您可能不得不尝试以某种方式“刷新”它。另见如何在 fgets 循环中正确刷新标准输入使用 fflush(stdin).

一般来说,如果你想让用户键入表单 A 的输入,但又担心用户可能会键入表单 B 的输入,你必须让用户键入,并且你必须读入,即表单 B 的输入。 您不能只编写代码来尝试读取表单 A 的输入,希望表单 B 的输入会被神奇地丢弃。 例如,正如您在此处看到的,如果您编写的代码在循环中使用

%c
读取单个字符,而用户错误地键入了三个字符,则您的循环将运行三次。

所以在一般情况下,如果你想处理用户可能错误地输入任何随机形式 B 而不是你想要的输入的情况,你最终不得不将用户的输入读取为 string,使用

scanf %s
,或者
fgets
。然后你必须检测输入是否是你想要的形式(“形式 A”)。然后您可能必须将输入转换为您想要的形式(例如,从字符串转换为单个字符,或从字符串转换为整数)。

无可否认,这是要做的更多工作,而且有点麻烦。如果您刚刚起步,我建议您专注于正确的输入,也就是说,编写代码时假定用户永远不会输入任何错误的内容。显然,从人为因素的角度来看,检测错误的输入是很好的,打印一个很好的提示要求用户再试一次,但是正确地编码却非常困难!这是一个你可能想推迟几周的问题,同时你会了解更多关于解决它所需的其他 C 工具。

© www.soinside.com 2019 - 2024. All rights reserved.