今回は少し長めのプログラムを、関数を使った形に変化させてみたいと思います。
下のプログラムは、以前作成した「数当て」を少し変えたプログラムです。
変えたのは、while文をfor文にしたくらいで、基本的な部分は何も変わっていません。
<sample program 130-01>
#include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) { int number; int input; int counter; srand((unsigned int)time(NULL)); number = rand() % 10 + 1; for (counter = 0; counter < 5; counter++) { printf("%d回目のチャレンジです。\n", counter + 1); do { printf("1〜10までの整数を入力してください:"); scanf("%d", &input); } while (input < 1 || input > 10); if (input == number) { break; } } if (input == number) { printf("%d回目で正解しました!\n", counter + 1); } else { printf("残念でした。\n"); } return 0; } |
<実行結果>
1回目のチャレンジです。 1〜10までの整数を入力してください:2 2回目のチャレンジです。 1〜10までの整数を入力してください:8 3回目のチャレンジです。 1〜10までの整数を入力してください:4 4回目のチャレンジです。 1〜10までの整数を入力してください:9 5回目のチャレンジです。 1〜10までの整数を入力してください:1 残念でした。 続行するには何かキーを押してください・・・
これを少しずつ、関数に分けていきます。
まずは、答えを計算する箇所を関数に分けてみます。
<sample program 130-02>
#include <stdio.h> #include <stdlib.h> #include <time.h> /* 答えを決定する */ int DecideAnswerNumber(void); int main(void) { int number; int input; int counter; srand((unsigned int)time(NULL)); number = DecideAnswerNumber(); for (counter = 0; counter < 5; counter++) { printf("%d回目のチャレンジです。\n", counter + 1); do { printf("1〜10までの整数を入力してください:"); scanf("%d", &input); } while (input < 1 || input > 10); if (input == number) { break; } } if (input == number) { printf("%d回目で正解しました!\n", counter + 1); } else { printf("残念でした。\n"); } return 0; } /* 答えを決定する */ int DecideAnswerNumber(void) { return rand() % 10 + 1; } |
<実行結果>
1回目のチャレンジです。 1〜10までの整数を入力してください:5 2回目のチャレンジです。 1〜10までの整数を入力してください:3 3回目のチャレンジです。 1〜10までの整数を入力してください:4 4回目のチャレンジです。 1〜10までの整数を入力してください:8 5回目のチャレンジです。 1〜10までの整数を入力してください:2 残念でした。 続行するには何かキーを押してください・・・
1行のプログラムを関数に分けたため、プログラムの総量として増えてしまい、無駄に思えるかもしれません。
しかし、これは「プログラムの機能ごとに名前を付ける」という関数の重要な役割の一つです。
rand() % 10 + 1; |
この1行のプログラムは、
乱数を10で割った余りに1を加算する
という風に書いてありますが、プログラム全体から見ると、
数当ての答えを決める
という「機能」を持っています。
長いプログラムになればなるほど、細かい部分は見づらくなり、デバッグも大変になります。
そこで、「機能」ごとにプログラムを分割し、管理しやすくしているのです。
次は、答えを入力する箇所を関数に分けます。
<sample program 130-03>
#include <stdio.h> #include <stdlib.h> #include <time.h> /* 答えを決定する */ int DecideAnswerNumber(void); /* 答えを入力する */ int InputAnswer(void); int main(void) { int number; int input; int counter; srand((unsigned int)time(NULL)); number = DecideAnswerNumber(); for (counter = 0; counter < 5; counter++) { printf("%d回目のチャレンジです。\n", counter + 1); input = InputAnswer(); if (input == number) { break; } } if (input == number) { printf("%d回目で正解しました!\n", counter + 1); } else { printf("残念でした。\n"); } return 0; } /* 答えを決定する */ int DecideAnswerNumber(void) { return rand() % 10 + 1; } /* 答えを入力する */ int InputAnswer(void) { int input; do { printf("1〜10までの整数を入力してください:"); scanf("%d", &input); } while (input < 1 || input > 10); return input; } |
<実行結果>
1回目のチャレンジです。 1〜10までの整数を入力してください:5 2回目のチャレンジです。 1〜10までの整数を入力してください:2 3回目のチャレンジです。 1〜10までの整数を入力してください:7 4回目のチャレンジです。 1〜10までの整数を入力してください:9 5回目のチャレンジです。 1〜10までの整数を入力してください:1 残念でした。 続行するには何かキーを押してください・・・
分割前は、main関数の変数inputに直接入力していましたが、分割後はInputAnswer関数に変数inputを作り、そこへ入力した後にreturnで戻り値として返しています。
ちなみに、main関数のinputとInputAnswer関数のinputは、全く別物で何の関係もありません。
(説明は雑ですが)関数が異なると同じ名前の変数を作ることが出来ると思ってください。
次は、結果を表示する箇所を関数に分割します。
<sample program 130-04>
#include <stdio.h> #include <stdlib.h> #include <time.h> /* 答えを決定する */ int DecideAnswerNumber(void); /* 答えを入力する */ int InputAnswer(void); /* 結果を表示する */ void ShowResult(int input, int number, int counter); int main(void) { int number; int input; int counter; srand((unsigned int)time(NULL)); number = DecideAnswerNumber(); for (counter = 0; counter < 5; counter++) { printf("%d回目のチャレンジです。\n", counter + 1); input = InputAnswer(); if (input == number) { break; } } ShowResult(input, number, counter); return 0; } /* 答えを決定する */ int DecideAnswerNumber(void) { return rand() % 10 + 1; } /* 答えを入力する */ int InputAnswer(void) { int input; do { printf("1〜10までの整数を入力してください:"); scanf("%d", &input); } while (input < 1 || input > 10); return input; } /* 結果を表示する */ void ShowResult(int input, int number, int counter) { if (input == number) { printf("%d回目で正解しました!\n", counter + 1); } else { printf("残念でした。\n"); } } |
<実行結果>
1回目のチャレンジです。 1〜10までの整数を入力してください:3 2回目のチャレンジです。 1〜10までの整数を入力してください:5 3回目のチャレンジです。 1〜10までの整数を入力してください:7 3回目で正解しました! 続行するには何かキーを押してください・・・
結果を表示するためには、main関数の「input」と「number」を比較し同じかどうか調べなければなりません。
また、正解であった場合「○回目で正解しました!」というメッセージを表示するため、「counter」も必要になります。
そこで、関数ShowResultには3つの引数を用意しました。
main関数と全く同じ名前の「input」「number」「counter」です。
しつこいですが、名前は同じでも関数が違いますので、異なる変数です。
必要な情報をmain関数からもらい、結果を表示しています。
ここまでやって、注目してほしいのはmain関数です。
<main関数>
int main(void) { int number; int input; int counter; srand((unsigned int)time(NULL)); number = DecideAnswerNumber(); for (counter = 0; counter < 5; counter++) { printf("%d回目のチャレンジです。\n", counter + 1); input = InputAnswer(); if (input == number) { break; } } ShowResult(input, number, counter); return 0; } |
ずいぶん短くなりましたが、機能としての名前を持った関数に置き換わっていますので、プログラム全体の意味は通じています。
main関数も含めて、1つ1つの関数はなるべく短くまとめた方が見やすく、メンテナンスしやすいです。
このことを頭において進めてください。