3. 関数 3.1 関数関数は数学の関数と同じようなイメージを持つと良いでしょう 例えば三角関数の様に一つの実数値 ( 角度 ) から値を求めますし 対数関数の様に二つの値から一つの値を出すものもあるでしょう これをイメージしてもらえば結構です つまり 何らかの値を渡し それをもとに何かの作業や計算を行い その結果を返すのが関数です C 言語の関数も基本は同じです 0 cos 1 cos(0) = 1 2 4 log 2 log 2 4 = 2 まず 簡単に関数の記法です return は途中にあってもよく その場合はそれ以降は実行されません 関数の戻り値の型関数名 ( 型 1 仮引数 1, 型 2 仮引数 2,...) { 宣言と文 return ( 変数 ); 一つの例として 一の位の数字を返す関数を作ります ex19.c /* 一の位の数字の関数 */ int lastdigit(int n); /* プロトタイプ宣言 */ printf(" 整数を入力してください :? "); scanf("%d",&x); printf("%d の一の位の数字は %d です \n", x, lastdigit(x)); /* 戻り値の型が int 型 引数が int 型の関数 lastdigit を宣言 */ int lastdigit(int n) { return (n % 10); 13
応用プログラミング I II 2014.12.1 ここで int lastdigit(int n){ の部分が関数を定義している部分 lastdigit (x) が関数を呼び出す部分です 定義する部分で括弧の中にある変数を仮引数といい 呼び出す側で括弧の中にある変数を実引数といいます 実引数の値が仮引数に渡されて 関数の中で使われます ところで 関数の定義は最後にあります つまり lastdigit(x) と関数を呼び出す段階では lastdigit 関数の型や引数の数や型などがわかりません したがって この関数の呼び出しが正しいかどうかの判断ができないのです そこで プロトタイプ宣言をおこなって 関数の型や引数の型をあらかじめ教える必要があります 使う時点で関数が定義されていない場合はプロトタイプ宣言をするのが原則です ところでこのプログラムの main の部分を見てみましょう printf(" 整数を入力してください :? "); scanf("%d",&x); printf("%d の一の位の数字は %d です \n", x, lastdigit(x)); ここの int main(void) も実は関数だったのです つまり 関数の名前は main 引数はない(void はないことを表す特別の型 ) 戻り値は int 型である関数を定義していたのです C では実行の際には必ず main 関数が呼ばれるのです 逆に言えば main 関数がなければ C のプログラムは実行できないということなのです さらに 少し考えてみましょう ここでは printf を使っています この printf は形からわかるように関数です では この関数はどこで定義されているのでしょうか? 残念ながらどこでも定義されていません では どこかでプロトタイプ宣言されているのでしょうか? 一見ではどこにもプロトタイプ宣言がされていないように見えますが 実はきちんとプロトタイプ宣言がされているのです 実は の部分ではヘッダーファイル stdio.h は読み込むという命令で このヘッダーファイルの中に標準で用意されている関数のプロトタイプ宣言が書かれているのです そのため 関数の型や引数の型がチェックすることができ ゆえに関数を利用することができるのです 関数の実態は ライブラリという形で ( すでにコンパイルされて ) ハードディスクに入れてあります この関数を使うためにプロトタイプ宣言されたヘッダファイルを読み込むわけです もし ヘッダーファイルを読み込まなかったら エラーが起きることになります 14
もう少し簡単な例を出します ex20.c /* 2 乗を計算する関数 3 乗を計算する関数 */ int sqr(int n); /* sqr 関数のプロトタイプ宣言 */ int cub(int n); /* cub 関数のプロトタイプ宣言 */ int x, y; printf(" 整数を入力してください :"); scanf("%d",&x); y = sqr(x); printf("%d の 2 乗は %d です \n", x, y); printf("%d の 3 乗は %d です \n", x, cub(x)); printf("%d の 4 乗は %d です \n", x, sqr(y)); printf("%d の 5 乗は %d です \n", x, y * cub(x)); printf("%d の 6 乗は %d です \n", x, cub(sqr(x))); printf("%d の 8 乗は %d です \n", x, sqr(sqr(y))); printf("%d の 9 乗は %d です \n", x, cub(cub(x))); /* sqr 関数の定義 */ int sqr(int n) {/* 戻り値の型が int 型 引数が int 型の関数 */ return (n * n); /* cub 関数の定義 */ int cub(int n) {/* 戻り値の型が int 型 引数が int 型の関数 */ return (n * n * n); ここのように 関数の結果を変数に入れて利用しても良いですし 関数の括弧の中に関数の呼び出しを書いてもかまいません 3.2 複数の引数をもつ関数引数の数は1つだけでなく複数あってもかまいません その場合は, を間において仮引数を必要な数だけ並べます 呼び出す側でも 実引数をその数だけ並べなければなりません また 関数の中で 変数を宣言したり if 文や for 文も利用できます 15
ex21.c /* べき乗を計算する関数 */ int power(int m, int n); /* プロトタイプ宣言 */ int x, y; printf(" 整数を入力してください : "); scanf("%d", &x); printf(" 何乗を計算しますか :"); scanf("%d", &y); printf("%d の %d 乗は %d です \n", x, y, power(x, y)); /* power 関数の定義 */ int power(int m, int n) { int i, x = 1; for(i = 0; i < n; i++) { x *= m; return (x); 3.3 文字の関数 文字も数値でしたから 関数を作ることもできます ex22.c /* 文字の関数 */ int kind(char c); /* プロトタイプ宣言 */ char lower(char c); char c; printf(" 文字を入れてください : "); scanf("%c", &c); x = kind(c); printf(" 種類 =%d\n", x); if(x == 1) { printf(" 小文字に直すと %c\n", lower(c)); 16
/* kind 関数の定義 */ int kind(char c) { if(c >= '0' && c <= '9') { else if(c >= 'A' && c <= 'Z') { return(1); else if(c >= 'a' && c <= 'z') { return(2); else { return(3); char lower(char c) { if(c >= 'A' && c <= 'Z') { c = c + 32; return(c); 戻り値は文字にするのか他のものにするのかをきちんと考える必要があります ex23.c /* 文字列の簡単な例 */ char next_char(char c); char str[81]; /* 80 文字までの文字列が格納できるように */ int i; printf(" 文字列を入れてください :"); scanf("%s", str); /* ここは &str としないことに注意 */ for(i = 0; str[i]!= '\0'; i++) { str[i] = next_char(str[i]); printf("1 文字ずらすと %s\n", str); return (0); char next_char(char c) { return(c + 1); 17
練習問題 3.1 次は平成 23 年度の大学入試センター試験数学 II B の問題の一部である 今回はまず 上の操作に当る関数 つまり 変換するための関数を f とおいて! x # (x が偶数 ) f (x) = " 2 # $ 3x +1 (x が奇数 ) という関数を作りなさい ex24.c /* 関数で変換する */ int f(int x); /* プロトタイプ宣言 */ printf(" 調べる整数を入力してください "); scanf("%d", &x); printf("%d %d", x, f(x)); return (0); int f(int x) { 練習問題 3.2 (ex25.c) 次は東京の電車の中にあった広告である この広告の iuuq://xxx.dzcfsefgfotf.kq/epeb.ajq の部分の暗号を解読するプログラムを作成しなさい 18