【问题标题】:fgets is getting skippedfgets 被跳过
【发布时间】:2018-04-14 10:24:54
【问题描述】:

我有一个小程序,我想询问一个选项,然后询问一个文件名。

  //Some code before
   printf("######################\n");
   printf("# 1. Register a file #\n");
   printf("# 2. Get global list #\n");
   printf("# 3. Download a file #\n");
   printf("# 4. Quit / Exit     #\n");
   printf("######################\n");
   printf("Enter decision: ");
      fflush(stdin);
   action = getchar();
   action -= '0';
   sprintf(input, "[%d]--", action);
   switch (action)
   {
    case 1:
     printf("Enter file name: ");
        fflush(stdin);
     fgets(input+strlen(input), LINE_LEN, stdin);
     input[strlen(input)] = (input[strlen(input)] == '\n') ? 0 : input[strlen(input)];
     if(write(sock, input, sizeof(input)) == -1) perror("Clienthandler Write 3");
    break;
//some code after

问题是我的 fget 被跳过了,即使在 gdb 中,gdb 在 inspect inputfgets 之后显示 "\n\000]--" action = 1 时的值

这是控制台输出:

######################
# 1. Register a file #
# 2. Get global list #
# 3. Download a file #
# 4. Quit / Exit     #
######################
Enter decision: 1
Enter file name: ######################
# 1. Register a file #
# 2. Get global list #
# 3. Download a file #
# 4. Quit / Exit     #
######################
Enter decision: ^C

【问题讨论】:

  • fflush(stdin); 不起作用。使用__fpurge(stdin),但应避免使用。
  • 而不是调用strlen(input) 3次,只需将结果存储在一个变量中并重复使用它[
  • @achal:__fpurge() 来自哪里?
  • @alk OP 说 我的 fgets 被跳过了 ?可能是什么原因?当然stdin 不清楚,用户需要冲洗它。 fflush(stdin) 不起作用,因为它用于输出流。其他选项是 OP 应该使用 \n__fpurge(stdin)。我同意 __fpurge(stdin) 不可移植,直到 glibc 2.1.95
  • @achal:如果你愿意,请看我的回答。

标签: c fgets getchar


【解决方案1】:

fget() 不会被跳过,而是使用 getchar() 从上一个输入中读取左侧的换行符。

这完全是关于完整错误检查和健全的日志记录:

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


#define LINE_LEN (1024)


int main(void)
{
  int action = 0;
  char input[LINE_LEN] = {0};
  size_t len = 0;

  printf("enter decision: ");
  {
    int c = fgetc(stdin); /* equivalent to getchar() */
    if (EOF == c)
    {
      putc('\n');

      if (ferror(stdin))
      {
        perror("fgetc(stdin) failed");
      }
      else
      {
        fprintf(stderr, "read EOF, aborting ...\n");
      }

      exit(EXIT_FAILURE);
    }

    action = c;
  }

  /* read left over from previous input: */
  {
    int c = fgetc(stdin);
    if (EOF == c)
    {
      putc('\n');

      if (ferror(stdin))
      {
        perror("fgetc(stdin) failed");
        exit(EXIT_FAILURE);
      }
    }
    else if ('\n' != c)
    {
      fprintf(stderr, "read unexpected input (%d), aborting ...\n", c);
      exit(EXIT_FAILURE);
    }
  }

  len = strlen(input);
  if (LINE_LEN <= len + 1) 
  {
    fprintf(stderr, "input buffer full, aborting ...\n");
    exit(EXIT_FAILURE);
  }

  switch(action - '0')
  {
    case 1:
      printf("enter file name: ");
      if (NULL == fgets(input + len, LINE_LEN - len, stdin))
      {
        putc('\n');

        if (ferror(stdin))
        {
          perror("fgets() failed");
        }
        else
        {
          fprintf(stderr, "missing input, aborting ...\n");
        }

        exit(EXIT_FAILURE);
      }

      (input + len)[strcspn(input + len, "\n")] = '\0'; /* cut off new-line, if any. */

      printf("read file name '%s'\n", input + len);

      break;

    default:
      fprintf(stderr, "unknown action (%d), aborting ...\n", action);
      exit(EXIT_FAILURE);

      break;
  }
}

【讨论】:

  • puts(""); 应该做什么?
  • @EdHeal "puts() 将字符串 s 和尾随换行符写入标准输出。" => puts(""); printf("\n");
  • 忘了换行了。 putc('\n') 会更好
  • @EdHeal:好点。将puts("")s 替换为putc('\n')s。
猜你喜欢
  • 2020-08-17
  • 1970-01-01
  • 2015-05-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-06
相关资源
最近更新 更多