1

私はCが初めてで、ファイルの読み取り方法を学ぼうとしています。私のファイルは、以下を含む単純なファイル (テスト用のみ) です。

this file
has been
successfully read
by C!

そこで、次の C コードを使用してファイルを読み取りました。

#include <stdio.h>

int main() {

   char str[100];
   FILE *file = fopen("/myFile/path/test.txt", "r");

   if(file == NULL) {
      puts("This file does not exist!");
      return -1;
   }

   while(fgets(str, 100, file) != '\0') {
      puts(str);
   }

   fclose(file);

   return 0;
}

これは私のテキストを次のように印刷します:

this file

has been

successfully read

by C!

コンパイルして実行すると、出力が にパイプされ、各行の末尾にhexdump -C余分なものが表示されます。0a

最後に、ファイルから読み取る文字の配列を宣言する必要があるのはなぜですか? 各行のデータ量がわからない場合はどうすればよいですか?

4

2 に答える 2

8

fgets()改行まで読み取り、改行を文字列に保持し、出力するためにputs()指定された文字列に常に改行を追加します。したがって、コードで使用すると、ダブルスペースの出力が得られます。

fputs(str, stdout)の代わりに使用しputs()ます。改行を追加しません。

廃止された関数gets()— C 標準の 2011 バージョンから削除されました — は改行まで読み取りますが、それを削除しました。gets()とのputs()ペアは、 と のようにうまく連携しましfgets()fputs()。ただし、絶対に使用しないでくださいgets()。それは起こるのを待っている大惨事です。(1988 年gets()に移行した最初のインターネット ワーム — Google で「morris インターネット ワーム」を検索)。


コメントで、審問官は次のように尋ねました。

行を特定のサイズの char 配列に読み込む必要があるのはなぜですか?

利用可能なスペースをオーバーランしないようにする必要があるためです。C は、文字列のスペースの自動割り当てを行いません。これは、いくつかの観点から見ると、その弱点の 1 つです。それは強みでもありますが、言語の初心者を日常的に混乱させます。入力コードで 1 行に十分なスペースを割り当てたい場合は、POSIX 関数を使用しますgetline()

'\0'特定の行の文字数が常にわかるとは限らないので、ヒットするまで読み取りと出力を行う方がよいでしょうか?

いいえ、一般的にはヒットしません'\0'。ほとんどのテキスト ファイルには、これらのいずれも含まれていません。行に十分なスペースを割り当てたくない場合は、次を使用します。

int c;
while ((c = getchar()) != EOF)
    putchar(c);

これはユーザー コードで一度に 1 文字を読み取りますが、基礎となる標準 I/O パッケージが入力をバッファリングするため、それほどコストがかからず、プログラムをそのように実装することは完全に実現可能です。行で作業する必要がある場合は、行に十分なスペースを割り当てるか (私はchar buffer[4096];日常的に使用しています) getline()、.

そして、チャーリー・バーンズはコメントで尋ねました:

getline() がもっと頻繁に提案されないのはなぜですか?

getline()比較的新しく、まだどこでも利用できるとは限らないため、あまり言及されていないと思います。POSIX 2008 に追加されました。Linux および BSD で使用できます。他の主要な Unix バリアント (AIX、HP-UX、Solaris) についてはよくわかりません。自分で書くのは難しくありませんが (私はそれをやったことがあります)、移植可能なコードを書く必要がある場合 (特に「移植可能」に「Microsoft」が含まれる場合) は厄介です。そのメリットの 1 つは、読み取った行が実際にどれくらいの長さだったかがわかることです。

使用例getline()

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

int main(int argc, char **argv)
{
    char *line = 0;
    size_t length = 0;
    char const name[] = "/myFile/path/test.txt";
    FILE *file = fopen(name, "r");

    if (file == NULL)
    {
        fprintf(stderr, "%s: failed to open file %s\n", argv[0], name);
        return -1;
    }

    while (getline(&line, &length, file) > 0) 
        fputs(str, stdout);

    free(line);
    fclose(file);

    return 0;
}
于 2013-11-07T16:44:57.777 に答える
5

fgets行ごとに読み取るときに、改行文字を行末に保存します。これにより、実際に行が読み取られたのか、単にバッファが小さすぎたのかを判断できます。

puts印刷時に常に改行を追加します。

から改行を削除するfgetsか、使用しますprintf

printf("%s", str);
于 2013-11-07T16:45:08.637 に答える