2016-07-06 12 views
2

fread()を使用してファイルを文字列にコピーしようとしていますが、新しい行の数と正確に等しいファイルから余分な文字が取得されています。なぜfread()はcで余分な '#newlines'文字を読みますか?

このプログラムの
#include <stdio.h> 
#include <stdlib.h> 
#define LEN 5000000 

int main() 
{ 
    char *in = (char*) malloc(LEN); 
    FILE *f=fopen("in.txt","r"); 
    fread(in,5000000,1,f); 
    printf("%ld\n", ftell(f)); 
    in[ftell(f)]=0; 
    int l; 
    for(l=0;true;l++) 
    { 
     if(in[l]<10) 
     break; 
     printf("%d ",in[l]); 
    } 
    printf("\n"); 
} 

入力は次のとおりです:入力用

1 
2 
<newline> 

リンク:https://paste.fedoraproject.org/388281/46780193/
私は文字のASCII値を印刷しています出力の場合は、読み: はここに私のコードです

6 
49 10 50 10 13 10 

入力の場合:

0入力用

リンク:https://paste.fedoraproject.org/388280/
、出力は次のようになります。

9 
49 10 50 10 51 10 51 13 10 

私は文字のすべてのテストケースの余分な数は常に新しい行の数ある他のいくつかのテストcases.Inを見ました。
私にはほとんど質問がありません:
- このようなパターンはどうですか?
- これは、新しい行が2バイトのウィンドウを受け取るという事実とどのように関連していますか?
- 余分な文字を削除するにはどうすればよいですか?
私も同様の質問をしましたが、回答が見つかりませんでした。誰か説明してください。

+2

なぜですか?それはまさにファイルの内容なのですから。改行文字( '\ n')は、新しい行*を表すためにそこにある必要があります。改行を取り除く方法はたくさんあります。最良の方法は、達成しようとしているものによって異なります。例えば、[fgets()の入力から末尾の改行文字を削除する]を参照してください。(http://stackoverflow.com/questions/2693776/removing-trailing-newline-character-from-fgets-input) – kaylum

+0

ファイルの正確な内容を表示してください。 – 2501

+0

また、 'fread()'呼び出しで数値を入力するのではなく、特に定義した 'LEN'を使っていないのはなぜですか? – Magisch

答えて

2

あなたの例のように、テキストモードで開いたストリームでftellを呼び出すことは意味がありません。

関数freadの使用法が正しくないため、サイズとカウントの引数が切り替わります。つまり、ファイルには5000000文字が含まれていないため、読み取りは常に部分的です。したがって、呼び出し後の配列内の要素の値は、不確定値の値を持ちます。あなたのケースでは、論理要素はサイズ5000000の単一要素です。

あなたが見ている結果は意味がありません。不定値を読み取ると、未定義の動作が発生する可能性があります。ファイルがコンテンツを持っているとき

#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h> 
#include <assert.h> 

int main() 
{ 
    unsigned char in[500] = { 0 } ; 
    FILE *f=fopen("in.txt","r"); 
    assert(f) ; 

    const size_t read = fread(in,1,500,f); 
    printf("read: %zu\n" , read); 

    for(size_t index = 0 ; index < read ; index++) 
    { 
     printf("%hhu " , in[index]); 
    } 

    fclose(f); 
} 

この正しいプログラムを使用して、:

あなたのファイルを読むための正しい方法は、関数freadに正しいパラメータを渡すと、正常に読み込まれた文字数を決定するために、戻り値を使用することです(ドットは、ファイルの一部ではありません):

read: 7 
49 10 50 10 51 10 10 

. 
1 
2 
3 

. 

は正しい値を読み、印刷します

改行文字が1つあり、の値が10で、最後に1つ追加されます。(:ISO:IEC 9899:から引用201X 7.21.9.4 ftellは機能2)


テキストストリームについて
、そのファイル位置インジケータはのためのfseek関数によって使用可能な、不特定 情報が含まれていftell呼び出し時に ストリームのファイル位置インジケータをその位置に戻します。そのような2つの戻り値の違いは、必ずしも書き込まれたり読み取られた文字数の有意義な尺度ではありません。

(より引用:ISO:IEC 9899:201X 7.21.8.1関数fread 2)
部分エレメントが読み出された場合、その値は不定です。

Windowsファイルでは、改行は13,10の2つの文字で表されます。キャリッジリターンと改行。しかし、テキストモードでファイルを読むとき、改行は常に改行文字にすぎません。10.プログラムの動作が意味をなさないため、文字13を見ました。あなたが(正しく)バイナリモードでファイルを開いて読むと、両方の文字で改行が見えます。

-1

CR-LF(キャリッジリターン、ラインフィード)((ASCII)13,10)を各改行に付けるエディタを使用してWindowsを使用し、ファイルin.txtを編集した場合、これは必ず起こります。プログラムでin.txtを書いてみて、それを読んでみてください。それは期待どおりになるでしょう。または、CR-LFをeol(行末)に付けることのないエディタを使用してください。申し訳ありませんが、私はそのようなエディタを知らない[​​しかし、いくつかのLinuxエディタは動作します。

関連する問題