为什么 scanf 将值传递给我的函数,不希望 scanf 将值发送给被调用者

Why does scanf pass the value to my function, dont want scanf to send value to callee

我知道 scanf() 用法,不鼓励使用。但我遇到了问题,scanf 将标准输入值发送到下一个函数标准输入。我想知道为什么会这样。

代码:

#include <stdio.h>

void ffgets() {
    char name[40];
    printf("What's your name? ");
    if (fgets(name, 40, stdin)) {
        printf("Hello %s", name);
    }
}

int main(int argc, char **argv) {
    int a;
    printf("enter a number: ");

    int res = scanf("%d", &a);
    if (res > 0) {
        printf("Valid Integer %d.\n", a);
    } else {
        printf("It's not a number\n");
    }

    ffgets();
    return 0;
}

输出:

测试用例 1:

为什么函数不请求标准输入,它只打印空字符串

 ./a.out 
enter a number: 23
Valid Integer 23.
What's your name? Hello 

测试用例 2:我输入了带有传递给 name 的特殊字符的字符串。

./a.out 
enter a number: random##¤
It's not a number
What's your name? Hello random##¤

我不想将 main 中的标准输入值传递给函数,该怎么做?

原因是在第一种情况下,匹配输入被 scanf() 消耗,但换行符 \n 出现在输入缓冲区中。在第一种情况下,fgets() 的有效输入终止符。

相关,引用 C11,章节 §7.21.6.2

Trailing white space (including new-line characters) is left unread unless matched by a directive. [....]

在第二种情况下,匹配失败发生,这使得整个输入在 fgets() 调用时在输入缓冲区中可用,因此 fgets() 读取整个内容。

如果您输入的内容 scanf 与格式规范不匹配,那么它会立即停止并且 将输入留在输入缓冲区中以供下一个输入函数使用.

此外,当使用 scanf 时,它不会消耗输入缓冲区中的尾随换行符,并将其留给下一个输入函数。

要解决这两个问题,请考虑使用 fgets 从输入中获取整行,然后使用 sscanf 解析字符串。

I am aware of scanf() usage and is not encouraged.

这正是来自 scanf() 的问题(即,scanf 未使用的输入留在输入缓冲区中,这与用户的预期相反)。因此,正如您似乎已经知道的那样,解决方案是不使用该功能。

创建一个函数来读取完整的输入行,并使用 sscanf()strtol 或朋友从那里解析一个 int 并不难:

#include <stdio.h>
#include <limits.h>

int getint(void)
{
    char buffer[120] = {0}; /* arbitrary limit */
    fgets(buffer, 120, stdin);
    int a;
    if (sscanf(buffer, "%d", &a) == 1) {
        return a;
    }
    return INT_MIN;
}

(当然 INT_MIN 是一个有效的输入数字,因此您可能希望有一些更好的方法来返回错误。也许考虑如何处理数字后面的垃圾。)