第 5回 - 計算技術研究会

計算技術研究会
第5回 C言語勉強会
関数(function)を使う
Slide Designed: Michio Harahashi(CS)
今回の予定と目標

関数を理解して使えるようにする
勉強内容は
関数とは
関数の書き方(型、引数、戻り値)
例題、練習問題
再帰呼び出し

関数とは?
数学における関数
与えられた値を決められた規則によって計算をすること

(例)

f ( x)  2 x  3
f (1)  2 1  3  5
f (2)  2  2  3  7
プログラミングにおける関数
プログラミングにおける関数
数学の関数と似たようなもの
値を受け取り、定められた通りの処理を実行して結果を返す
処理のひとまとまりのこと。

このとき、関数に渡す値を引数(ひきすう)
関数を実行した結果として帰ってくる値を戻り値という。
(イメージ)
f ( x)  2 x  3
f (1)  2  1  3  5
引数
処理
戻り値
Example 01 二乗をする関数
#include <stdio.h>
int pow(int a);
int main() {
int a=10, result;
result=pow(a);
printf(“%dの二乗は%dです\n”,a,result);
return 0;
1
}
2
int pow(int a) {
return a*a;
}
戻り値の型 関数の名前(引数の型 変数) {
処理内容;
return 戻り値;
}
プロトタイプ宣言

自作関数を使用することを宣言
いままではmain()関数のみであったが、今回は自分で新しく
関数を作ることになる。
その際に、#include文の下に次のような文が必要となる。
戻り値の型 関数の名前(引数1の型 引数1, 引数2の型 引数2, …);
これをプロトタイプ宣言という。
#include <stdio.h>
int function(int x);
main() {
int x, y;
x = 10;
y = function(x);
printf(“f(%d) = %d\n”, x, y);
}
int function(int x) {
return x * x;
}
戻り値:return文

計算結果を返す
main()関数などから自作関数を呼び出した後に、呼び出し元へ値を返すときは
return 値; の文を用いる。
関数を使うメリットって?
処理の部品化
頻繁に行う処理を一つの関数としてまとめることによって、
関数に値を渡すとその値に応じた処理結果を返してくれる
何度も同じ処理を書かなくて良く、プログラムがすっきりする

(例)aとbの平均の数を求めたい。
その次にcとdの平均の数を求めたい。
「引数m,nの平均を求める」という処理を関数としてまとめてあげれば
あとはその関数に2つの数を与えるとその処理結果を返してくれる
→「平均を求める」を2回も書かなくてすむ!
Example 02 2つの数の平均を求める関数
#include <stdio.h>
double average(int m, int n);
int main() {
int a=5, b=10;
double result = average(a, b);
printf(“%dと%dの平均の値は%fです\n”,a,b,result);
return 0;
}
double average(int m, int n) {
return (m+n)/2.0;
}
Practice 01
2つの数の和を求める関数
内容
2つの数の和を求めるプログラム

仕様
メイン関数と2つ数の和を求める関数からなる。
コンソールから入力された2つの数を和を求める関数に引数として渡して
その結果を戻り値として受け取り、表示する。

ヒント
コンソールから数を入力をするにはscanfを使います

関数のプロトタイプ宣言を忘れずに!
Practice 01 : Answer
2つの数の和を求める関数(例)
#include <stdio.h>
int sum(int m, int n);
int main() {
int a, b, result;
printf(“2つの整数を入力”);
scanf(“%d %d”, &a, &b);
result = sum(a, b);
printf(“%dと%dの和は%d\n”, a, b, result);
return 0;
}
int sum(int m, int n) {
return m + n;
}
voidというもの
引数や戻り値が無い関数
数学の関数とは違い、プログラムの関数は引数が無いという関数もある。
また、戻り値が無い関数というのも存在し、その関数の「型」はvoid型と呼ぶ。

引数があるのに戻り値が無い関数や、引数無いのに戻り値はある関数、
さらには引数も無ければ戻り値も無い関数などといろいろなバリエーションがある。
(例1)引数が無い関数
(例2)戻り値が無い関数
(例3)引数、戻り値が無い関数
double getPi() {
return 3.14;
}
void printA(int a) {
printf(“%d”,a);
}
void printHello() {
printf(“Hello, K3!”);
}
この関数はdouble型の関数。
この関数はvoid型の関数。
この関数はvoid型の関数。
Example 03
“Hello, World!” を10回表示する関数
#include <stdio.h>
void printHello();
int main() {
printf(“今から10回Hello,World!と出力\n”);
printHello();
printf(“表示されましたね?\n”);
}
void printHello() {
int i;
for (i = 1; i <= 10; i++) {
printf(“%d回目の表示:Hello, World!\n”, i);
}
}
Practice 02
指定された回数だけHello, World!と
表示する関数
内容
コンソールから入力された整数の回数だけ Hello, World! と表示する
仕様
main関数でコンソールから整数を受け取り、callHello関数でその整数
の回数分だけ Hello, World! と表示させる。
ヒント
callHello関数は void callHello(int n) です。
これもプロトタイプ宣言を忘れずに!
Practice 02:Answer
#include <stdio.h>
void callHello(int n);
int main() {
int n;
printf(“整数を入力:”);
scanf(“%d”, &n);
callHello(n);
}
void callHello(int n) {
int i;
for (i = 0; i < n; i++) {
printf(“Hello, World!\n”);
}
}
Practice 03 (ちょっと上級)
入力された整数が素数かどうか判定する関数
内容
入力された整数が素数かどうか判定するプログラム

仕様
メイン関数と素数を判定する関数からなる。
素数を判定する関数は引数がコンソールから入力されたint型の整数で、
int型の戻り値を持ち、1が帰ってきたら素数、0が帰ってきたら合成数と判断する。

ヒント
ある整数nが素数ならば、1とn以外では割り切ることが出来ない。
つまり、nを1から順番に割っていって、2回以上割り切ることが出来なかったら
戻り値として1を返し、3回以上割り切れたら0を返せばよい。
余りを求める剰余演算子は% (例:5%2 = 1)

Practice 03 : Answer
入力された整数が素数かどうか判定する関数
include <stdio.h>
int isPrime(int n);
int main() {
int n, result;
printf(“整数nを入力”);
scanf(“%d”,&n);
result=isPrime(n);
if(result==0) {
printf(“%dは合成数です\n”,n);
} else {
printf(“%dは素数です\n”,n);
}
return 0;
}
int isPrime(int n) {
int i, count=0;
for(i=1; i<=n; i++) {
if(n%i==0) { count++; }
}
if(count>2) {
return 0;
} else {
return 1;
}
}
再帰的呼び出し(Recursive Call)
自分自身を呼び出す?
関数はプロトタイプ宣言をしていればどこからでも呼び出せる。
つまり、とある関数が自分自身(関数)を呼び出すことも出来る。


具体例:nの階乗を求める
【階乗の定義】
n=0 ならば 0! = 1
n≠0 ならば n! = n * (n – 1)!
例えば、n=3ならば
3! = 3 * (3 – 1)! = 3 * 2!
2! = 2 * (2 – 1)! = 2 * 1!
1! = 1 * (1 – 1)! = 1 * 0!
0! = 1
再帰的呼び出し(Recursive Call)2
関数を利用
「階乗を求める」という処理を関数としてまとめると、
factorial(n) = 1;
// n=1のとき
facotiral(n) = n * factorial(n-1) // n≠1のとき

関数factorialが、引数nの値を1ずつ減らして自分自身を呼び出している。
http://java.cis.k.hosei.ac.jp/materials/lecture09/method3.html
より図を引用
nの階乗を求めるプログラム(再帰)
#include <stdio.h>
int factorial(int n);
int main() {
int n, result;
printf(“整数nを入力してください:”);
scanf(“%d”,&n);
result=factorial(n);
printf(“%dの階乗は%dです\n”,n,result);
return 0;
}
int factorial(int n) {
if (n==0) { return 1;}
else { return n*factorial(n-1); }
}