Download presentation
Presentation is loading. Please wait.
1
情報処理Ⅱ 2007年1月26日(金)
2
本日学ぶこと ファイル入出力,標準入力・標準出力 記憶域管理関数(mallocなど) 問題
ファイルを入力にとり,先頭に行番号をつけて出力できる? 標準入力(キーボードなど)からの入力に対して,先頭に行番号を右揃えでつけて出力できる?
3
ファイルとは(復習) 補助記憶装置に保存する単位となる,データの集まり. プログラムが終了しても,内容が保持されるデータ構造.
(比較)変数の値はメモリ上にあるため,プログラム終了時に破棄される. コンピュータの電源を切って入れ直しても,保持されていることが多い. ストリームと呼ばれるバイト列として,読み書き可能. バイト列とは? char配列で表現できるデータ構造. '\0' で終わるものではなく,途中に '\0' があってもいいという点が,文字列と異なる.
4
ファイル操作のライブラリ関数(復習) 操作対象(関数への入力)は,ファイルポインタ. ライブラリ関数
stdio.h で定義されているFILE型のポインタ. 例: FILE *fp; ライブラリ関数 fopen : ファイルを開き(プログラムから使えるようにし),ファイルポインタを返す. fgets : 指定されたバイト数(文字数)を読み出す. fprintf : printfと同様の形式で,ファイルに出力する. fclose : 開いたファイルを閉じる(プログラムから使えないようにする). fgetc : 1バイト(1文字)読み出す.
5
行番号問題1 仕様 コマンドライン引数(複数ある場合は最初のみ)をファイル名とみなして,そのまま出力していく.ただし行の先頭には行番号をつける. 考え方 fgetcを用いて1バイトずつ読み出す. 「行の先頭」とは,「ファイルの先頭」か「改行文字('\n')の直後」のいずれか. 「今何行目を読んでいるか」を保存する変数line_countを用意する.
6
1文字ごとの読み出し(1) while ((c = fgetc(fp)) != EOF) {...} 'a' 'b' 'c' '\n'
これがストリーム ファイルabc プログラムの 内部状態 'a' 'b' 'c' '\n' FILE オブジェ クト fp '\0'がない点に注意 (文字列ではない) c = ??? 'a'
7
1文字ごとの読み出し(2) while ((c = fgetc(fp)) != EOF) {...} 'a' 'b' 'c' '\n'
プログラムの 内部状態 'a' 'b' 'c' '\n' FILE オブジェ クト fp c = ??? EOF '\n'
8
EOF(1) 「ファイルの終わり(End Of File)」を表す定数.
stdio.hで,#define EOF (-1)などと定義されている. unsigned char signed char ASCII (7ビット) -128 -1 127 255 EOF ヌル 文字
9
EOF(2),ファイルアクセス 文字(バイト)単位で読み書きするとき 文字列単位で(何バイトか一括して)読み書きするとき
int型を使用する. signed char型だと,255をEOFと区別できない. unsigned char型だと,EOFが来ても255にしてしまう. EOFから255までの「257種類の値」は,char型(signed char型,unsigned char型)で区別できない! 読み出してEOFが来たら,そこでおしまいにする. ライブラリ関数はfgetc, getcharなど 文字列単位で(何バイトか一括して)読み書きするとき char配列またはchar*型を使用する. ライブラリ関数はfgets, freadなど
10
標準入力と標準出力 標準入力(standard input, stdin) 標準出力(standard output, stdout)
通常はコンソール入力(キーボード入力) 標準出力(standard output, stdout) 通常はコンソール出力(画面表示) シェルのリダイレクション機能を用いて変更可能. 実行例: find ~ > files 実行例: ./liner < /usr/share/dict/words シェルのパイプ機能を用いて,あるプログラムの標準出力と別のプログラムの標準入力を接続できる. 実行例: echo '1+2*3' | bc
11
標準入力・標準出力とコンソール 実行環境 (OSなど) 標準入力 実行プログラム コンソール 'a' 'b' 'c' '\n' 'a'
$ ./liner abc 1: abc $ 'a' 'b' 'c' '\n' '1' ':' ' ' 標準出力 実行コマンド 入力(エコーバック) 出力
12
標準入力に関するライブラリ関数 int getchar(void); char *gets(char *s);
標準入力から1文字(1バイト)読み込む. 戻り値はunsigned char型の値,もしくは定数EOF. char *gets(char *s); 標準入力から1行読み込み,sの指す領域に格納する. 1行が,sの領域サイズよりも大きいとしても,そのまま格納しようとする. int scanf(const char *format, ...); formatに従って標準入力から入力を読み込み,第2引数以降が参照する領域に格納する. 読み込みに失敗すれば,入力が進まない. なるべく使わない! なるべく使わない!
13
標準出力に関するライブラリ関数 int putchar(int c); char *puts(const char *s);
cをunsigned char型に変換した上で,標準出力に(1文字)書き出す. char *puts(const char *s); 文字列sと改行文字を標準出力に書き出す. int printf(const char *format, ...); formatに従って標準出力に書き出す. 「標準出力に書き出す」の主語は,それぞれのライブラリ関数である. 「画面に表示する」ではない. ただし,「画面に表示される」というのは,利用するプログラマの観点とした表現であり,これは差支えない(利用する状況にも夜が). 「書き出す」「読み出す」はそれぞれ,「書き込む」「読み込む」と表現されることもある.
14
標準入出力と標準入出力関数 標準入力・標準出力に対する関数は,標準入出力関数およびstdin, stdoutを用いた関数形式マクロにより定義されている(ことがある). 例: #define getchar() getc(stdin)
15
行番号問題2 仕様 考え方 標準入力から入力をとり,そのまま標準出力に書き出す. ただし行の先頭には行番号を右揃えでつける.
読むのはgetchar(文字ごと),書くのはprintf(行ごと). すべての入力を終えた時点で,行数が確定し,そこから出力する. 入力内容を行単位で保存する. 標準入力は後戻りができない! 実行開始時に行数はわからないので, 「記憶域管理関数」を使用する. 「標準入力から入力し」と書いてはいけない. 一般に,入力「する」のはプログラムではないから. 一方,「出力する」と書くのは,その主語はプログラムなので,問題ない. ただし「標準出力に出力する」と表記すると,「出力」が2箇所出現してくどいので, 「標準出力に書き出す」とここでは書いた. なお,「画面に表示する」という表現がよく見られるが,これも,画面に表示「する」のは プログラムではないので,その意味では不適切であるが,古くから用いられ,また オンラインマニュアルの日本語訳でもよく見かけるので,「表示する」と書いて 試験で減点するようなことはしない.
16
liner.cの概要(1) 定義した構造体 定義した関数 line:1行の文字列の情報 line_array:行単位で分割した入力の情報
いずれも,「本体(具体的な中身,コンテンツ)」と「確保した要素数」と「格納されている要素数」をメンバに持つ. 定義した関数 get_line_array:入力を読み出す get_line:1行読み出す put_lines:行番号を付けて出力する get_digit_width:桁数を求める
17
liner.cの概要(2) 「右揃え」の出力方法 ライブラリ関数printfの補足 printf("%*d: ", width, i);
iの値を,width文字分の右揃えで出力する. width=3, i=10なら," 10: "が出力される. 「*」を用いて,実行時に桁数を指定できる. ライブラリ関数printfの補足 様々な変換規則を持つ. 可変引数関数である. ファイルへ出力はfprintf, 文字列に書き出すのはsprintf
18
実行時の領域確保について プログラム実行時(main関数に制御が移る前)に ブロック({...})が実行されるときに
static変数のオブジェクトが確保,初期化される. プログラム終了時に破棄される. ブロック({...})が実行されるときに auto変数のオブジェクトが確保される. ブロック終了時に破棄される. 記憶域管理関数(malloc, callocなど)を呼び出すと オブジェクトとして使用できる領域が確保される. freeなどの関数が呼び出されるか, プログラム終了時に破棄される. スタック領域 mallocは,リストやツリーのプログラムをCで書くときに必要になる. 例えば,ノード(節点)を自己参照構造体で定義し,新たなノードを作るときに,mallocなどでその構造体オブジェクトを生成するのである. ヒープ領域
19
mallocの基本的な使い方 準備 p = (int *)malloc(sizeof(int)); ⇒ *p がint型変数として利用可能.
#include <stdlib.h> int *p; p = (int *)malloc(sizeof(int)); ⇒ *p がint型変数として利用可能. p = (int *)malloc(sizeof(int) * 10); ⇒ p[0], ..., p[9] がint型変数として利用可能. 必ずポインタ型 (intの部分は用途による) p p[0] p[1] p[9] … sizeof(int) *10 バイトの領域
20
malloc使用の注意点 領域の値は不定であるため,必要に応じて初期化する.代わりにcallocを使用すれば,すべて0に初期化された領域が得られる. 代入される変数はポインタ変数なので,左辺値になり得る(p++; などとできる). 領域確保に失敗するとNULLを返すので, if ((p = (int *)malloc(sizeof(int) * 10)) == NULL) { エラー処理 } などとするのが一般的.
21
可変長配列 可変長配列の例 可変長配列をCで取り扱うときは, 実行時にその個数(の上限)がわからないような配列
行番号問題2では,「1行の文字列」と「標準入力より獲得する入力(文字列の配列)」が該当する. 可変長配列をCで取り扱うときは, mallocまたはcallocで初期化し, より大きな領域が必要になったら,reallocを用いるとよい.
22
後始末 ファイルの読み書きを終えたら,fcloseを用いる. ヒープ領域の内容を解放するには,freeを用いる.
「fopen/fclose」をペアで覚える. fcloseを呼び出す前のファイルの出力内容は,プログラム内に保持されている(バッファリング)可能性がある. プログラム終了時に,閉じられていないファイルは保存されるが,これに頼らない(積極的にfcloseを用いる)ほうがよい. ヒープ領域の内容を解放するには,freeを用いる. 「malloc/free」をペアで覚える. プログラム終了時に,freeされていない領域も破棄される.基本的に,これに頼ってよい(積極的にはfreeを用いない).
23
まとめ ファイルは,実行プログラムとは異なる生存期間を持つ,バイト列のデータ構造である.
ファイル,標準入力,標準出力にアクセスするためのさまざまな標準入出力関数が存在する. 実行後のオブジェクト確保には,mallocなどを用いる. 後始末を忘れずに.
24
プログラミング講義を終えて(1) 授業内容の関連 難しかったテーマを復習するときは,関連する(一つ前や後の)テーマを見直すのもよい. 構造体
入出力 ライブラリ関数 再帰呼び出し その他の型 前処理指令 関数 変数の有効範囲 (新設) 記憶域管理関数 (名称変更) 算術型⇒算術型・型変換 ファイル入出力⇒入出力 制御文 演算子 ポインタ 記憶域管理関数 識別子 算術型・型変換 配列・文字列
25
プログラミング講義を終えて(2) 2年以降で身につけてほしいこと 自在にCでプログラミングできる能力
特に,ファイル処理,文字列処理,リストとツリー,スタックとキュー 「先人の知恵」を学び活用する能力 ライブラリ関数,先生・先輩のノウハウ プログラムを設計する能力 与えられた課題に対して,何をすべきかを自主的に決め,プログラムコードや文章で表現すること
26
今後の日程 1月31日(水):金曜の授業だが,当科目は実施しない. 2月2日(金):おさらい問題 2月9日(金):試験
11月8日に補講実施済のため. 2月2日(金):おさらい問題 何でも持ち込み可.相談可.成績には関係ない. 5分復習問題,40分おさらい問題,45分解説 2月9日(金):試験 80点満点 自筆ノート1冊と,C言語の教科書1冊の持込可
Similar presentations
© 2024 slidesplayer.net Inc.
All rights reserved.