【问题标题】:scanf AFTER fgets breaks the fgets statementscanf AFTER fgets 中断 fgets 语句
【发布时间】:2014-10-03 01:31:48
【问题描述】:

我看过各种帖子,说明如何在 fgets 之前使用 scanf 可能会导致问题。但是,我认为为什么在 AFTER 之后添加它会导致第一个语句中断。

这就是我所拥有的:

  unsigned char key;
  unsigned char message[100];

  printf(" Please input a message \n  ");
  fgets(message, MAX_BUF, stdin); 
  printf("Your message is:  %s \n", message);


  // Read user input for message
  printf(" Please input a numeric key\n  ");
  scanf("%d", &key);

  printf("Your message is:  %s \n", message);
  printf("strlen(message) = %d \n", strlen(message));

这是一次“试运行”:

  Please input a message
   hello
   Your message is: hello

  Please input a numeric key
   123

  Your message is: 
  strlen(message) = 0

像这样,无论输入如何,消息变量最终都是空的。但是,如果我用 scanf 注释掉该行,一切正常(除了我无法分配键)。

救命!

【问题讨论】:

  • 只在程序中稍后运行的代码应该不可能及时返回并更改之前的输出。因此,请使用您问题上的 EDIT 按钮提供"Minimal, Complete, Verifiable Example"。没有它,就不可能确切知道您的定义是什么或可能导致您看到的问题的原因。
  • 报告fgets()scanf() 的返回值以帮助理解问题至关重要。显示您的输入会有所帮助。
  • 感谢 cmets,这是我在 Stack Overflow 上的第一个问题,因此对于帖子的不完整深表歉意。我已经编辑了它,希望它现在很好。
  • @HostileFork 未定义的行为可能导致时间旅行。 (虽然在这段代码中不需要时间旅行,因为虚假输出直到 UB 之后才会出现)
  • @MattMcNabb 嗯。我现在看到了一个可能未开发的电影剧本领域。 “宇宙是一台巨大的计算机,如果你违反规则,宇宙编译器可以随意对事件进行重新排序。Michael J Fox 和 Christopher LLoyd 在《回到未来 IV:未定义的行为》中回归” (也许宇宙规范说 87 mph 是 DeLorean 应该走的最快速度?)

标签: c scanf fgets


【解决方案1】:

%d 格式说明符到 scanf() 是一个承诺,即下一个参数是内存缓冲区的地址,该地址足够大以容纳 int(通常为 4 或 8 个字节),但您的 key只是一个 1 字节的 unsigned char,所以 scanf() 将在末尾写入 3(或者可能 7)字节,践踏占用该内存的任何内容——在这种情况下,很可能是 message。它究竟写了什么取决于你的系统的字节序,但对于小端系统(例如 x86)上的小输入(message 的第一个字节)将为 0,这实际上以零长度终止 message

【讨论】:

  • %d 承诺下一个参数 实际上是指向 int 的指针。做任何其他事情(即使大小合适)都会导致未定义的行为,尽管您可能会侥幸逃脱。
  • 谢谢。在 %u 也没有工作后,我切换到了 %d。我刚刚发现正确的格式说明符是 %hhu。
  • @PabloPrado:很高兴你解决了这个问题。如果我的回答有帮助,请点赞和/或将其标记为已接受的答案:)
猜你喜欢
  • 1970-01-01
  • 2010-11-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多