Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fgets naturally puts a terminating zero in C?

Tags:

c

fgets

struct DVDInfo  *ReadStruct( void ) {
    struct DVDInfo  *infoPtr;
    int             num;
    char            line[ kMaxLineLength ];
    char            *result;

    infoPtr = malloc( sizeof( struct DVDInfo ) );

    if ( NULL == infoPtr ) {
        printf( "Out of memory!!!  Goodbye!\n" );
        exit( 0 );
    }

    printf( "Enter DVD Title:  " );
    result = fgets( line, kMaxLineLength, stdin );
    line[ strlen( line ) - 1 ] = '\0';
    infoPtr->title = MallocAndCopy( line );

    printf( "Enter DVD comment:  " );
    result = fgets( line, kMaxLineLength, stdin );
    line[ strlen( line ) - 1 ] = '\0';
    infoPtr->comment = MallocAndCopy( line );

    do {
        printf( "Enter DVD Rating (1-10):  " );
        scanf( "%d", &num );
        Flush();
    }
    while ( ( num < 1 ) || ( num > 10 ) );

    infoPtr->rating = num;

    printf( "\n----------\n" );

    return( infoPtr );
}

I asked a different question about this code in another thread on stackoverflow but didn't want to double up on that one - why is the terminating zero being added to the end of these files read in by fgets? fgets adds the terminating zero anyway, isn't this overkill?

like image 865
startuprob Avatar asked Oct 13 '10 18:10

startuprob


2 Answers

Generally, you replace the newline character that fgets adds to the string with a NUL character. In all cases, fgets will NUL-terminate.

See: http://www.opengroup.org/onlinepubs/009695399/functions/fgets.html

like image 177
Michael Goldshteyn Avatar answered Sep 24 '22 00:09

Michael Goldshteyn


fgets writes a nul terminator into the buffer you provide (if you specify the buffer size as larger than 0). Otherwise you could not call strlen() on it, strlen() expects a string, and if it isn't nul terminated it is not a string.

You're asking about

line[ strlen( line ) - 1 ] = '\0';

This strips off the last character in line .If you've read a line, it replaces the last character, presumably a \n with a nul terminator.

Consider that fgets just read a line, e.g. your line buffer now contains the string "Hello\n" (the \n is just the escape sequence here, it's actually just 1 character, not 2)

strlen ("Hello\n") is 6, and 6-1 is 5, so the 5. index is replaced by 0

"Hello\n"
      ^
      |
      Add 0 terminator

Result: "Hello"

Just be careful:

  • you don't want to do line[ strlen(line) - 1 ] = '\0'; on an empty string, in that case you'll end up doing line[-1].
  • You should check if fgets succeds. You don't want to poke around in line if fgets failed, and didn't write anything to your buffer.
  • You might want to check whether a whole line actually got read. IF the line you read is larger than kMaxLineLength ,or e.g. if the last "line" in the file doesn't have a trailing \n , strlen(line) -1 will not be a \n (newline).
like image 43
nos Avatar answered Sep 24 '22 00:09

nos