当只读取换行符

时间:2015-09-24 08:51:23

标签: c

以下是来自Prata的C Primer Plus的gets()的描述:

  

通常,它会从系统的标准输入设备中获取一个字符串   你的键盘。因为字符串没有预定长度,所以gets()   需要一种方法来知道何时停止。它的方法是读取字符   直到它到达你生成的换行符(\ n)   按Enter键。它需要所有角色(但不是   包括)换行符,固定空字符(\ 0),并给出   字符串到调用程序。

我很好奇当gets()只读取换行符时会发生什么。所以我写了这个:

  int main(void)
  {
    char input[100];

    while(gets(input))
    {
      printf("This is the input as a string: %s\n", input);
      printf("Is it the string end character? %d\n", input == '\0');
      printf("Is it a newline string? %d\n", input == "\n");
      printf("Is it the empty string? %d\n", input == "");
    }

    return 0;
  }

这是我与该计划的互动:

$ ./a.out
This is some string
This is the input as a string: This is some string
Is it the string end character? 0
Is it a newline string? 0
Is it the empty string? 0

This is the input as a string:
Is it the string end character? 0
Is it a newline string? 0
Is it the empty string? 0

当我按下的所有内容都输入时,第二个块真的是感兴趣的东西。在这种情况下,input究竟是什么?它似乎不是我的任何猜测:\0\n""

2 个答案:

答案 0 :(得分:3)

它将字符串设置为"",即{'\0'}。但是,不要使用gets()。它会导致缓冲区溢出。

答案 1 :(得分:1)

gets说明中的这一部分可能令人困惑:

  

所有角色都需要(但不包括)换行符

最好说 所有字符包括换行符,但存储所有字符不包括新线。

因此,如果用户输入some stringgets函数将从用户终端读取some string和换行符,但仅在缓冲区中存储some string - 换行符丢失了。这很好,因为无论如何都没有人想要换行符 - 它是一个控制字符,而不是用户想要输入的数据的一部分。

因此,如果您只按输入gets会将其解释为空字符串。现在,正如一些人所指出的,您的代码存在多个错误。

  

printf("This is the input as a string: %s\n", input);

这里没问题,不过你可能想用一些人工字符来划分你的字符串,以便更好地调试:

  

printf("This is the input as a string: '%s'\n", input);

  

printf("Is it the string end character? %d\n", input == '\0');

不好:你想在这里检查1个字节,而不是整个缓冲区。如果您尝试将整个缓冲区与0进行比较,则答案始终为false,因为编译器将\0转换为NULL并将比较解释为“缓冲区是否存在?”。

正确的方法是:

  

printf("Does the first byte contain the string end character? %d\n", input[0] == '\0');

这只比较1个字节到\0

  

printf("Is it a newline string? %d\n", input == "\n");

不好:这会将缓冲区的地址与"\n"的地址进行比较 - 答案始终为false。在C中比较字符串的正确方法是strcmp

  

printf("Is it a newline string? %d\n", strcmp(input, "\n") == 0);

请注意特殊用法:strcmp在字符串相等时返回0。

  

printf("Is it the empty string? %d\n", input == "");

这里有同样的错误。此处也使用strcmp

  

printf("Is it the empty string? %d\n", strcmp(input, "") == 0);

正如人们总是说的那样,BTW不能以安全的方式使用,因为它不支持缓冲区溢出保护。因此,您应该使用fgets代替,即使它不太方便:

gets

这可能会引起混淆:char input[100]; while (fgets(input, sizeof input, stdin)) { ... } 不会从它读取的输入中删除换行符。因此,如果您将代码中的fgets替换为gets,则会得到不同的结果。幸运的是,您的代码将以清晰的方式说明差异。