Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Little trouble with fgets and error handling

Tags:

c

fgets

i have recently started to learn C and have encountered a little problem with a code snipped.

I want want wo read a character string, 20 chars long, over the stdin, so I have chosen fgets.

Here is my code:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
unsigned int length = 20;
char input_buffer[length];
fgets(input_buffer, length, stdin);
if(input_buffer == NULL)
    printf("Error, input too long");
else
    printf("%s", input_buffer);
return 0;
}

It compiles without any error, if I enter a sentence shorter than 20 characters, everything is fine. But when I try to test the error handling, it fails.

The output is:

peter@antartica ~/test % ./test    
Hello world, this is a very long test
Hello world, this i%      

Am I doing anything wrong? I thought fgets returns a NULL pointer if it fails(which should be the case here)?

Thank you for any help.

like image 978
r4ptor Avatar asked Dec 25 '22 12:12

r4ptor


2 Answers

From fgets reference:

On success, the function returns str.

If the end-of-file is encountered while attempting to read a character, the eof indicator is set (feof). If this happens before any characters could be read, the pointer returned is a null pointer (and the contents of str remain unchanged).

If a read error occurs, the error indicator (ferror) is set and a null pointer is also returned (but the contents pointed by str may have changed).

So it may return NULL without generating an error in the event of reaching end-of-file. You may need to see ferror return value to be sure about it.

Please note fgets() will automatically append a null character (\0) to the end of the string, which may cause the string to be truncated, since you specify how many characters must be read. The call won't fail if a string with more than length characters is found.

like image 193
Mauren Avatar answered Jan 13 '23 20:01

Mauren


On error, fgets() returns NULL, but the contents of the buffer are indeterminate.

You are checking the buffer, not the return value.

Try:

if ( fgets(input_buffer, length, stdin) == NULL )
{
    printf("Error, input too long");
}
else
{
    printf("%s", input_buffer);
}

Good advice: Always use {}, even for one-line blocks. It really helps avoiding errors and makes code better readable.

Edit: +1 to Mauren: A too-long input line is actually not considered an error, but silently truncated, so your whole concept won't work as intended. If in doubt, always check the docs for the function you're using. Try man fgets -- on the command line in a Unix-ish environment, or if in a pinch, in a web search engine. ;)

like image 36
DevSolar Avatar answered Jan 13 '23 21:01

DevSolar