とらりもんHOME  Index  Search  Changes  Login

とらりもん - ファイルの入出力 Diff

  • Added parts are displayed like this.
  • Deleted parts are displayed like this.

<[[C言語入門]]に戻る>

 [[C言語入門2. 繰り返し処理]]で, 出力を画面に出すかわりに, リダイレクトによってファイルに出力することができた。このように, Unixの上でプログラミングをしたり解析したりするときは, データの入出力にリダイレクトを活用するのが合理的である。なぜなら, リダイレクトはすなわち標準入出力とのやりとりなのだから, 他の標準入出力の機能の利用, 特にパイプによって複数のプログラムと結合できるからである。

 しかし, 標準入出力を介さずに直接ファイルにデータを書き込んだりファイルからデータを読み込んだりしたいこともよくある。特に, 複数のファイルからデータを読んだり複数のファイルへ出力したりは, 標準入出力では実現できない。

 ここでは, 標準入出力を介さずに, じかに特定のファイルとデータをやりとりする方法を学ぼう。例として, 0から9までの整数を出力するプログラムを考える:

    /* number.c */
    /* 2008/07/15 K. Nasahara */
    # include <stdio.h>

    int main()
    {int i;
     for (i=0; i<10; i++) printf("%d\n", i);
    }

このプログラムをコンパイルして実行したら, 画面に0から9までの数字があらわれる。これをファイルにリダイレクトすれば, 0から9までの数字が並んだテキストファイルができる:

$ ./number > result.txt

しかしここでは, このプログラムを改造して, 直接, out.txtというファイルに出力してみよう。改造箇所は, mainの部分であり, 以下のようにしてみよう:

    int main()
    {int i;
     FILE *fp;
     fp=fopen("out.txt", "wt");
     for (i=0; i<10; i++) fprintf(fp, "%d\n", i);
     fclose(fp);
    }

これをコンパイルし, 実行すれば, out.txtというファイルができて, その中には0から9までの数字が書き込まれていることがわかる。

上の改造箇所を解説しよう。まず, ファイルを扱うには{{fontc(ファイルポインタ, red)}}というものを用意する必要がある。ファイルポインタはプログラム内における, ファイルの分身みたいなものである。プログラムの中でデータをファイルに書き込みたいときは, そのファイルのファイルポインタを指定して「そこに書け」と命ずる。何かをファイルから読み込みたい時も, そのファイルのファイルポインタを指定して「そこから読め」と命ずるのだ。

そのファイルポインタを用意しているのは, 上の改造箇所の
    FILE *fp;
    fp=fopen("out.txt", "wt");
という2行である。

FILE *fp; で, fpという名前で「ファイルポインタ型変数」がひとつ用意された。このへん, 今はあんまり深く意味を考えなくてよい。FILEはなんで大文字?, *はどういう意味?などの疑問はそのうちわかるので今はスルーしよう。

次の行の, fp=fopen("out.txt", "wt");で, fpというファイルポインタにout.txtという名前のファイルが対応づけられた。以後, このプログラムの中ではout.txtというファイルはfpというファイルポインタで扱われる。"wt"は, 「テキストデータを書き込む」というモードの指定である。

その次の
    for (i=0; i<10; i++) fprintf(fp, "%d\n", i);
という行では, データを実際にファイルに書き込んでいる。fprintfはファイルを相手にした"printf"のようなものである。fprintfの第一引数は出力先のファイルポインタである(ここではfp)。

その次の
    fclose(fp);
は, ファイルへの出力が終わったことを宣言している(実体としては, ファイルポインタを解放している)。

!!標準入出力のファイルポインタ

 実は, 標準入出力も, 一般のファイルと同じように, Cプログラムのなかでファイルポインタで指定することで, あたかもファイルのようにあつかうことができる。標準入力のファイルポインタはstdin, 標準出力のファイルポインタはstdoutである。これらは宣言したりfopen, fcloseなどをする必要はない。

'''課題6-1''' 上のプログラムで, fprintfの中のfpをstdoutにかえてコンパイル・実行してみよ。

'''質問''': 「あたかもファイルのようにあつかうことができる」とはどういうことでしょうか?

'''回答''': 標準入出力は, (通常は)ディスプレイやキーボードからの入出力です。それを, ファイルへの入出力と同様のやりかたで実現できるということです。課題6-1をやってみてください。それでどういうことかわかるでしょう。

'''質問''': 画面に0から9までの数字があらわれました。ファイルへの入出力のやり方で標準入出力を行うということでしょうか。

'''回答''': そういうことです。特定のファイルに紐付けられたファイルポインタをfprintfの中で指定するとそのファイルに書き込まれますが, stdoutというファイルポインタをfprintfの中で指定すると標準出力に書き込まれる(つまりディスプレイに表示される)わけです。

 printfやscanfを使えば, わざわざ標準入出力のファイルポインタなどを使わなくてもいいじゃないかと思うかもしれない。それはそのとおりである。しかし, Cの関数として, バイナリファイルを入出力する, freadやfwriteという関数があり, これらは画像解析や偏微分方程式の解析などで非常によく使われるが, これらの関数は, 必ずファイルポインタを指定しなければならない。そのような関数に対して標準入出力を割り当てる場合に, stdinやstdoutというファイルポインタが欠かせないわけである。

 ファイルポインタという概念は, C言語やC++言語で大変重要であり, pythonにも似た概念がある。衛星画像の解析では大量のファイルを扱うので, ファイルポインタと友達になる必要がある。

!!参考になるサイト
ポインタがよくわからない人は[[ここ|https://www.cc.kyoto-su.ac.jp/~yamada/programming/pointer.html]]を見よう。

<[[C言語入門]]に戻る>