「関数」という考え方 「関数の定義」とは(What) ? 「プログラムの一部」に「名前」を付ける事 「名前」を「関数名」と呼ぶ 「プログラムの断片」を「関数の本体」と呼ぶ 関数をどうやって利用する(How to) ? 「関数名」を指定するだけで「関数本体」が実行される(関数呼出し) !! 関数呼び出しをする部分で実行する命令を、 !! 関数定義と関数呼び出しに置き換えている !! <= 置き換える前の状況を考えると、 !! 関数の定義はなくても、目的(プログラムの実行結果)が実現できる !! => 関数がなくてもよいのでは ?? 関数を定義する理由は (Why) ? 「プログラムの断片」に「名前」が付けられるので、分かり易い もちろん、「断片の内容に対応した分り易い名前をつければ..」だが.. # 名前つける機会(権利)が与えられる # => 機会をつかみ、権利を行使して、良い名前を付けて欲しい 「関数名前」を指定するだけで「関数本体」が実行される 何度も「同じ事」をする場合に便利(プログラムが短くなる) 記述が増えると「同じ」である事を保証するコストが大きくなる 関数を定義する => 関数名が同じなら、それに対応する本体も同一 => 本体同士の比較より、関数名の比較の方が(普通..)簡単なので.. 関数定義(とその関数の利用により..) 同一性のチェックが楽になる 「引数」を利用する事により「色々な断片」を「一つの関数本体」にまとめられる 複数のプログラムの断片があり、一部だけが異なる場合、 「変数」を導入する事により、同一化できる => 引数付き関数を導入する <= コピペじゃいけないのか ?? => コピペで問題が解決できるのでは ?? => コピペをすると、 もし、そのコピー元に誤りがあったら、 コピー先にも誤りを作る事になる 「コピペ」がバグの増殖を促す 関数を作る事によって、 バグの『増殖』を防ぐ事ができる 一箇所の「関数本体」を直すだけで、多数の場所の命令を直す効果がある 「関数」の表現方法 具体例: 関数定義 void printHello(void) { printf ( "Hello, World\n" ); } int main(void) { printHello(); /* 関数呼び出し */ } 関数定義(の文法) 「関数定義」は、「関数頭部」と「関数本体」に分けられる 例: 関数頭部 「void printHello(void)」 関数本体 「{printf ( "Hello, World\n" );}」 「関数頭部」は、「関数の値の型宣言」「関数名」「仮引数変数宣言」に分けられる 例: 関数の値の型宣言 「void」 関数名 「printHello」 仮引数変数宣言 「(void)」 「関数宣言」は、void(これまで)/int(main だけ) 「関数名」は、自由に决めて良い(他と重複すると駄目だが..) 「仮引数宣言」は、「(」+「仮引数宣言並び」+「)」 「仮引数宣言並び」は、 「void」 引数がない場合 か、 「char *変数名」のカンマ(,)区切 => 引数の個数だけ並べる ( , は引数の区切り記号 ) 「関数本体」は、「{」+「命令列」+「}」 関数呼出し(の文法) 「関数呼出し」は、「関数名」+ 「実引数並び」 例 関数名 printHello 実引数並び () 「実引数並び」は、 '()' 引数がない場合 か、 '(' + 「式」のカンマ並び + ')' => それぞれの式を計算した値が、対応する 仮引数変数の値になる !! 仮引数変数の個数と実引数変数の個数は一致している必要がある !! => 一致していないと「(コンパイル)エラー」になる 文字を引数に持つ関数と型宣言 これまでの関数 引数がないか、文字列を引数としていた 「char *」をお呪いとし、関数を呼び出す時に、文字列を指定 => printf 関数 (引数として文字列を取る) これまでの(自作した..)関数は、引数(文字列)を、 基本、そのまま、他の関数の引数に与えていた 例: printf, strcmp 例外 : putchar 関数 : 引数が「文字」(「文字列」ではなく) 「文字」を引数に持つ関数の場合 仮引数変数宣言のところを「char」とする必要がある 型宣言(データの種類) 「char *」/「char」は実は、「引数の型」を表現していた 「char *」は「文字列」 「char」は「文字」 !! => 一般論として、変数に入るデータの種類(型)を、仮引数変数宣言で指定する !! 呼び出しの時も、その型の実引数を与える 変数に、その型と異る型の値を入れようとすると「エラー」になる C のプログラムで扱うデータの型は(基本)文字列 => 一種類の型しか扱っていない <= 複数の種類の型を利用する 「型」の違いを意識する必要がある 「型」= <「値の取りうる範囲を表す集合」、「その値を利用する演算の集合」> 例: 小学校で学ぶ、「整数」=> < { 0, +1, -1, +2, -2, .. }, { +, -, *, / } > 「3 次元ベクトル空間」=> < { (x,y,z) | x, y, z 実数 }, { 定数倍, 和 } > 「値の集合」と「演算」 データを処理する時に、 そのデータの型がわからないと そのデータの処理(演算の適用)ができない => 常に「データの『型』」を意識する必要がある 「文字」に 「1 を加える」と、「次の文字」 「文字列」に 「1 を加える」と、「短くなった文字列」 同じ「1 を加える」という「演算」でも、「意味」が異る 「演算」と「型」は「一組」で考える必要がある