Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does fgets() always terminate the char buffer with \0?

Tags:

c

fgets

Does fgets() always terminate the char buffer with \0 even if EOF is already reached? It looks like it does (it certainly does in the implementation presented in the ANSI K&R book), but I thought I would ask to be sure.

I guess this question applies to other similar functions such as gets().

EDIT: I know that \0 is appended during "normal" circumstances, my question is targeted at EOF or error conditions. For example:

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);
}
like image 897
Ree Avatar asked Nov 02 '09 09:11

Ree


People also ask

Does fgets include \0?

The fgets() function stores the result in string and adds a NULL character (\0) to the end of the string. The string includes the newline character, if read. The fgets() function is not supported for files opened with type=record or type=blocked .

Does fgets have null terminate?

fgets terminates at the newline character but appends it at the end of the string str . The function also appends the terminating null character at the end of the passed string.

Does fgets automatically add null terminator?

The fgets() function stores the result in string and adds a null character (\0) to the end of the string. The string includes the new-line character, if read.

What does fgets return at end-of-file?

If the end of file is reached without reading any characters, fgets is obliged to return NULL .


3 Answers

fgets does always add a '\0' to the read buffer, it reads at most size - 1 characters from the stream (size being the second parameter) because of this.

Never use gets as you can never guarantee that it won't overflow any buffer that you give it, so while it technically does always terminate the read string this doesn't actually help.

like image 84
CB Bailey Avatar answered Sep 27 '22 20:09

CB Bailey


Never use gets!!

    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.

So, yes, when fgets() does not return NULL the destination array always has a null character.

If fgets() returns NULL, the destination array may have been changed and may not have a null character. Never rely on the array after getting NULL from fgets().


Edit example added

$ 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]
$

See? no NUL in buf :)

like image 35
pmg Avatar answered Sep 27 '22 20:09

pmg


man fgets:

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 new‐line is read, it is stored into the buffer. A '\0' is stored after the last character in the buffer.

like image 45
eyalm Avatar answered Sep 27 '22 20:09

eyalm