【问题标题】:Scanf recursive function triggers printf twice?scanf递归函数触发printf两次?
【发布时间】:2019-06-13 18:30:55
【问题描述】:

我正在尝试创建一个函数来获取“y”或“n”的用户输入。

#include <stdio.h>
#include "userinput.h"

bool userinput_get_yes_or_no(char message[]) {
    printf("%s [y/n]: \n", message);

    char answer;
    scanf_s(" %c", &answer, 1);

    if (answer == 'y') return true;
    if (answer == 'n') return false;

    return userinput_get_yes_or_no(message);
}

当用户只输入“y”、“n”时效果很好。 当您输入任何其他内容(但只有 1 个字符)时,它会重复问题并打印一次消息。

但是 当您输入超过 1 个字符的内容时,该消息会重复多次(与您输入的字符一样多次),然后再等待输入。

我做错了什么?

【问题讨论】:

  • 假设(因为可以测试和确认/拒绝):字符已经输入到控制台/std-in,并且在消耗之前不会被丢弃。所以 "yy" 将导致读取 两个 'y' 字符,每次调用一个,因为一次只消耗一个字符。
  • 糟糕的递归使用。使用简单的 do-while 循环。
  • “我做错了什么” - 你似乎假设scanf_s(" %c", &amp;answer, 1); 在阅读stdin 时会神奇地清除所有字符,包括空格和非空格,除了第一。那不是它的作用。如果您输入“abc”并提取“a”,则输入流中还剩下“bc”,并且您的循环愉快地为每次迭代消耗一个。
  • 首先使用scanf...
  • scanf 表示“读取下一个可用字符”,而不是“等待输入”(粗略地说)

标签: c scanf


【解决方案1】:

我复制了您的问题 - 基本上,您的控件正在流入您的函数的下一次调用,并在 stdin 队列中找到已经存在的内容。我找到了一个有用的答案here on c-faq.com,并将其添加到您的函数中:

bool userinput_get_yes_or_no(char message[])
{
    char answer;
    char c; /* for discard */
    printf("%s [y/n]: \n", message);
    scanf_s(" %c", &answer, 1);
    while((c = getchar()) != '\n' && c != EOF); /* discard */
    if (answer == 'y') {
        return true;
    }
    else if (answer == 'n') { 
        return false;
    }
    else {
        return userinput_get_yes_or_no(message);
    }
}

为了便于阅读,我稍微更改了控制流程,请随意忽略。重要的部分是标记为丢弃的行,我们丢弃缓冲区的其余部分,确保没有任何东西在等待函数的下一次调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-27
    • 2019-09-13
    • 1970-01-01
    • 2016-04-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多