【问题标题】:My inputs are getting skipped when using gets使用获取时我的输入被跳过
【发布时间】:2021-06-05 01:56:11
【问题描述】:

对于循环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;
}

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

【问题讨论】:

    标签: c string input struct structure


    【解决方案1】:

    您需要记住的第一件事是永远不要再使用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 个字符,为空终止符保留一个空间,这是gets 无法做到的,这就是它被从语言,虽然一些编译器仍然支持它,但我无法想象为什么。

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

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

    【讨论】:

      【解决方案2】:

      您正在从标准输入读取一些垃圾,您需要使用setbuf(stdin, NULL); 清理标准输入。为了显示价格,您只需要小数点后 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;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-06-03
        • 2021-11-29
        • 2016-04-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-14
        • 1970-01-01
        相关资源
        最近更新 更多