プログラミング実習

プログラミング論
第十六回
よく使う処理は関数にしよう
本日の内容

簡単な関数の例
–
–
–
–
–


関数の構成
ローカル変数の宣言
戻り値とreturn文
関数の呼び出し
関数のプロトタイプ宣言
戻り値のない関数
グローバル変数
簡単な関数の例
では,関数を作ってみよう!

数学における関数を思い出しましょう。
関数 f に x を与えたときの結果を y に代入する
これは,こう書きましたね。
y  f (x)
実際に,関数 f が x をもらってどういう計算をしているかは,・・
f ( x)  x  3x  2
2
と定義しましたね。
簡単な関数の例
では,関数を作ってみよう!

プログラミング言語の場合も同じです。
f ( x)  x 2  3x  2
y  f (3)



と関数を宣言して,
のように利用します。
関数の宣言は,main関数の外で行います。
関数は,main関数など他の関数の中で利用されます。
自分自身の中で呼び出すこともできます(再帰処理)
簡単な関数の例
では,関数を作ってみよう!
#include <stdio.h>
double f( double x)
{
double y;
int main(void)
{
double x,y;
printf("x=?");
scanf("%lf", &x);
y = x*x+3*x+2;
y = f(x);
return y;
}
printf("y=%f\n",y);
}
ここが関数の宣言部です
簡単な関数の例
では,関数を作ってみよう!

#include <stdio.h>

double f( double x)
{
引数
double y;
ローカル変数
y = x*x+3*x+2;



return y;
}

関数の処理は,{ }で囲んで
表します。
プログラム内では,変数は型
指定されなければなりません。
関数が呼び出されたところか
ら受け取るデータを引数とい
います。
関数の答えが何型になるの
か,の指定も行います。
計算した後,関数の答えとし
て出力する変数の値はreturn
文で返します。
関数の中で宣言される変数を
ローカル変数と言います。関
数の中だけで有効です。
簡単な関数の例
では,関数を作ってみよう!
必ず,main関数から実行されます
#include <stdio.h>
int main(void)
{
double f( double x) 引数の値が double x,y;
渡されます。
{
両方ともロー
カル変数の
double y;
printf("x=?");
ため,変数名
scanf("%lf", &x);
は同じですが
y = x*x+3*x+2; まったく別の
変数です。
渡された引数を元に
y = f(x); 関数が呼び
処理を行います。
出されます
return y;
}
printf("y=%f\n",y);
処理結果のyが関数の結果
として呼び出し元に返されます。
}
結果が画面に表示されます。
演習




ensyu44.cを完成させ,結果を確認しなさい。
引数として,直接数値を指定しても良いことを
確認しなさい。
ローカル変数名(引数と関数の結果の変数名)
は,main関数と関数fとで異なっていても問題な
いことを確認しなさい。
最後のprintfにて,変数yの値を出力する代わ
りに,直接printf内にて関数fの呼び出しを行っ
ても結果が出力されることを確認しなさい。
演習


実数を四捨五入して整数にする処理を,
関数で実現するプログラムを作成しなさ
い。
ensyu45.cを完成させなさい。
プロトタイプ宣言



ensyu46.cは,ensyu44.cを改訂したもの
です。
main関数を最初に配置し,後ろに関数f
を配置しています。
コンパイルするとどうなるでしょうか?
プロトタイプ宣言

こんなエラーが出ます。
警告 W8065 ensyu46.c 12: プロトタイプ宣言のない
関数 'f' の呼び出し(関数 main )
エラー E2356 ensyu46.c 20: 'f' の再宣言で型が一致していない

では,一つずつ考えていきましょう。
プロトタイプ宣言
警告 W8065 ensyu46.c 12: プロトタイプ宣言のない
関数 'f' の呼び出し(関数 main )
#include <stdio.h>
int main(void)
{
double x, y;
printf("x=");
scanf("%lf",&x);
y = f(x);
printf("y=%f\n",y);
}
double f(double x)
{
double y;
y = x*x+3*x+2;
return y;
}
ここの段階でこのメッセージ
が出力されます。
ここでいきなり初めて関数fと
いうのが出てきた。
こんなものは聞いたことがない
から勝手に解釈して先に進み
ます。
プロトタイプ宣言
エラー E2356 ensyu46.c 20: 'f' の再宣言で型が一致していない
#include <stdio.h>
int main(void)
{
double x, y;
printf("x=");
scanf("%lf",&x);
y = f(x);
printf("y=%f\n",y);
}
double f(double x)
{
double y;
y = x*x+3*x+2;
return y;
}
ここの段階でこのメッセージ
が出力されます。
さっき初めて見たからこっちで
勝手に解釈していたのに,
こんなところで教えてくれたって
もう遅い!
プロトタイプ宣言




というわけで,初めて作って利用する関数は,
「呼び出す関数の前に宣言をすませておかな
いと,コンパイル時に解釈できなくてエラーが出
る」ということになります。
プリプロセッサの位置に,「これからこういう関
数を使いますよ」という関数の形の宣言をしま
す。これを「プロトタイプ宣言」といいます。
関数名,引数の数・型,返り値(関数の結果)の
型を宣言します。
ensyu47.cでプロトタイプ宣言の方法を確認し
て下さい。
プロトタイプ宣言
#include <stdio.h>
double f(double);
int main(void)
{
double x, y;
printf("x=");
scanf("%lf",&x);
y = f(x);
printf("y=%f\n",y);
}
double f(double x)
{
double y;
y = x*x+3*x+2;
return y;
}
プロトタイプ宣言
double f(double);
引数の型と数
関数名
関数の結果(返り値)の型
printfやscanfは,標準ライブラリ
関数と言われ,stdio.hの中に記載
してあるため,エラーとならない。
返り値のない関数

返り値がない関数の場合は,関数宣言時の返
り値の型はvoidで宣言をします
(ensyu48.c)
#include <stdio.h>
void putd(int);
int main(void)
{
int dt=100;
putd(dt);
return 0;
}
void putd(int a)
{
printf("%d\n",a);
}
関数の型宣言
はvoid型となる
関数が値を返さない
=return文がない
演習:よく間違う例


ensyu49.cは,変数xと変数yの値を交換
するプログラムとして作ってみたものです。
実行して,変数値が交換できることを確
認しなさい。
ensyu50.cは,交換の機能をswapという
関数で実現しようとしたものです。しかし,
これでは変数値が交換されません。この
理由を考えなさい。
グローバル変数




関数内で宣言された変数はローカル変数と呼
ばれ,その関数内でのみ有効です。
同じ名前の変数があったとしても,異なる関数
内で宣言されていれば,「違う家に住んでいる
同姓同名の人」という扱いになり,まったく別の
変数,と言うことになります。
ただし,関数の外,プリプロセッサの位置で宣
言された変数は「グローバル変数」と呼ばれ,
どの関数からでも共通して利用できる変数にな
ります。
ensyu51.cで確認しましょう。
グローバル変数
#include <stdio.h>
double r;
グローバル変数
double pi=3.141592;
double menseki(void);
double ensyu(void);
この値を共通
int main(void)
に利用できる
{
double c, s;
printf("r="); scanf("%lf",&r);
c=ensyu();
s=menseki();
printf("ensyu=%f, menseki=%f\n",c,s);
return 0;
}
double ensyu(void)
{
return 2*r*pi;
}
double menseki(void)
{
return r*r*pi;
}
共通に利用できる
演習


int型引数一つを受け取り,その数値の階
乗を計算する関数int kaijo(int n)を完成
させなさい(ensyu52.c)。
グローバル変数を用いることによりデータ
交換を可能にした関数void swap(void)
を完成させなさい(ensyu53.c)。