fgets自然会在C中终止零?

时间:2010-10-13 18:54:05

标签: 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 );
}

我在stackoverflow上的另一个线程中询问了有关此代码的另一个问题,但是不想在那个上加倍 - 为什么终止零被添加到fgets读入的这些文件的末尾? fgets无论如何都会添加终止零点,这不是太过分了吗?

5 个答案:

答案 0 :(得分:3)

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

请参阅:http://www.opengroup.org/onlinepubs/009695399/functions/fgets.html

答案 1 :(得分:2)

fgets将nul终止符写入您提供的缓冲区(如果指定缓冲区大小大于0)。否则你不能在它上面调用strlen(),strlen()需要一个字符串,如果它不是nul终止它不是一个字符串。

你问的是

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

这会删除line中的最后一个字符。如果你读了一行,它会替换最后一个字符,可能是一个带有nul终结符的\ n。

考虑fgets只读一行,例如你的line缓冲区现在包含字符串“Hello \ n”(\ n这里只是转义序列,它实际上只有1个字符,而不是2)

strlen(“Hello \ n”)是6,而6-1是5,所以5.索引被0替换

"Hello\n"
      ^
      |
      Add 0 terminator

结果: “你好”

小心点:

  • 你不想做行[strlen(line) - 1] ='\ 0';在一个空字符串上,在这种情况下,你最终会做行[-1]。
  • 您应该检查fgets是否成功。如果fgets失败,你不想在line中找到它,并且没有向你的缓冲区写任何东西。
  • 您可能想要检查是否实际读取了整行。如果您阅读的行大于 kMaxLineLength,或者例如如果文件中的最后一行“没有”尾随\ n,则strlen(line)-1将不是\ n(换行符)。

答案 2 :(得分:1)

result = fgets( line, kMaxLineLength, stdin );

没关系,因为行的大小是kMaxLineLength

fgets最多从size读取一个少于stream个字符并将其存储到缓冲区中...

答案 3 :(得分:1)

line[ strlen( line ) - 1 ] = '\0';是不必要的(如果字符串尚未以字符结尾,那么不安全 - strlen()将无法正常工作)。 fgets()将终止缓冲区。此外,在尝试复制result != NULL之前,您应该检查linefgets()在文件结尾或发生错误时返回NULL。

答案 4 :(得分:1)

是的,这太过分了。

一个建议,使其更强大,以防止代码腐烂......改变

result = fgets( line, kMaxLineLength, stdin );

result = fgets( line, sizeof(line), stdin );