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の別のスレッドでこのコードについて別の質問をしましたが、そのコードを2倍にしたくありませんでした-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は、指定したバッファーにnulターミネーターを書き込みます(バッファーサイズを0より大きい値として指定した場合)。それ以外の場合は、strlen()を呼び出すことができず、strlen()は文字列を予期し、nulで終了しない場合は、文字列ではありません。

あなたはについて尋ねています

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

これにより、の最後の文字が削除されlineます。行を読んだ場合は、最後の文字(おそらく\ n)がnulターミネータに置き換えられます。

fgetsが行を読み取るだけであると考えてください。たとえば、lineバッファに文字列「Hello \ n」が含まれているとします(\ nはここでは単なるエスケープシーケンスであり、実際には2文字ではなく1文字です)

strlen( "Hello \ n")は6、6-1は5なので、5。インデックスは0に置き換えられます

"Hello\n"
      ^
      |
      Add 0 terminator

結果:「こんにちは」

注意してください:

  • line [strlen(line)-1]='\0';を実行したくない 空の文字列で、その場合はline[-1]を実行することになります。
  • fgetsが成功したかどうかを確認する必要があります。linefgetsが失敗し、バッファに何も書き込まなかった場合は、いじくり回したくありません。
  • 行全体が実際に読み取られたかどうかを確認することをお勧めします。読み取った行がkMaxLineLengthより大きい場合、またはファイルの最後の「行」に末尾の\ nがない場合、strlen(line)-1は\ n(改行)にはなりません。
于 2010-10-13T19:24:15.023 に答える
1

あなたの

result = fgets( line, kMaxLineLength, stdin );

行のサイズが。なので、OKですkMaxLineLength

fgetsから最大で1文字少ないsize文字を読み込みstream、バッファに格納します...

于 2010-10-13T19:03:19.560 に答える
1

line[ strlen( line ) - 1 ] = '\0';不要です(そして安全strlen()ではありません—文字列がまだヌル文字で終了していない場合は正しく機能しません)。fgets()バッファを無効にします。result != NULLまた、コピーを試みる前にそれを確認する必要がありますlinefgets()ファイルの終わりまたはエラーが発生した場合にNULLを返します。

于 2010-10-13T19:05:08.557 に答える
1

はい、それはやり過ぎです。

コードの腐敗に対してより堅牢にするための1つの提案...変更

result = fgets( line, kMaxLineLength, stdin );

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