第11回 ファイル操作2(6月30日)

今日の課題

■ メモリの書き出しと読み込み

カーソル型線型リストや画像ファイルは、データが連続したメモリ上に存在する。連続したメモリ上の値をファイルに書き出すには、 fwrite 命令が便利である。逆にファイルから連続領域に読み込むには、 fread 命令が便利である。

fwrite 引数は次の3つ。(メモリの先頭を指すポインタ, データ1つぶんのバイト数, データ数, 出力先)

fread 引数は次の3つ。(メモリの先頭を指すポインタ, データ1つぶんのバイト数, データ数, 入力元)

(例)カーソルリストをセーブするサブルーチン

void list_save(List *lst, FILE *fp)
{
  fprintf(fp,"%d %d %d\n", lst->max, lst->free, lst->head);
  fwrite(lst->nodes, sizeof(Node), lst->max, fp);
}

最初の fprintf はヘッダ部の出力である。次の fwrite はノードの配列の出力である。

上記は、先頭ノードがダミーでない場合の例である。ダミーノードを用いるには lst->head および それに対応する %d を削除すればよい。

□ 課題1

カーソル型線型リストのデータをロードするサブルーチンを作成せよ。そして、セーブとロードの動作確認をせよ。

■ 1文字入力と返却

fgetc ファイルから1文字入力する関数。返り値が EOF のときは、ファイルの終端、または、エラーを表す。

ungetc 入力した1文字をファイルに返す。たとえば、ファイルの入力時に1文字先を見て処理を判断することに有効。

サンプルプログラム ⇒ list1101.c   ⇒ data1

実行方法: gcc list1101.c; ./a.out

■ ファイルアクセスの位置指定と位置検出

ftell 現在参照しているファイルの上の位置を求める関数

fseek ファイルの参照位置を定める関数

(例)ファイル「data2」の中の最初の「@」の位置を調べる ⇒ list1102.c   data2

(例)ファイル「data2」の指定位置から3文字を表示する ⇒ list1103.c

list1102.c の実行結果から得た値を使って、list1103.c を実行してみよう。

□ 課題2

「data3」のシリーズは、次の書式のデータファイルである。

「非数値文字列1」、「数値文字列1」、「非数値文字列2」、「数値文字列2」、「非数値文字列3」、「数値文字列3」、「非改行文字列1」、「改行」
※ 「非数値文字列1」や「非改行文字列1」は省略される場合がある。
※ 「非数値文字列」の中に「#」があるならば、その位置から「改行」までを「非数値文字列」とみなす。

このファイルから、数値とファイル位置を抽出し表示するプログラムを作成せよ。ここでファイル位置とは、上記フォーマットの「改行」の次の部分のファイル位置である。プログラムのサンプルを示す。 ⇒ prac1101.c

データファイルの例をここに示す。⇒ data3a data3b data3c data3d

正しく動作するとそれぞれ以下の表のように出力される。
data3a data3b data3c data3d
100 100 100 100
200 200 200 200
300 300 300 300
19 12 27 39

◇ ヒント

ignore_line() 非改行文字を読み飛ばし、最後に改行を読み飛ばす。つまり、入力の1文字が '\n' でない間、入力を続ける。

skip_to_num() 数の文字のところまで読み飛ばす。つまり、入力の1文字が数字になるまで読み飛ばし、最後に数字を戻す。これができたら、「#」を考慮したプログラムを作ろう。

get_num() 数の文字を1つ読むと、その時まで読んだ数を 10 倍して加算する。たとえば、「1」を読んだ状態では「num=1」であり、加えて「2」を読むと全体で「12」と読んだことになる。「num = num * 10 + 2 = 12」という計算をする。さらに「3」を読むと全体で「123」である。これは「num = num * 10 + 3 = 123」という計算をする。「'3'」を「3」に変換するには「'3' - '0'」とすればよい。

■ 宿題

課題1は、「ロードの部分」を提出せよ。課題2は、プログラムを完成させ、各行にコメントを手書きして、提出せよ。また実行結果も提出せよ。来週(7月7日)の授業開始時に集めます。

2005.6.28 by tokuhisa