3 関数

3.1 関数とは何か?

C言語の関数(function)とは,ある特定の処理を行うプログラムのことである.数学にも 関数という単語を使うが,それと似ている場合もあるし,異なる場合もある.それぞれの 場合について,例を使って説明する.

3.1.1 数学の関数と似ているC言語の関数

最初は,数学関数をC言語の関数を使って計算する.これまで,さんざん作成してきた次の関数

$\displaystyle f(x)=-x^2 + 10*x + 8 + 10\sin^2 x$ (1)

の最大値を求めるプログラムにC言語のユーザー定義関数を適用する.この数学の関数 を計算するために,C言語のユーザー定義関数f()を使うのである.リスト 1にプログラムを示す.このプログラムは,次のようになっている.
図 4: リスト1の関数の説明
\includegraphics[keepaspectratio, scale=1.0]{figure/function.eps}

   1 #include <stdio.h>
   2 #include <math.h>
   3 
   4 double f(double x);           //プロトタイプ宣言
   5 
   6 //========================================================
   7 // メイン関数
   8 //========================================================
   9 int main(void){
  10   double x, dx, xmin, xmax, y;
  11   double max_y, max_x;
  12   int i, ncal;
  13 
  14   //--- 計算条件設定 ---
  15   xmax = 10;
  16   xmin = -10;
  17   dx = 0.0001;
  18   ncal = (xmax-xmin)/dx;
  19 
  20   //--- 暫定最大値 ---
  21   max_x = xmin;
  22   max_y = f(xmin);
  23 
  24   //--- 最大値検索 ---
  25   for(i=1; i<=ncal; i++){
  26     x = xmin + i*dx;
  27     y = f(x);
  28     if(max_y <= y){        //最大値が見つかった場合
  29       max_x = x;
  30       max_y = y;
  31     }
  32   }
  33 
  34   printf("%fのとき,最大%fとなる.\n",max_x, max_y);
  35 
  36   return 0;
  37 
  38 }
  39 
  40 //============================================================
  41 // ユーザー定義関数
  42 //============================================================
  43 double f(double x){
  44   double y;
  45 
  46   y = -x*x + 10*x + 8 + 10*sin(x)*sin(x);        // 関数の計算
  47 
  48   return y;
  49 }

3.1.2 手続きの集まりとしてのC言語の関数

C言語の関数は処理の手続きをまとめたもの--である.先に示した例は数学の関 数をC言語の関数を使って計算しており,両者は同一の形になっている.しかし,このよ うに数学の関数を表現するために,C言語の関数を使う例は特殊である.C言語の関数はあ る特定の機能をはたす手続きをまとめたもの--となっているのが普通である.

リスト2の27-47行に記述している関数は,公約数に関する手 続きをまとめている.この関数の機能は,(1)2つの整数の公約数を表示,(2)公約数の個 数を返す--というものである.この関数の動作を見てみよう. -4pt

  1. 2つの整数を指定して,このプログラムを呼び出す(15行).2つの整数は,変数 mnにコピーされる.
  2. 整数mnの大小関係を比較して,小さい方の値を変数smallに格 納する.
  3. mnの公約数は,以下の通りです.」と表示する.
  4. 1〜smallまでの整数が公約数になっているか--調べる.
  5. 公約数が見つかれば,表示する.
  6. 呼出元へ,公約数の個数を返す.
メイン関数では,2個の整数をキーボードより読み込み,公約数を調べる関数 cmndivを呼び出す.そして,公約数の個数を表示する.プログラムの実行結果は, 以下のようになる.



\fbox{実行結果}

2つの整数を入力してください.公約数を表示します.
84
48
84と48の公約数は,以下の通りです.
1
2
3
4
6
12
公約数の数は,6個です.

   1 #include <stdio.h>
   2 
   3 int cmndiv(int m, int n);      //プロトタイプ宣言
   4 
   5 //========================================================
   6 // メイン関数
   7 //========================================================
   8 int main(void){
   9   int hoge, fuga, num;
  10 
  11   printf("2つの整数を入力してください.公約数を表示します.\n");
  12   scanf("%d", &hoge);
  13   scanf("%d", &fuga);
  14 
  15   num = cmndiv(hoge, fuga);
  16 
  17   printf("公約数の数は,%d個です.\n", num);
  18 
  19   return 0;
  20 }
  21 
  22 
  23 //============================================================
  24 // ユーザー定義関数
  25 // 公約数(common diviser)を捜す
  26 //============================================================
  27 int cmndiv(int m, int n){
  28   int i, small, count=0;
  29 
  30   if(m<n){
  31     small = m;
  32   }else{
  33     small = n;
  34   }
  35 
  36   printf("%dと%dの公約数は,以下の通りです.\n",m,n);
  37 
  38   for(i=1; i<=small; i++){
  39     if(m%i == 0 && n%i ==0){
  40       count++;
  41       printf("%d\n", i);
  42     }
  43   }
  44 
  45   return count;
  46 
  47 }

3.2 関数の役割

これまで,2つの関数を使ったプログラムの例を示した.この例で示したプログラムでは, 関数を使わないでも記述できる.それでは,なぜプログラムの記述に関数が必要なのであ ろうか?.長いプログラムを効率よく記述するために関数を使う--というのが答え である.

そのために,コンピュータープログラムの関数には2つの役割がある.一つ目の役割は, 同じような処理を一つにまとめることである.実際のプログラムの動作は,同じ処理,あ るいは似たような処理が非常に多い.いちいちそれを書くとプログラムが長くなり,プロ グラマーは大変である.そこで,ひとつにまとめ,必要なときに呼び出す.

分かりやすいプログラムの記述--が関数の二つ目の役割である.長いプログラムになる と,処理の内容がわかり難くなる.例えば,ソースプログラムが4000万行だと言われてい るWindows 2000 について,それぞれの実行文の役割など分からない.コンピューターは大量のト ランジスターからできているが,それぞれの役割が分からないのと同じである.このよう に大量の部品(実行文)から構成されるコンピューター(プログラム) の動作を考える際に 重要なことは,モジュール2に分解することである.モジュールと は,ある機能を果たす部品のことである.複雑な機械も,モジュールに分割すると動作の 内容が分かるようになる.長いプログラムを作る場合も同じで,モジュールに分け,分か りやすくすることが重要である.プログラムをモジュール--機能単位--に分割し, プログラムの動作内容をわかりやすくするために,C言語では関数を使う.

まとめると,関数の役割は -4pt

である.特に,2番目が重要で,「プログラムのソースは分かりやすくなくてはならない」 ということを,肝に銘じておかなくてはならない.

3.3 関数の作り方と使い方

関数をつくり,使うためには,ソースプログラムを図5の ように記述する.必要な記述は, -4pt
図 5: ユーザー定義関数を含んだソースプログラムの書き方
\includegraphics[keepaspectratio, scale=1.0]{figure/how_to_make_function.eps}

3.3.1 プロトタイプ宣言

プロトタイプ宣言はコンパイラー3に関数の引数の型と個数,それか ら戻り値の型を知らせる役割がある.これにより,コンパイラーがソースプログラム中で関数の 使い方の間違いをチェックする.これは,プログラマーにとって,非常にありがたい機能である.

プロトタイプ宣言は,図5のように関数の定義より前に記 述しなくてはならない.実際には,コールよりも前に関数の定義を書けば,このプロトタ イプ宣言を省くことは可能である(教科書 [1]のリスト 5.3).しかし,それは良くないスタイルとされている.このプロトタイプ記述は簡単で, 関数の定義の先頭部分をコピーして,セミコロンをつければ良い.

プロトタイプ宣言を書くことにより,ソースプログラムを読みやすくなる.現在では,複 数のプログラマーによりひとつのプログラムが作成されるため,読みやすいあるいは分か り易いプログラムを書くことは重要である.

プロトタイプ宣言をまとめると -4pt

となる.

3.3.2 関数の定義

プログラマーが関数に要求する動作の内容の記述を,ここでは関数の定義と言う.動作と いっても,(1)引数を受け取り,(2)それを処理して,(3)その結果を呼び出し元へ返す-- という一連の処理の内容をプログラムソースに記述するだけである.

関数の定義をまとめると,次のようになる. -4pt

3.3.3 関数のコール

実際に関数を使う場合,それを使いたい場所で,引数を伴って関数名を書く.関数を使う 動作を「関数のコール」,あるいは「関数の呼出し」と言う.関数をコールは main関数のみならず,他の関数からも可能である.また,自分自身の関数からも コールできる(再帰呼び出し).再帰呼び出しについては,2年生で学習する. -4pt
ホームページ: Yamamoto's laboratory
著者: 山本昌志
Yamamoto Masashi
平成18年10月20日


no counter