【问题标题】:C - Prompted for a second input and does nothingC - 提示输入第二个输入但什么也不做
【发布时间】:2015-09-16 12:41:56
【问题描述】:

这是我下面的代码。它的作用不是问题。问题是,一旦它运行,我输入我的输入,如果它太小,它会在第二行再次要求输入,这似乎不会影响我的程序流程。如果我填充了缓冲区(我假设缓冲区是 100 或更多),则不会要求我再次提示。

#include <stdio.h>
#include <string.h>

int main()
{
  int ch;
  char x[3];
  char *word, string1[100];
  x[0]='y';

  while(x[0]=='y'||x[0]=='Y')
  {
    fgets(string1, 100, stdin);
    while ( (ch = fgetc(stdin)) != EOF && ch != '\n');
    printf("The string is: %s", string1);

    word = strtok(string1, " ");
    while(word != NULL)
    {
      printf("%s\n", word);
      word = strtok(NULL, " ");
    }

    printf("Run Again?(y/n):");
    fgets(x, 2, stdin);
    while ( (ch = fgetc(stdin)) != EOF && ch != '\n');
  }

  return 0;
}

编辑: 我已经换了,

    fgets(string1, 100, stdin);
    while ( (ch = fgetc(stdin)) != EOF && ch != '\n');

与,

 fgets(string1, 100, stdin);
 if (string1[98] != '\n' && string1[99] == '\0') 
 { 
   while ( (ch = fgetc(stdin)) != EOF && ch != '\n'); 
 }

【问题讨论】:

  • @JohnnyMopp fflush(stdin); 是 UB。
  • 我想的也差不多。有什么建议吗?

标签: c input buffer stdin fgets


【解决方案1】:

来自手册页:

fgets()  reads in at most one less than size characters from stream and stores them into the buffer pointed to by s.  Reading stops
   after an EOF or a newline.  If a newline is read, it is stored into the buffer.  A terminating null byte ('\0') is stored after the
   last character in the buffer.

fgets 会将所有输入(最多 99 个chars)放入 string1。如果您输入 98 个字符并按回车键(创建第 99 个\n),则所有 100 个字符都将被使用,因为最后一个字符是 \0 终止符。

然后你会陷入那个小的while 循环,它只会消耗另一行输入。如果您输入的字符串小于最大值,则输入会在该循环等待\n 时暂停。

如果您输入 >98 个字符,则前 99 个字符将保存到您的输入字符串中,其余的以及最后的 \n 立即通过该 while 循环运行,使其退出速度足够快,以至于看起来被跳过。

我希望这会有所帮助。不幸的是,我无法发表评论并要求澄清,所以我在这里要说的是,很难说出你究竟想要修复或明确什么。

【讨论】:

  • 非常好的评论。感谢您帮助我更好地理解 fgets。我已经通过检查 string[99] 的空终止符和 string[98] 的不是下一行字符来解决这个问题。
【解决方案2】:

您的问题的答案就在这里:man fgets

fgets()stream 中读取最多比size 少一个字符,并将它们存储到s 指向的缓冲区中。 EOF 或换行符 后停止阅读。如果读取了换行符,则将其存储到缓冲区中。终止空字节 ('\0') 存储在缓冲区中的最后一个字符之后。

要知道fgets 是否使用了整个缓冲区,请将一些非 NUL 字节写入缓冲区的末尾。如果在调用fgets 之后,该字节已被 NUL 覆盖,则表示缓冲区已满。如果直接在它之前的字符不是换行符,那么还有更多的输入需要读取。

buffer[size - 1] = 'a'; // any character that's not '\0'
fgets(buffer, size, stdin);
if (buffer[size - 1] == '\0' && buffer[size - 2] == '\n') {
    // handle extra input
}

或者,您可以使用 getchar 一次读取一个字节。

【讨论】:

  • 这很麻烦,但我会试一试。我的老师要求每一个细节。如果他问为什么会有第二个输入,我说我不知道​​。肯定会划掉。理所当然的!
  • @AndrewRicci 如果 fgets 读取的字符串中的最后一个字符不是 \n,则该行太大而无法容纳缓冲区。第二个输入将消耗剩下的输入。
  • 感谢您的评论,非常感谢。
【解决方案3】:

我认为你需要这个:

注意:x 必须是 int,如果您想将其与 EOF 进行比较

int main()
{
  int x;
  char *word, string1[100];

  do
  {
    fgets(string1, 100, stdin);
    printf("The string is: %s", string1);

    word = strtok(string1, " ");
    while(word != NULL)
    {
      printf("%s\n", word);
      word = strtok(NULL, " ");
    }

    printf("Run Again?(y/n):");
    x = fgetc(stdin);
    fgetc(stdin); // absorb `\n`
  }
  while( (x=='y'||x=='Y') && x != EOF) ;

  return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-08
    • 1970-01-01
    • 1970-01-01
    • 2011-08-30
    • 1970-01-01
    • 2016-01-30
    • 2021-10-15
    相关资源
    最近更新 更多