講義用スライド

情報処理技法
(Cプログラミング)I
第8回
ー 関数 ー
担当: 荻田 武史
本日の授業内容 •  代入と演算の組み合わせ •  関数 •  return文 •  プロトタイプ宣言 •  グローバル変数・ローカル変数 2
代入と演算の組み合わせ
•  以下のような省略した表記が可能。
演算子
+=
-=
*=
/=
記述例
a += b;
a -= b;
a *= b;
a /= b;
意味
a = a + b;
a = a - b;
a = a * b;
a = a / b;
3
関数 •  自分で関数を定義することができる。 戻り値の型 引数の型 int func(int a, int b) { 関数の内容 return 戻り値 ; } 関数名(funcの部分)は自由に名前を付けて良い。 4
func.c #include <stdio.h> int func(int a, int b) { printf("a..%d, b..%d\n", a, b); return a + b; } int main(void) { int return_value; printf("Start of function main()\n"); return_value = func(3, 5); printf("return_value..%d\n", return_value); return 0; } 5
func.c の説明 •  C言語では、プログラム実行は main()関
数から開始される。 •  "Start of function main()"が表示。 •  main()の中で関数 func()を呼び出してい
る。 •  func()の中の最後のreturn文で、2つの
引数を足した値を返している。 •  結果(return_value)の表示。 6
戻り値や引数のない関数 •  戻り値のない関数 void func(int a,……) { } •  引数のない関数 double func(void) { } 7
return文 •  関数の最後で呼び出し元に戻り値を返す機能。 •  関数の途中で実行を打ち切って呼び出し元に戻る機能。 ⇒ return文は関数の途中に書くこともできる。 void func(void) { if (評価式) { return; } returnした場合は この部分は実行されない } 8
プロトタイプ宣言(1) •  C言語では、関数は呼び出し元より先(ソース
コードの中で、上側)に定義または宣言されて
いなければならない(試しにfunc.cを書き換えて
みよう)。 $ cp func.c func2.c $ xemacs func2.c & (関数の定義の順序を自分で変更) $ gcc -Wall func2.c (警告をすべて出力) func2.c: In function `main': func2.c:9: warning: implicit declaration of function `func' 9
プロトタイプ宣言(2) •  関数の「定義」を先に書くことができな
い場合は、「宣言」だけを先に書く。 int func(int a, int b); ⇒ 関数の定義から、最初の部分だけ取り出
して、最後にセミコロンを付けたもの。 10
func2.c #include <stdio.h> int func(int a, int b); int main(void) { int return_value; printf("Start of function main()\n"); return_value = func(3, 5); printf("return_value..%d\n", return_value); return 0; } int func(int a, int b) { printf("a..%d, b..%d\n", a, b); return a + b; } 11
関数を使ったソートプログラム • 
「my_sort5.c」では、プログラムのすべてが
main関数に書かれているため全体の見通しが
悪い。 ⇒ 関数を使ってプログラムを書き換え、見通しを
良くする。 プログラムを以下の3つのパートに分離する。 1.  データを読む関数: read_data() 2.  ソートする関数: sort_data() 3.  データを出力する関数: print_data() 12
my_sort6.c の全体像 #include <stdio.h> #include <stdlib.h> #define SCORE_ARRAY_SIZE 100 int score[SCORE_ARRAY_SIZE]; int score_count; void read_data(void) { } 関数の外側で宣言されている: グローバル変数 ⇒ すべての関数から参照できる void sort_data(void) { } void print_data(void) { } int main(void) { } 13
関数 main() int main(void) { read_data(); sort_data(); print_data(); return 0; } ⇒ 単純明快! 14
関数 read_data() void read_data(void) { int status; int temp_score; score_count = 0; while (1) { status = scanf("%d", &temp_score); if (status == EOF) { break; } else if (status != 1) { fprintf(stderr, "input error\n"); exit(1); } if (score_count >= SCORE_ARRAY_SIZE) { fprintf(stderr, "data are too many\n"); exit(1); } score[score_count] = temp_score; score_count++; } } 関数の内側で宣言されている: ローカル変数 ⇒ この関数の中でしか参照できない 15
関数 sort_data() void sort_data(void) { int sorted_count; int minimum_index; int temp; int i; for (sorted_count = 0; sorted_count < score_count; sorted_count++) { minimum_index = sorted_count; for (i = sorted_count + 1; i < score_count; i++) { if (score[i] < score[minimum_index]) { minimum_index = i; } } temp = score[minimum_index]; score[minimum_index] = score[sorted_count]; score[sorted_count] = temp; } } 16
関数 print_data() void print_data(void) { int i; for (i = 0; i < score_count; i++){ printf("score[%d]..%d\n", i, score[i]); } } 17
プログラムが完成したら・・・ $ gcc -Wall my_sort6.c -o my_sort6 $ ./my_sort6 < data.txt 結果が正しいか確認する。 18