fgets()总是使用\ 0终止char缓冲区吗?

时间:2009-11-02 09:27:38

标签: c fgets

即使已经达到EOF,fgets()总是使用\ 0终止char缓冲区吗?它看起来确实如此(它肯定在ANSI K& R书中提供的实现中),但我想我会要求确定。

我想这个问题适用于其他类似的函数,例如gets()。

编辑:我知道在“正常”情况下会附加\ 0,我的问题是针对EOF或错误条件。例如:

FILE *fp;
char b[128];
/* ... */
if (feof(fp)) {
    /* is \0 appended after EACH of these calls? */
    fgets(b, 128, fp);
    fgets(b, 128, fp);
    fgets(b, 128, fp);
}

5 个答案:

答案 0 :(得分:10)

fgets总是向读缓冲区添加'\ 0',它会从流中读取最多size - 1个字符(size是第二个参数)因此。< / p>

永远不要使用gets因为你永远不能保证它不会溢出你给它的任何缓冲区,所以虽然它在技术上总是终止读取字符串,但实际上并没有帮助。

答案 1 :(得分:8)

永远不要使用获取!!

    7.19.7.2 The fgets function
    Synopsis
1           #include <stdio.h>
            char *fgets(char * restrict s, int n,
                 FILE * restrict stream);
    Description
2   The fgets function reads at most one less than the number of characters
    specified by n from the stream pointed to by stream into the array pointed
    to by s. No additional characters are read after a new-line character
    (which is retained) or after end-of-file. A null character is written
    immediately after the last character read into the array.
    Returns
3   The fgets function returns s if successful. If end-of-file is encountered
    and no characters have been read into the array, the contents of the array
    remain unchanged and a null pointer is returned. If a read error occurs
    during the operation, the array contents are indeterminate and a null
    pointer is returned.

所以,,当fgets()没有返回NULL时,目标数组总是有一个空字符。

如果fgets()返回NULL,则目标数组可能已更改,并且可能没有空字符。从fgets()获取NULL后,永远不要依赖数组。


编辑示例已添加

$ cat fgets_error.c
#include <stdio.h>

void print_buf(char *buf, size_t len) {
  int k;
  printf("%02X", buf[0]);
  for (k=1; k<len; k++) printf(" %02X", buf[k]);
}

int main(void) {
  char buf[3] = {1, 1, 1};
  char *r;

  printf("Enter CTRL+D: ");
  fflush(stdout);
  r = fgets(buf, sizeof buf, stdin);
  printf("\nfgets returned %p, buf has [", (void*)r);
  print_buf(buf, sizeof buf);
  printf("]\n");

  return 0;
}
$ ./a.out
Enter CTRL+D:
fgets returned (nil), buf has [01 01 01]
$

请参阅?在buf中没有NUL:)

答案 2 :(得分:4)

man fgets:

fgets()从流中读取最多一个小于大小的字符,并将它们存储到s指向的缓冲区中。读数在EOF或换行符后停止。如果读取新行,则将其存储到缓冲区中。 A'\ 0'存储在缓冲区中的最后一个字符之后。

答案 3 :(得分:2)

如果您确实以二进制模式&#34; rb&#34;打开文件,并且如果您想使用fgets逐行读取文本,则可以使用以下代码来保护软件丢失文本,如果通过文本中包含的错误是&#39; \ 0&#39;字节。 但最后与提及的其他人一样,如果流包含&#39; \ 0&#39;通常不应使用fgets

size_t filepos=ftell(stream);
fgets(buffer, buffersize, stream);
len=strlen(buffer);
/* now check for > len+1 since no problem if the 
   last byte is 0 */
if(ftell(stream)-filepos > len+1) 
{
    if(!len) filepos++;
    if(!fseek(stream, filepos, SEEK_SET) && len)
    {
        fread(buffer, 1, len, stream);
        buffer[len]='\0';
    }
}

答案 4 :(得分:0)

是的。来自CPlusPlus.com

  

从流中读取字符并将它们作为C字符串存储到str中,直到读取了(num-1)个字符或者到达了换行符或文件结尾,以先到者为准。

     

换行符使fgets停止读取,但它被认为是有效字符,因此它包含在复制到str的字符串中。

     

在读取字符后,空字符会自动附加在str中,以表示C字符串的结尾。