cp-8. 関数
C プログラミング入門)
URL: https://www.kkaneko.jp/pro/adp/index.html
1
金子邦彦
内容
例題1.棒グラフ
関数とは.プログラム実行順.データの流れ.
引数と仮引数
例題2.月の日数
return
例題3.1か月分のカレンダー
例題4.月初めの曜日
例題5.カレンダー
関数の集まりとしてのプログラム
2
○○仕事
頼む!
頼む人
担当者A
担当者B
△△の仕事を
頼む!
仕事の分割
3
関数とは
プログラムは,しばしば,複数の関
数に「分割」される
関数
関数
関数
呼び出し側
呼び出され側
呼び出され
4
目標
1つの main 関数と,その他の複数の関数から
構成されたプログラムを読んで,理解できる能
力を習得する
複数の関数の間での「情報の受け渡し」につい
て理解する
5
例題1.棒グラフ
整数から,その長さだけの棒を表示する関数を作
例) 5 *****
上記で作った関数を使って,「整数を読み込んで,
読み込んだ長さの棒を表示するプログラム」を作
6
棒グラフ
#include <stdio.h>
#pragma warning(disable:4996)
void bar( int len )
{int i;
for (i=0; i<len; i++) {
printf("*");
}
printf("\n");
return;
}
int main()
{int len;
printf( "len=" );
scanf( "%d", &len );
bar( len );
return 0;
}
bar関数
main関数
7
グラフ
実行結果の例
len=5
*****
8
関数呼び出しの流れ
bar 関数
void bar( int len )
main 関数
int main()
bar(len);
関数呼び出し
return;
戻り
9
プログラム実行順
#include <stdio.h>
#pragma warning(disable:4996)
void bar( int len )
{int i;
for (i=0; i<len; i++) {
printf("*");
}
printf("\n");
return;
}
int main()
{int len;
printf( "len=" );
scanf( "%d", &len );
bar( len );
return 0;
}
bar関数
main関数
関数呼び出し
戻り
main 関数の先頭行
がプログラムの始まり
main 関数内の return
がプログラムの終わり
10
プログラム実行順
bar( len );
main 関数
int main()
if( i < len )
printf( "*" );
i++;
No
Yes
printf("\n");
return;
bar 関数
void bar( int len )
関数
呼び出し
戻り
printf( "len=" );
scanf( "%d", &len );
return 0;
i= 0;
11
プログラム実行順
普通,プログラム中の文は逐次的に実行され
関数呼び出しでは関数の先頭に「ジャン
プ」する.
関数呼び出しの例) bar( len );
関数の中で return 文に出会うと,関数呼び出
しの場所に戻る
12
main 関数
プログラムの実行を開始すると,自動的にmain
関数が呼ばれる
プログラムの開始は,main 関数の最初の行から
main 関数内return 文は,「プログラムのわり
を示す
プログラムには,必ず main 関数が書かれていな
ければならない
13
関数定義の例
#include <stdio.h>
#pragma warning(disable:4996)
void bar( int len )
{int i;
for (i=0; i<len; i++) {
printf("*");
}
printf("\n");
return;
}
int main()
{int len;
printf( "len=" );
scanf( "%d", &len );
bar( len );
return 0;
}
bar関数
頭部
名前仮引数
本体
main関数
頭部
名前仮引数(は空)
本体
14
関数定義
関数定義とは関数実体をプログラムとして
書くこと
関数には名前型,仮引数がある
仮引数のそれぞれにも,型と名前がある
void bar( int len )
名前 仮引数
呼び出し側から関数側に
されるデータに関係する
関数側から呼び出し側に
返されるデータに関係する
int main()
例)
15
関数でのデータの流れ
関数
関数
呼び出し側
呼び出され側
関数呼び出し時に,
データ処理すべき
データ)を渡す
関数からの戻り時に,
データ(処理結果の
データ)を返す
16
データの流れ
bar 関数
void bar( int len )
main 関数
int main()
bar(len);
関数呼び出し
return;
戻り
仮引数
len の値を,
bar 関数に渡す ②整数を受け取って,
len」という名前で使う
main 関数には,
何も返さない 17
データの流れ
len 5
sum 関数
void bar( int len )
main 関数
int main()
bar(len);
関数呼び出し
return;
戻り
仮引数
len の値を,
bar 関数に渡す 整数を受け取って,
len」という名前で使う
main 関数には,
何も返さない
len 5
main 関数内で宣言された len
len 5
仮引数で宣言された len
こちらは使われない
値がコピーされる
main 関数内で宣言された len
と,仮引数で宣言された len
別のもの
18
引数と仮引数
関数呼び出し側
カッコの中に書いた変数等の値(引数という)が,
関数に渡される
(例) bar( len );
呼び出された関数側
呼び出された関数は,値を受け取って,名前を付け
使用する仮引数という
(例) int bar( int len )
len の値を,bar 関数に渡す(引数)
整数を受け取って,「len
という名前で使う(仮引数) 19
引数と仮引数
引数
関数などに実際に渡される「データ」のこと
関数呼出しの(,)内に並べる
定数や変数や式を書く
仮引数パラメータともいう
関数定義の(,)中で宣言された変数のこと.
(例) void bar(int len)では,変数 len が宣言されている
関数は,呼び出された時点において,値を受け取り,当
該関数の仮引数である変数にセットする.
引数で与えられた値が,仮引数の変数代入され
て情報の受け渡しが行われる. 20
例題2.月の日数
年と月から,日数を求める関数を作る
うるう年の2月ならば29
めた日数は,関数の返り値として呼び出し側に返
こと
例) 2001 11 30
上記で作った関数を使って,「年と月を読み込ん
で,日数を求めるプログラム」を作る
21
#include <stdio.h>
#pragma warning(disable:4996)
int num_of_day( int y, int m)
{int num_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if ( (m == 2) && (((y % 400) == 0) || (((y % 100) != 0) && ((y % 4) ==
0)))){
return 29;
}
else {
return num_days[m-1];
}
}
int main()
{int y;
int m;
int n;
printf( "y=" );
scanf( "%d", &y );
printf( "m=" );
scanf( "%d", &m );
n = num_of_day(y, m);
printf( "number of days(%d) = %d\n", m, n );
return 0;
}22
月の日数
実行結果の例
y=2001
m=11
number of days(11) = 30
23
関数呼び出しの流れ
main 関数
int main()
n = num_of_day(y, m);
関数呼び出し
戻り
num_of_day 関数
int num_of_day( int y, int m )
return num_days[m-1];
return 29;うるう年のとき
うるう年
でないとき
24
#include <stdio.h>
#pragma warning(disable:4996)
int num_of_day( int y, int m)
{int num_days[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if ( ( m == 2 ) && (((y % 400) == 0) || (((y % 100) != 0) && ((y %4) == 0)))){
return 29;
}
else {
return num_days[m-1];
}
}
int main()
{int y;
int m;
int n;
printf( "y=" );
scanf( "%d", &y );
printf( "m=" );
scanf( "%d", &m );
n = num_of_day(y, m);
printf( "number of days(%d) = %d\n", m, n );
return 0;
}
プログラム実行順
25
プログラム実行順
n = num_of_day(y, m);
main 関数
int main()
if( ・・・ )
return 29;
No
Yes
return num_days[m-
1];
num_of_day 関数
int num_of_day( int y, int m)
関数
呼び出し
戻り
26
データの流れ
y m の値を,
num_of_day 関数に渡す ②整数を2つを受け取って
y m」という名前で使う
main 関数に,num_days[m-1]
の値を返す
main 関数
int main()
n = num_of_day(y, m);
関数呼び出し
戻り
num_of_day 関数
int num_of_day( int y, int m )
return num_days[m-1];
return 29;うるう年のとき
うるう年
でないとき
main 関数に,29 を返す
仮引数
27
データの流れ
y m の値を,
num_of_day 関数に渡す ②整数を2つを受け取って,
y」と「m」という名前で使う
main 関数に,num_days[m-1]
の値を返す
main 関数
int main()
n = num_of_day(y, m);
関数呼び出し
戻り
num_of_day 関数
int num_of_day( int y, int m )
return num_days[m-1];
return 29;うるう年のとき
うるう
でないとき
main 関数に,29 を返す
仮引数
y2001
値がコピーされる
m11
y2001
m11
y2001
m11
28
関数の中の return
関数の呼び出しの場所に戻ることを示す
return 文で書いた式の値が,呼び出し側に返される
(例)return; 何も返さない
return 29;29 を返す
return num_days[m-1]; num_days[m-1] を返す
29
void 意味
関数には,型がある
int
double
void など
但し,void は,「関数が return 文で,何も返さな
いこと(値を返さない関数)」 を示す
例) void print_calendar( int num_days, int youbi )
void 関数定義したら,return の次に式を書
かない( return;).
30
関数から返された値の使い方
関数は,一種の「式」であって,「値」を
この「値」が,関数から返された値
n = num_of_day(y, m);
関数呼び出し
num_of_day 関数から返された値が n に入る
31
例題3.1か月分のカレンダー
日数と曜日から,1か月分のカレンダーを表示す
関数を作る
日数は,28,29,30,31 のいずれか
曜日は,0,1,,6 のいずれか
表示される日付は,2桁の幅としそれぞれの間に1
つの空白を置くこと.
32
#include <stdio.h>
#pragma warning(disable:4996)
void print_calendar( int num_days, int youbi )
{int i;
int d;
int x;
if ( ( num_days < 28 ) || ( num_days > 31 ) || ( youbi < 0 ) || ( youbi > 6 ) )
{return;
}
for ( i = 0; i < ( youbi * 3 ); i++ ) {
printf( " " );
}
d = 1;
x = youbi;
do {
printf( "%2d ", d );
d++;
if ( x == 6 ) {
printf( "\n" );
x = 0;
}
else {
x++;
}
} while ( d <= num_days );
return;
}
曜日の分だけ空白を表示
日付を書く
土曜日に来たら改行する
月末までいたらえる
渡された値がおかしいときは,
何もせずに終わる
33
int main()
{int num_days;
int youbi;
printf( "num_days=" );
scanf( "%d", &num_days );
printf( "youbi=" );
scanf( "%d", &youbi );
print_calendar( num_days, youbi );
return 0;
}
前のページからの続き
34
1か月分のカレンダー
実行結果の例
num_days=30
youbi=4
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30
35
関数呼び出しの流れ
main 関数
int main()
print_calendar(num_days,
youbi);
関数呼び出し
戻り
num_of_day 関数
void print_calendar( int num_days, int youbi )
return; 渡された値が
おかしいとき
return;
36
プログラム実行順
print_calendar( num_days, youbi );
main 関数
int main()
print_calendar 関数
void print_calendar( int num_days, int youbi )
関数
呼び出し
戻り
if( ・・・ )
return;No
Yes
return;
1か月分のカレンダーの表示
37
1月分のカレンダーの表示
曜日」の分だけ空白を表示
日付を書く
日付が「日数」を超えたか?
Yes No
日付を1足す
書いた日付土曜日か?
No
Yes
改行する
日付を0にする
38
例題4.月初めの曜日
ツエラーの公式を使い,年と月から,月初め
の曜日を求める関数を作る
曜日は,0,1,,6 のいずれか
0:日曜日
1:月曜日
2:火曜日
3:水曜日
4:木曜日
5:金曜日
6:土曜日
39
月初めの曜日
#include <stdio.h>
#pragma warning(disable:4996)
int zeller( int y, int m, int d )
{if ( ( m== 1 ) || ( m== 2 ) ) {
y= y- 1;
m= m+ 12;
}
return (y + (y/4) - (y/100) + (y/400) + ((13 * m + 8 ) / 5) + d) % 7;
}
int first_day( int y, int m )
{return zeller( y, m, 1 );
}
int main()
{int y;
int m;
int f;
printf( "y=" );
scanf( "%d", &y );
printf( "m=" );
scanf( "%d", &m );
f = first_day(y, m);
printf( "first days(%d, %d) = %d\n", y, m, f);
return 0;
}
40
例題5.カレンダー
年と月から,カレンダーを表示するプログラ
ムを作る
41
「カレンダー」のプログラムの関数分
役割ごとに関数を作る.
1. 本体
2. 月の日数
3. 月初めの曜日
4. 1ヶ月分のカレンダー
42
カレンダー
月の日数
日数
月初めの
曜日
1か月分の
カレンダー
曜日
日数
曜日
main関数
例題2で
作成済み
例題3で
作成済み
例題4で
作成済み
main関数
のみを新規
に作成
43
コメントでおおまかな処理を書く
int main()
{
/* 年と月を読み込む */
/* 年と月から「月の日数」を求める */
/*年と月から「月初めの曜日」を求める */
/* 「月の日数」と「月初めの曜日」からカレンダーを表示す
*/
return 0;
}
44
コメント
コメントはプログラムの中に書く注釈のこと
プログラムの説明や使用上の注意などを書く.
コメントは,プログラム実行では無視される
コメントのまりは/*で,終わりは*/である.あ
るいは//を使って,1行分のコメントを書くことも
ある.コメントは,入れ子にすることができない.
次のコメントは入れ子になっていて間違いである.
/* n = n + 1; /* n は「空き領域」の先頭を指す */ */
45
カレンダー#pragma warning(disable:4996)
int main()
{
int y;
int m;
int nissu;
int youbi1;
/* 年と月を読み込む */
printf( "y=" );
scanf( "%d", &y );
printf( "m=" );
scanf( "%d", &m );
printf( "日月火水木金土\n" );
/* 年と月から「月の日数」を求める */
nissu = num_of_day(y, m);
/*年と月から「月初めの曜日」を求める */
youbi1 = first_day(y, m);
/* 「月の日数」と「月初めの曜日」からカレンダーを表示する */
print_calendar( nissu, youbi1 );
return 0;
}46
-関数と変数-
プログラム
データ
処理手順
変数
関数
main 関数
ライブラリ関数
ユーザが自分で
定義した関数
printf, scanf など
47
関数の種類
main関数
プログラムは,main 関数を必ず含む
ライブラリ関数
システムに既に組み込まれた関数
ユーザが定義した関数
プログラマが独自の関数を定義可能
48