計算機言語 II 第 9 回 ファイルポインタ入門 , その 2
http://www.math.u-ryukyu.ac.jp/~suga/gengo/2018-2/09.pdf
1
ファイルポインタ前回述べたことの要約です.
• /usr/include/stdio.hにファイル型の構造体FILE が定義されている.
• プログラムでファイルの読み書きをするには, FILE型へのポインタを用いるライブラリ関数を利用 する.
• ファイルを利用する前に, fopenを利用してファイルを開く必要がある.
• ファイルの利用を終えた際には, fcloseでファイルを閉じる. これにより,バッファリングされた書き 込みを実際にファイルに書き込むという動作(Flush するという)をOSが実行する.
• プログラム終了時には,fcloseが自動的に起こるが,
– 開けるファイル数の上限が決まっていることがあり,環境によっては, あまり大きな値でないこと もある.
– 終了時では, Flushの際のエラーのリカバリができない.
の理由により, プログラム内で明示的にfclose を呼ぶ方が好ましい. きちんとしたプログラムなら, fcloseでエラーが起きないかをチェックする.
• fopen を呼ばなくても自動的に開いているファイルが3つあり,それらは,標準入力(stdin), 標準出力 (stdout), 標準エラー出力(stderr)である.
上の標準出力,標準エラー出力の使い分けですが,パイプやリダイレクトの仕組みを考えると.
• プログラムからの出力は, 標準出力へ,それ以外のメッセージは全て標準エラー出力へ
というのが正しいプログラミングスタイルです. 教科書は, printfを利用して全て標準出力に出しています が,これは感心しません.
fprintf(), fscanf()
ファイルに対する文字データの読み書きの基本的な2つのライブラリ関数です. 第一引数に, FILEへのポ インタを代入し,読み書きをするファイルを指定します. printf(), scanf()は, それぞれ標準出力,標準入 力にファイルが固定されているライプラリ関数です. すなわち,
fprintf(stdout, ....) = printf(...)
1
fscanf(stdin, ... ) = scarf(...)
が成立します. 標準エラー出力への出力は, fprintf(stderr, ...);
の形になります. 今後この講義では,プログラム出力以外の全てのメッセージは,標準エラー出力に出します. 例えば,教科書 p. 337, List 13–2では,最初の if文のあとの出力は,
fprintf(stderr, "ファイルをオープンできません\n");
と書くべきです.
printf(), fprintf(), scanf(),fscanf()等は,int値を返す関数で, 返り値は「関数の実行において成 功した値の個数」です. 教科書では, List 13–2で初めて利用していますが,本来はどのようなプログラムでも 利用すべきものです. 特にscanf()は,想定外の入力のリカバリが面倒なことで知られているので,この返り 値は積極的に利用すべきものです.
時刻
教科書List 13–3 は時刻をファイルに書き出すプログラムです. そこで用いられているライブラリ関数につ
いては,manコマンド man 3 time man 3 localtime
でどのようなものかを知ることができます. UNIX(Linux)では,時刻は, 1970年1月1日0時0分0秒を起 点として,time_tという変数型に秒数が記録されています.
古いシステムでは,time_tが32ビットint型(符号付)となっていたため, 2038年に秒数が232−1を超 え,時刻の値が負数となって,システムのエラーが起きます. この古いtime_tを用いたシステム(やプログラ ム)がどの程度残っているかというのがわからず, 2038 年に色々なシステムが止まってしまうのではいか? と の予想があります. これは「2038年問題」と呼ばれています.
time_t型を人間が使いやすい時刻の構造体に変換するライブラリ関数がいくつかあり, List 13–3では localtimeという関数が利用されています. localtimeは/usr/include/time.hで定義されている構造体 tmへのポインタを返します. (ここでも,構造体のコピーは遅くなるという原則が適用されています.)
struct tm *timer = localtime(¤t);
これは, tm型へのポインタ変数としてtimerが定義され,初期値に関数localtime() での返り値が与えられ ています. 構造体tmの実体の確保は,関数localtime()が実行します.
構造体tmについては, 教科書 p. 340のColumn 13–1 を読んでください. 教科書 p. 339, List 13–3, p.
340, List 13C–1, p. 323, List 13–4 をコンパイル, 実行してみてください. List 13C–1 はUnix(Linux)の dateコマンドの簡易版です.
教科書p. 344–346 では,データをコピーするプログラムがあります. しかしこれらは, ファイルデータをそ
のまま別のファイルにコピーするだけです.
2
Unix(Linux)のcpコマンドは,内容以外に,ファイルのアクセス権や実行権,ファイル所有者の変更等も行 いますので, 単にデータコピーをしているだけではありません. ただし,データのコピーの部分だけは,教科書 にあるものと本質的に同じことを行なっています.
2
次回の予告次回は, バイナリファイルの読み書きを述べた後,「動的なメモリの確保」について述べます. 教科書の p.
348–351にある例は, 17桁程度しか精度のないdouble型変数に20桁を超えるπの値を代入するという時点
で,「全く意味を持たない例」ですので, 飛ばします. 最後のファイルのダンプを解説して,この教科書を終え る予定です.
教科書を終えた後は,
奥村晴彦著, 改訂新版C言語によるアルゴリズム辞典,技術評論社 の行列計算の部分p. 48, matutils.cを解説します.
https://github.com/okumuralab/algo-c/blob/master/src/matutil.c
レポート問題
:
締め切り12
月13
日(
木)
送り先は, [email protected] 1. 教科書,演習13-4.件名: Enshu 13-4.
テキストの置き場所: ftp://ftp.math.u-ryukyu.ac.jp/pub/gengo/2018-2/
3