使用 gets 时我的输入被跳过

My inputs are getting skipped when using gets

我无法为循环 i = 2i = 3 的书的 name 输入内容。

它正在被跳过。 i = 1 的第一个输入是 运行 绝对没问题。

我的代码:

#include<stdio.h>

typedef struct book
{
    char name[100];
    float price;
    int pages;  
}bk;

int main(void)
{
    int i;
    bk b[100];
    // b1, b2, b3;
    for(i=1;i<=3;i++)
    {
        printf("Enter name of book %d: ",i);
        gets(b[i].name);
        printf("Enter price of book %d: ",i);
        scanf("%f",&b[i].price);
        printf("Enter pages of book %d:",i);
        scanf("%d",&b[i].pages);
    }
    printf("\nYour inputs are:");   
    for(i=1;i<=3;i++)
    {
        printf("\nName of book %d: %s",i,b[i].name);
        printf("\nPrice of book %d: %f",i,b[i].price);
        printf("\nPages of book %d: %d",i,b[i].pages);
    }
    return 0;
}

我应该如何解决这个问题?

您需要记住的第一件事是永远不要再使用 gets,更多的是 here

第二个是不要混用gets(或者说fgets,你应该用它来代替gets)和scanf.

问题的根源在于,在第二个循环中,gets 读取循环结束时 scanf 留在缓冲区中的换行符,看起来好像被跳过,它不是,如果你打印 b[2].name 你会看到它有一个换行符。

您的代码应该更像这样:

void clear_buffer(){ //helper function to clear buffer when needed
    int c;
    while((c = getchar()) != '\n' && c != EOF){}
    printf("Bad input, try again: ");
}
//...
int main(void)
{
    int i;
    bk b[100];
    for (i = 0; i < 3; i++)
    {
        printf("Enter name of book %d: ", i);
        while(scanf(" %99[^\n]", b[i].name) != 1){ // mind the space before specifer
            clear_buffer(); 
        }
        printf("Enter price of book %d: ", i);
        while(scanf("%f", &b[i].price) != 1){
            clear_buffer(); // if the value was not parsed correctly, ask again
        }
        printf("Enter pages of book %d:", i);
        while(scanf("%d", &b[i].pages) != 1){
            clear_buffer();
        }
    }
    //...
    //rest of the code
}

代码有一些改进:

  1. 使用scanf(" %99[^\n]", b[i].name)确保不会有缓冲区溢出,它最多读取99个字符,为空终止符保留一个space,这是一些gets 做不到,这就是为什么它被从语言中删除的原因,虽然有些编译器仍然支持它,但我无法想象为什么。

  2. 我正在检查 scanf 是否真的解析了值,如果没有,假设有人输入了一个字符而不是数字,它再次询问,而不是进入无限循环这就是以前会发生的事情。

  3. for (i = 0; i < 3; i++) 确保数组是从索引 0 填充的,按照你的方式,它不会使用数组的第一个元素,你必须修复printf 因此..

您正在从 stdin 读取一些垃圾,您需要使用 setbuf(stdin, NULL); 清理 stdin。而为了显示价格你只需要 2 位小数,你的程序将是这样的:

#include<stdio.h>
typedef struct book
{
    char name[100];
    float price;
    int pages;  
}bk;
int main(void)
{
    int i;
    bk b[100];
    // b1, b2, b3;
    for(i=1;i<=3;i++)
    {
        printf("Enter name of book %d: ",i);
        setbuf(stdin, NULL);
        gets(b[i].name);
        
        printf("Enter price of book %d: ",i);
        scanf("%f",&b[i].price);
        printf("Enter pages of book %d:",i);
        scanf("%d",&b[i].pages);
    }
    printf("\nYour inputs are:");   
    for(i=1;i<=3;i++)
    {
        printf("\nName of book %d: %s",i,b[i].name);
        printf("\nPrice of book %d: %.2f",i,b[i].price);
        printf("\nPages of book %d: %d",i,b[i].pages);
    }
    return 0;
}