fgets自然会在C中终止零?

sta*_*rob 5 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 );
}
Run Code Online (Sandbox Code Playgroud)

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

nos*_*nos 2

fgets 将 nul 终止符写入您提供的缓冲区中(如果您将缓冲区大小指定为大于 0)。否则,您无法对其调用 strlen(),strlen() 需要一个字符串,如果它不是 nul 终止,那么它就不是一个字符串。

你问的是

line[ strlen( line ) - 1 ] = '\0';
Run Code Online (Sandbox Code Playgroud)

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

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

strlen("Hello\n")为6,6-1为5,所以5.索引被0替换

"Hello\n"
      ^
      |
      Add 0 terminator
Run Code Online (Sandbox Code Playgroud)

结果:“你好”

请小心:

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