【问题标题】:Difference between fgets and getsfgets和gets的区别
【发布时间】:2015-04-08 14:48:30
【问题描述】:

fgets()gets() 有什么区别?

当用户点击“输入”时,我试图打破我的循环。它与gets() 配合得很好,但我不想使用gets()。 我尝试使用fgets()scanf(),但结果与gets() 不同。 fgets() 无论用户在文本中输入什么,都会打破循环!这是我的代码:

void enter(void)
{
  int i,

  for(i=top; i<MAX; i++)
    {
      printf(".> Enter name (ENTER to quit): ");
      gets(cat[i].name);

      if(!*cat[i].name)
         break;

      printf(".> Enter Last Name: ");
      scanf("%s",cat[i].lastname);
      printf(".> Enter Phone Number: ");
      scanf("%s",cat[i].phonenum);
      printf(".> Enter e-Mail: ");
      scanf("%s",cat[i].info.mail);
      printf(".> Enter Address: ");
      scanf("%s",cat[i].info.address);
      printf("\n");
    }
  top = i;
}

【问题讨论】:

  • 你为什么不想使用gets
  • 我在 linux 上工作,它给我一个警告.. 我不知道,它很好用吗?
  • 哦,是的,我记得它会造成缓冲区溢出。请你解释一下为什么你不想在你的问题中使用gets
  • @Milind Bleh,我是 C 的新手。如果现在有人想杀我,我很抱歉。

标签: c scanf fgets gets


【解决方案1】:

gets()fgets() 之间的区别在于 fgets() 将换行符留在缓冲区中。所以不是检查输入的第一个元素是否为0,而是检查是否为'\n'

fgets(cat[i].name, sizeof cat[i].name, stdin);
if (cat[i].name[0] == '\n' || cat[i].name[0] == 0) {
    // empty line or no input at all
    break;
} else {
    // remove the trailing newline
    int len = strlen(cat[i].name);
    cat[i].name[len-1] = 0;
}

【讨论】:

  • 好的,我试试这个。但它打破了循环,似乎它从缓冲区读取一些文本或其他东西..
  • 当您使用scanf 读取地址时,它不会消耗行尾的换行符。所以循环重复时对fgets() 的调用将读取该换行符。
  • 好的,我该如何解决这个问题?
  • 最好的办法是不要使用scanf。使用fgets 读取每一行,并使用sscanf 解析该行。
  • 好的,我会尝试使用 fgets 读取每一行,它可以使用 fgets 来制作任何函数,而不是每次都使用所有这些检查?
【解决方案2】:

删除gets() scanf()
创建一个辅助函数来处理和限定用户输入。

// Helper function that strips off _potential_ \n
char *read1line(const char * prompt, char *dest, sizeof size) {
  fputs(prompt, stdout);
  char buf[100];
  *dest = '\0';
  if (fgets(buf, sizeof buf, stdin) == NULL) {
    return NULL;  // EOF or I/O error
  }
  // Remove potential \n
  size_t len = strlen(buf);
  if (len > 0 && buf[len-1] == '\n') {
    buf[--len] = `\0`;
  }
  // Line is empty or too long
  if (len == 0 || len >= size) return NULL;
  return memcpy(dest, buf, len+1);
}

void enter(void)
{
  int i;

  for(i=top; i<MAX; i++)
    {
      if (read1line(".> Enter name (ENTER to quit): ", 
          cat[i].name, sizeof cat[i].name) == NULL) break;
      if (read1line(".> Enter Last Name: ", 
          cat[i].lastname, sizeof cat[i].lastname) == NULL) break;
      if (read1line(".> Enter Phone Number: ", 
          cat[i].phonenum, sizeof cat[i].phonenum) == NULL) break;
      if (read1line(".> Enter e-Mail: ", 
          cat[i].info.mail, sizeof cat[i].info.mail) == NULL) break;
      if (read1line(".> Enter Address: ", 
          cat[i].info.address, sizeof cat[i].info.address) == NULL) break;
    }
  top = i;
}

fgets()gets()的一些属性:

fgets() 读取输入并保存到缓冲区,直到:
1) 缓冲区距离已满 1 步 - 或 -
2) 遇到'\n' - 或 -
3) 流达到文件结束条件 - 或 -
4) 出现输入错误。

gets() 执行上面的#2 - #4 除了它会扫描,但不保存'\n'
gets() 在 C99 中已被贬值,不再属于 C11。

【讨论】:

  • 哇!太棒了,我完成了我的工作,除了函数参数 sizeof size ,我将其更改为 int size ,因为我有错误!谢谢
【解决方案3】:

gets 和 fgets 之间存在问题的区别在于,gets 会从输入行中删除尾随的 '\n',但 fgets 会保留它。

这意味着 fgets 返回的“空”行实际上是字符串“\n”。

这意味着最好完全避免 get 的糟糕区别在于,如果你给 got 一个太长的行,你的程序将会以非常糟糕的方式崩溃。

【讨论】:

    【解决方案4】:

    您可以将 fgets() 与 STDIN 一起使用。 此函数是安全的,并且总是在字符串末尾插入一个 '\0'。

    一个例子:

    char inputbuffer[10];
    char *p;
    p = fgets(inputbuffer, sizeof(inputbuffer), stdin);
    printf(">%s<\n", p);    /* p is NULL on error, but printf is fair */
    

    在本例中,您最多可以获得 9 个字符 + '\0'。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-13
      • 2010-11-18
      • 2012-02-13
      • 2013-08-17
      • 1970-01-01
      • 1970-01-01
      • 2021-11-29
      • 2011-02-14
      相关资源
      最近更新 更多