前回 コマンドライン引数 プログラムを実行するときに、プログラムに対する引数(パラメータ)を 指定する事ができる => main 関数の引数と反映される main 関数から、コマンド引数の内容を参照できる main には、二つの引数 ( argc, argv ) argc : 整数型 引数の個数 + 1 を表している argv : argv[k] (k は整数値) k 番目の引数 (文字列) が参照できる ./p-001.exe abc 123 xxxxx argc => 3 (引数の個数) + 1 = 4 argv[1] => "abc" argv[2] => "123" argv[3] => "xxxxx" argv[0] => "./p-001.exe" argv[4] = argv[argc] => NULL ( <= 特別値 ) int main(int argc, char *argv[]) char *argv[] => (char *)argv[] => (char) *(argv[]) => argv[] が文字列を表している Hanoi のプログラム (C 言語の話でなく => アルゴリズムの話) 問題を解くために、再帰を上手に利用している cf. この講義では、再帰を繰り返しのために *のみ* 導入 => 再帰は、繰り返しより、表現力が高い Hanoi では、その表現力の高さを例示した... loop(arg) { if ( arg が最小 ) { なにもしない } else { 繰り返したい内容 loop ( arg をひとつ小さくする ) } } => loop によって、「繰り返したい内容」が繰り返される(arg サイズだけ) loop ( n ) => loop ( n - 1 ) => loop ( n - 2 ) => .. loop ( 0 ) :おしまい 線になる hanoi( size ) { hanoi ( size - 1 ); move() hanoi ( size - 1 ); } => hanoi では再帰が二度呼ばれる hanoi ( n ) => hanoi ( n - 1 ) => hanoi ( n - 2 ) hanoi ( n - 2 ) hanoi ( n - 1 ) => hanoi ( n - 2 ) hanoi ( n - 2 ) => 二分木 これまで 先々週までの内容で、基本、C 言語でのプログラミングに必要 内容は、一通り終わっている [本日の内容] 一周目に関して、いくつか落としている内容 => 落穂ひろいをする => できれば、今日から 2週目に... s_input.h/s_outpu.h の使い方 (API) プログラム作成時 ヘッダファイルはインクルードする #include "s_input.h" #include "s_print.h" => しばらくは、stdio.h と同じ扱い コンパイル時 cc の後ろに -I ~/c/include を追加する => s_input.h/s_print.h のある場所を指定 使えるようになる関数 s_print.h <= 出力関数 s_print_char char 型 : 文字の出力 putchar と同じ s_print_string 文字列の出力 printf と同じ s_print_int int 型 : 整数の出力 以前講義中でつくった整数出力関数 s_print_newline 改行の出力 putchar ( '\n' ) / printf ( "\n" ) と同じ s_input.h <= 入力関数 s_input_char char 型 : 文字の入力 getchar と同じ s_input_string 文字列の入力 s_input_int int 型 : 整数の入力 基本的なデータ型 ( 文字列[char *], 文字[char], 整数[int] ) の 入出力関数を紹介 関数の「返り値」 関数は、return 命令によって、途中で終了できる。 この時に、return 命令の後ろに「式」を書くと、 「式」の値(計算の結果)が、「関数の返り値」になる 「返り値」を持つ関数は、関数の前の void を、その値の型に する必要がある。 「返り値」もつ関数は、式の中で利用できる これまでと同様、「返り値」を持つ関数を、プログラムの一部の 呼び出しのために利用する(void の関数と同じ)に利用可能 => 「返り値」は、無視される 特に main 関数の「返り値」について 今まで : main には、必ず最後に return 0 をかいていた main の前は int と書いてあった => main 関数も返り値(整数値:int)を返す関数 普通の関数 他の関数から呼び出される(cf. main は、基本、そうではない) => 返り値も、他の関数に返されて、利用される main は、他の関数からよばれてない 引数は ... ? => コマンドラインから作られて、渡される(shell が渡している) 返り値は .. ? => コマンドに戻っている (shell に戻っている) shell で「$?」で参照する事ができる これは、「習慣的には」コマンド「エラー情報」を表すとなっている 特に 0 が返った場合は、「正常終了」、それ以外の場合はエラーコード(異常がおきて、 その詳細は、その値で区別する ) => これまで main で return 0 としてきたのは、「正常終了」という意味だった 特に、make では、コマンドの返すエラーコードが 0 でないと、 途中で終了する という規則になっているので、自分が作成したプログラムを make で利用する場合は、「return 0」(or もし、エラーあるなら、 「return エラーコード」) の記述が必須になる。 関数の副作用と実行順序 返り値を持つ関数は、式の中で利用できる f(x) = x^2, g(x) = x + 1 例 : f(2) + g(3) => 2^2 + 3+1 => 4 + 4 => 8 例 : f(2) + g(3) => 2^2 + g(3) => 4 + g(3) => 4 + (3+1) => 4 + 4 => 8 式の評価(値の計算)には順序がある 式の値には(今、皆さんが学んでいる範囲では..)評価順序は無関係 C 言語の関数では(数学の関数にない)副作用がある 副作用 : 関数の値とは無関係な作用 !! 副作用を考える、評価順序をきちんととらえる必要がある 式の中の関数は、左から右に評価 関数合成は、内から外 f(g(x)) => g();f() 引数が複数あるときには、左から右に評価される。 h(x,y) = x * y h(f(2),g(3)) => g(3), f(2), h(4,4) 現時点で、副作用としっているのは 出力と入力の二種類だけ