4

使用fflush(stdin) 和 和有什么不一样flushstdin()?我知道的唯一区别是我需要在使用之前写下那些 void 的东西flushstdin(),但我不知道为什么。

void flushstdin()
{
    int c;
    while((c = getchar()) != '\n' && c != EOF); 
}
int main () {
    float a, b, c;
    float s=0, ar1=0, ar2=0;
    printf("Inform value of side A");
    while(scanf("%f",&a) != 1 || a <= 0){ 
        printf("Invalid value.\n");
        flushstdin();
    }
}

int main(){
    float a,b,c,s=0;
    printf("Inform value of side A.");
    while(scanf("%f",&a) != 1 || a<=0){
        printf("Invalid value.\n");
        fflush(stdin);
    }
}

我是初学者!哪个代码最好?或者他们是平等的?

4

3 回答 3

8

不同之处在于这flushstdin是用户定义的,并且是标准 C 中的唯一方法 flush stdin
fflush是标准库函数。fflush(stdin);将调用未定义的行为。

c-常见问题解答:12.26a

fflush仅为输出流定义。由于它对“flush”的定义是完成缓冲字符的写入(而不是丢弃它们),丢弃未读输入对于fflush输入流来说不是一个类似的含义。

常见问题解答: 12.26b

没有标准方法可以从 stdio 输入流中丢弃未读字符。一些供应商确实实现fflushfflush(stdin)丢弃未读字符,尽管可移植程序不能依赖于此。(一些版本的stdio库实现fpurgefabort调用做同样的事情,但这些也不是标准的。)还要注意,冲洗stdio输入缓冲区不一定足够:未读字符也可以累积在其他操作系统级别的输入缓冲区中。如果您尝试主动放弃输入(可能是因为预期会发出意外提示以确认破坏性操作,而意外键入的“y”可能是灾难性的),您将不得不使用特定于系统的技术来检测预输入输入的存在;见问题 19.1 和 19.2。请记住,如果您丢弃碰巧输入得太快的输入,用户可能会感到沮丧。

于 2015-06-05T20:15:30.603 回答
2

它们完全不同。它们都可以“刷新”输入,但该词的含义不同。

fflush是一个标准的 C 函数。它在诸如输入流上的行为stdin未定义的——这意味着 C 标准没有定义它的行为。

一些系统确实定义了fflush输入流的行为。例如在 Linux 上:

对于输入流,fflush()丢弃任何已从底层文件获取但尚未被应用程序使用的缓冲数据。

如果您的程序在基于 Linux 的系统上运行,或者在记录相同行为的另一个系统上运行,您可以依赖fflush(stdin)于按照此描述运行。您的程序的行为将不可移植;在其他系统上,它可能会以任意糟糕的方式运行。(很可能如果不起作用,它只会返回错误指示,但不能保证。)fflush(stdin)

您自己的flushstdin函数所做的事情与fflush(stdin). 它读取并丢弃所有输入函数,直到第一个换行符或直到EOF(由文件结尾或错误触发)。无论输入是否被缓冲,它都会这样做。

例如,假设您键入字符hello(没有换行符),然后您的程序调用fflush(stdin)然后您输入换行符。

fflush(stdin),鉴于 Linux 记录的行为,将丢弃hello并立即返回,让换行符由以后的调用读取。它“刷新”stdin的意思是它丢弃所有待处理的输入,不管它是什么。

您的flushstdin()函数将读取并丢弃hello,然后等到您键入Enter(或Ctrl-D),然后读取并丢弃它。它读取并丢弃直到换行符或 EOF 的所有输入,无论它在调用时是否处于挂起状态。

同样,C 标准没有定义 的行为fflush(stdin),因此使用它会使您的程序不可移植(并且您的编译器不一定会警告您)。

顺便说一句,“那个空洞的东西”是函数的定义flushstdin。它不是必需的,fflush因为这是已经为您定义的标准 C 库函数。

于 2015-06-05T20:48:31.090 回答
1

两个版本都有问题。

正如已经广泛记录的那样,fflush(stdin)根据 C 标准具有未定义的行为。使用该flushstdin()功能的替代方案也好不到哪里去。我建议一次读取一行标准输入并用 解析它sscanf(),所有这些都在一个实用函数中,您可以根据需要使用它:

int readfloat(const char *prompt, float *val) {
    char buf[128];
    for (;;) {
        if (prompt) 
            fputs(prompt, stdout);
        if (!fgets(buf, sizeof(buf), stdin)) {
            printf("Premature end of file\n");
            return 1;
        }
        if (sscanf(buf, "%f", val) == 1 && *val > 0)
            return 0;
        printf("Invalid value.\n");
    }
}

int main(void) {
    float a, b, c, s = 0;
    if (readfloat("Enter value of side A: ", &a))
        return 1;
    ...
}
于 2015-06-05T21:07:32.627 回答