8

私は次のコードを実行しています:

#include<stdio.h>
#include<string.h>
#include<io.h>

int main(){
    FILE *fp;
    if((fp=fopen("test.txt","r"))==NULL){
        printf("File can't be read\n");
        exit(1);
    }
    char str[50];
    fgets(str,50,fp);
    printf("%s",str);
    return 0;
}

text.txtに含まれるもの:I am a boy\r\n

私はWindowsを使用しているので、改行文字として\ r \ nが必要です。したがって、これをファイルから読み取ると、に保存"I am a boy\n\0"されますstrが、。を取得し"I am a boy\r\n"ます。私はmingwコンパイラを使用しています。

4

3 に答える 3

9

動作は、C ライブラリの実装と、どのモードに渡すかによって異なりますfopenfopen (MSDN の fopen) に関するMSDN ドキュメントからのこの引用を参照してください。

b - バイナリ (未翻訳) モードで開きます。復帰文字と改行文字を含む翻訳は抑制されます。

つまり、Microsoft c ライブラリを使用し、'b' を省略してファイルを開くと、キャリッジ リターン文字がストリームから削除されます。

mingw を使用しているため、コンパイラはおそらく POSIX 標準に準拠した GNU c ライブラリにリンクしています。これは、GNU ドキュメントfopen (gnu.org の fopen)について述べていることです。

opentype の文字 'b' には標準的な意味があります。テキスト ストリームではなく、バイナリ ストリームを要求します。しかし、これは POSIX システム (GNU システムを含む) では何の違いもありません。

結論:ストリームをテキストモードで開く「b」モード文字を省略しています。Windows を使用していますが、テキスト モードとバイナリ モードの違いがない GNU c ライブラリを使用しています。fgetsこれが、キャリッジ リターンと改行の両方を読み取る理由です。

于 2013-09-27T06:37:48.727 に答える
5

私はWindowsを使用しているため、\r\nを改行文字として使用します...

この仮定は間違っています。C 標準では、C99 §5.2.1/3 (文字セット) で証明されているように、キャリッジ リターンと改行を 2 つの異なるものとして扱います。

[...] 基本的な実行文字セットには、アラート、バックスペース、キャリッジ リターン、改行を表す制御文字が含まれます。[...]

C99 §7.19.7.2/2のfgets関数の説明は次のとおりです。

fgets 関数は、stream が指すストリームから s が指す配列に、n で指定された文字数より最大で 1 つ少ない文字を読み取ります。改行文字 (保持されます)の後またはファイルの終わりの後、追加の文字は読み取られません。ヌル文字は、配列に読み込まれた最後の文字の直後に書き込まれます。

したがって、 string に遭遇した場合I am a boy\r\n、準拠する実装はその\n文字まで読み取る必要があります。\rプラットフォームに基づいて実装を破棄する正当な理由はおそらくありません。

于 2012-10-07T14:23:01.113 に答える