5
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 );
}

我在 stackoverflow 上的另一个线程中问了一个关于此代码的不同问题,但不想在那个问题上加倍 - 为什么将终止零添加到 fgets 读取的这些文件的末尾?fgets 无论如何都会添加终止零,这不是矫枉过正吗?

4

5 回答 5

3

通常,您将 fgets 添加到字符串中的换行符替换为 NUL 字符。在所有情况下,fgets 都将 NUL 终止。

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

于 2010-10-13T18:57:31.360 回答
2

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).
于 2010-10-13T19:24:15.023 回答
1

您的

result = fgets( line, kMaxLineLength, stdin );

可以,因为线的大小是kMaxLineLength

fgets从最多读取一个size字符,stream并将它们存储到缓冲区中......

于 2010-10-13T19:03:19.560 回答
1

是不必要的line[ strlen( line ) - 1 ] = '\0';(并且不安全——strlen()如果字符串还没有以 nul 结尾,则无法正常工作)。fgets()将终止缓冲区。此外,您应该result != NULL在尝试复制line. fgets()在文件结尾或发生错误时返回 NULL。

于 2010-10-13T19:05:08.557 回答
1

是的,这太过分了。

一项建议是让它更强大地抵抗代码腐烂......改变

result = fgets( line, kMaxLineLength, stdin );

result = fgets( line, sizeof(line), stdin );
于 2010-10-13T19:47:19.020 回答