【问题标题】:skipping over scanf loops in c跳过c中的scanf循环
【发布时间】:2015-09-15 17:53:49
【问题描述】:

我不知道为什么,当我运行它时,它会跳过“书中有多少页”scanf 并直接进入第二个循环“谁是作者”。

我确定这与空白有关,但我认为我使用 for 循环底部的 getchar 解释了这一点。

标题:

struct bookInfo{
  char title[40];
  char author[25];
  float price;
  int pages;
}; 

.c 文件:

int main()
{
  int ctr;
  struct bookInfo books[3]; 
  for (ctr = 0; ctr < 3; ctr++)
  {
    printf("what is the name of the book #%d?\n", (ctr+1));
    gets(books[ctr].title);
    puts("who is the author?");
    gets(books[ctr].author);
    puts("how much did the books cost");
    scanf(" $%f", &books[ctr].price);
    puts("how many pages in the book");
    scanf(" %d", &books[ctr].pages);
    getchar();
  }

  printf("here is the collection of books: \n");
  for (ctr = 0; ctr <3; ctr++)
  {
    printf("book #%d: %s by %s", (ctr+1), books[ctr].title, books[ctr].author);
    printf("\nit is %d pages and costs $%.2f", books[ctr].pages, books[ctr].price);
  }
  return 0;
}

【问题讨论】:

  • 你记得输入美元符号$吗?您应该始终检查来自scanf 的返回值,以验证调用是否成功。
  • 使用调试器是你的朋友。通常,这是一个比发布更好的朋友,因为调试器并不关心您描述的问题与您提供的代码一起没有意义(但您的帖子的读者可能会注意到这个细节)。
  • 谢谢。问题是忘记了 $ - 多么迟钝哈哈。绝对不会再犯这个错误
  • 函数:gets() 由于它的许多故障不再与我们同在。强烈建议使用fgets()

标签: c scanf


【解决方案1】:

改变这个:

puts("how much did the books cost");
scanf(" $%f", &books[ctr].price);

到这里:

printf("how much did the books cost: $");
fflush( stdout );
scanf("%f", &books[ctr].price);

除非您打算让您的用户在价格前输入$,否则会很烦人。您不需要格式字符串中的前导空格,因为%f 告诉scanf 跳过前导空格。

其次,永远永远永远永远永远永远永远永远使用gets。曾经。以任何方式,形状或形式。它(不是可能,)在您的程序中引入故障点/主要安全漏洞。它在 1999 年标准中已弃用,并已从 2011 年标准的标准库中删除。它相当于在淋浴时拼接火线的编程。

使用fgets(与gets 不同,如果有空间,它将尝试将换行符存储在目标缓冲区中)或scanf(在转换说明符中具有适当的精度)。

【讨论】:

  • 如果理解正确 - gets 不好但 fgets 不是?
  • @i486:正确。 gets 不知道目标缓冲区有多大,如果用户键入更多缓冲区大小可以容纳的文本,那么 gets 会很高兴地将多余的文本写入目标缓冲区之后的内存,从而导致各种混乱。 fgets 允许您指定从输入流中读取的最大字符数,使其更安全一些(显然,您必须传递正确的值,因此它并非完全万无一失,但它不是 @ 987654335@ 是)。从 2011 年标准开始,不再支持 gets
【解决方案2】:

这是因为 gets() 读取当前缓冲区中存在的文本行。并且由于当前缓冲区包含“作者姓名是什么?”它会读取它。

如果你显示结构成员的内容,你可以清楚地观察到这一点。

所以我建议这个 使用

    char *temp;
    fgets(STDIN,temp);

循环开始之前。

这对你有帮助

【讨论】:

  • gets 不是从stdout 读取的,并且temp 没有指向任何有意义的地方; fgets 调用很可能会导致访问冲突。
  • fgets() 接受 3 个参数。
猜你喜欢
  • 1970-01-01
  • 2020-07-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-10
  • 2010-12-12
  • 2016-06-05
相关资源
最近更新 更多