getchar() 如何在 While 循环中工作?

How does getchar() work in a While loop?

当我在做练习册时,程序的这一部分让我感到困惑。

为什么当我交换最后一个 if 语句和 while getchar() 时得到相同的结果?

在这两种情况下,我都先得到句子 "Enter the next title."。在这两种情况下,我都得到 getchar() 秒,等待光标闪烁的输入。

不应该把 while(getchar()!= '\n'); continue; 首先让程序在打印之前等待输入 puts("Enter the next title.");

我的理解应该是卡在while循环中,直到出现exit条件,再进行下一条语句!这是打印

首先是if语句:

while(count< MAXBKS && s_gets(library[count].title,MAXTITL) != NULL && library[count].title[0] != '[=10=]')
    {
        puts("Now enter the author.");
        s_gets(library[count].author,MAXAUTL);
        puts("Now enter the value.");
        scanf("%f", &library[count++].value);
        if( count < MAXBKS)  //  1  //
            puts("Enter the next title.");
        while(getchar()!= '\n')  //  2  //
            continue;

    }

首先是while(getchar()..

while(count< MAXBKS && s_gets(library[count].title,MAXTITL) != NULL && library[count].title[0] != '[=11=]')
{
    puts("Now enter the author.");
    s_gets(library[count].author,MAXAUTL);
    puts("Now enter the value.");
    scanf("%f", &library[count++].value);
    while(getchar()!= '\n')  //   2  //
        continue;

    if( count < MAXBKS)    //   1  //
        puts("Enter the next title.");
}

这是上下文的完整程序:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 10

char * s_gets(char * st, int n);
struct book
{
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};


int main(void)
{
    struct book library[MAXBKS];
    int count = 0;
    int index, filecount;
    FILE *pbooks;
    int size = sizeof(struct book);

    if ((pbooks = fopen("book.dat", "a+b")) == NULL)
    {
        fputs("Can't open book.dat file\n", stderr);
        exit(1);
    }

    rewind(pbooks);
    while(count< MAXBKS && fread(&library[count],size,1, pbooks) == 1)
    {
        if (count ==0)
            puts("Current contents of book.dat:");
        printf("%s by %s: $%.2f\n", library[count].title, library[count].author, library[count].value);
        count++;
    }
    filecount = count;
    if(count == MAXBKS)
    {
        fputs("The book.dat file is full.\n", stderr);
        exit(2);
    }
    puts("Please add new book titles.");
    puts("Press [enter] at the start of a line to stop.\n");
    while(count< MAXBKS && s_gets(library[count].title,MAXTITL) != NULL && library[count].title[0] != '[=12=]')
    {
        puts("Now enter the author.");
        s_gets(library[count].author,MAXAUTL);
        puts("Now enter the value.");
        scanf("%f", &library[count++].value);
        while(getchar()!= '\n')
            continue;

        if( count < MAXBKS)
            puts("Enter the next title.");
    }
    if(count>0)
    {
        puts("Here is a list of your books:");
        for(index =0; index < count; index++)
            printf("%s by %s: $%.2f\n", library[index].title, library[index].author, library[index].value);
        fwrite(&library[filecount],size,1,pbooks);
    }
    else
        puts("No books? Too bad.\n");
    puts("Bye.\n");
    fclose(pbooks);
    return(0);
}


char *s_gets(char *st, int n)
{
    char *ret_val;
    char *find;

    ret_val= fgets(st,n,stdin);
    if (ret_val)
    {
        find = strchr(st, '\n');
        if(find)
            *find = '[=12=]';
        else
            while(getchar() != '\n')
                continue;
        }
        return (ret_val);
    }

Shouldn't putting the while(getchar()!= '\n'); continue; first make the program wait for an input before printing puts("Enter the next title.");?

不,while(getchar()!= '\n'); continue;会清除输入缓冲区1,它会 不等待用户输入。然后它将打印文本。不行的原因 等待用户输入的东西是你之前有一个scanf。如果它 匹配一个浮点数,它将转换并保存在 &library[count++].value, 但是换行符将留在输入缓冲区中。这就是为什么人们使用这个 清除输入缓冲区中剩余部分的方法。如果它不匹配任何东西, 那么整行将保留在输入缓冲区中。

因此,先执行哪个并不重要,缓冲区将是 清除,您的文本将被打印。就是下一个fgets中的s_gets() 调用哪个块并等待用户输入,而不是 getchar().

My understanding that it should be stuck inside while loop until the condition of exit is present, then proceed to the next statement! which is the print

确实如此,您很可能误解了谁阻止并等待 用户输入。

一些建议:

最好这样清除缓冲区:

int c;
while( (c = getchar()) != '\n' && c != EOF);

此外,最好始终检查 scanf 的 return 值。它将 return 成功匹配令牌的数量。所以如果你期望一次转化,那么 检查 scanf returns 1. 如果不是这样,则输入错误。你 可能决定清除缓冲区并让用户输入重试。


1显然,如果第一个读取的代码是 while(getchar() != '\n') continue; 那么它会阻塞并等待用户输入,因为输入缓冲区将为空。但在你的情况下,输入缓冲区肯定不是空的。