Proper length passed to fgets

Viewed 62

If I have the following buffer:

char buffy[40]; // includes \0 at the end

Should the fgets function have STLEN 40 or 39? Why?

char buffy[40];
while (fgets(buffy, 40, fp) != EOF)
    // ...
4 Answers

The number of characters that fgets reads in is at most one less than the value of its second parameter. So the proper value should be 40 in this context. It will read at most 39 characters and the last element of the array will be used to store the '\0'. This ensures that no buffer overrun will occur. As an idiom

fgets(buf, sizeof buf, fp)

may be used if (and only if) the declaration of the array buf is visible.

Notice that there is nothing wrong with calling it as fgets(buf, 39, fp), but this will cause it to read in at most 38 characters, and the '\0' will be stored in buf[38] (if 38 characters have been read). The last element of the array (buf[39]) will not be used at all.

Per C11 7.21.7.2 The fgets function:

Synopsis

    #include <stdio.h>
    char *fgets(char * restrict s, int n,
         FILE * restrict stream);

Description

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.

So

char buffy[40];
while (fgets(buffy, 40, fp) != NULL)

is correct, but

char buffy[40];
while (fgets(buffy, sizeof(buffy), fp) != NULL)

would be better.

If you will write for example

fgets(buffy, 39, fp)

then the function fgets will know nothing about that actually the array contains 40 characters.:)

So the 40-th element of the array will not be used and will be redundant.

As you declared the array with 40 characters

char buffy[40]; 

then use all of them in a call of fgets as for example

fgets(buffy, sizeof( buffy ), fp)

The function will read from the string no more than 39 characters and appends the array with the zero character '\0'.

If you need to remove the new line character '\n' from the inputted string then you can write for example

buffy[ strcspn( buffy, "\n" ) ] = '\0'; 

As stated in the fgets docs:

Arguments:
...
n - This is the maximum number of characters to be read (including the final null-character). Usually, the length of the array passed as str is used.

So, you should use 40 if your array has a length of 40.

Related