関数の基本
コードを整理して再利用する方法。プログラムの核となる概念
概要
プログラムが複雑になると、同じ処理を何度も書く必要が出てきます。 そこで活躍するのが関数です。
関数とは、一連の処理をまとめて、 名前を付けたもの。 与えられた入力(引数)に対して 処理を行い、結果(戻り値)を返します。
関数の基本形
戻り値の型 関数名(引数) {
// 処理
return 戻り値;
}
各要素:
- 戻り値の型:関数が返す値のデータ型。戻り値がない場合は void
- 関数名:その関数を呼び出す時に使う名前
- 引数:関数に渡される値。複数可。不要な場合は空
- return:関数を終了して値を返す
シンプルな例
例1: 戻り値ありの関数
#include <iostream>
int add(int a, int b) {
return a + b;
}
int main() {
int result = add(3, 5);
std::cout << "3 + 5 = " << result << std::endl;
return 0;
}
3 + 5 = 8
add関数は2つの整数を受け取り、その合計を返します。
例2: 戻り値なしの関数(void)
#include <iostream>
void greet(std::string name) {
std::cout << "こんにちは, " << name << "!" << std::endl;
}
int main() {
greet("太郎");
greet("花子");
return 0;
}
こんにちは, 太郎!
こんにちは, 花子!
void型の関数は値を返しません。
画面に出力したり、データを変更したりする処理に使われます。
関数の宣言と定義
通常、プログラムは上から順に実行されるため、 関数を定義する前に呼び出すことはできません。
これを解決する方法が関数の宣言です。
#include <iostream>
// 関数の宣言(プロトタイプ)
int multiply(int a, int b);
int main() {
int result = multiply(4, 5);
std::cout << result << std::endl;
return 0;
}
// 関数の定義
int multiply(int a, int b) {
return a * b;
}
20
;で終わる行を宣言(プロトタイプ)、
{}を含む部分を定義と呼びます。
複数の引数
例1: 3つの数値の最大値
#include <iostream>
int maxOfThree(int a, int b, int c) {
int max = a;
if (b > max) max = b;
if (c > max) max = c;
return max;
}
int main() {
std::cout << maxOfThree(10, 20, 15) << std::endl; // 20
std::cout << maxOfThree(5, 5, 5) << std::endl; // 5
return 0;
}
20
5
例2: 四則演算
#include <iostream>
double calculate(double a, char op, double b) {
if (op == '+') return a + b;
if (op == '-') return a - b;
if (op == '*') return a * b;
if (op == '/') return a / b;
return 0;
}
int main() {
std::cout << calculate(10, '+', 5) << std::endl; // 15
std::cout << calculate(10, '*', 3) << std::endl; // 30
std::cout << calculate(10, '/', 4) << std::endl; // 2.5
return 0;
}
15
30
2.5
スコープ(変数の範囲)
関数内で宣言された変数は、 その関数のスコープ内でのみ有効です。 関数の外からはアクセスできません。
#include <iostream>
void testScope() {
int x = 10; // x はここで生成
std::cout << x << std::endl;
} // x はここで破棄される
int main() {
testScope(); // 出力: 10
// std::cout << x << std::endl; // エラー! x は存在しない
return 0;
}
このおかげで、異なる関数で同じ名前の変数を使ってもぶつかりません。
実践例
例1: 成績判定関数
#include <iostream>
char getGrade(int score) {
if (score >= 90) return 'A';
if (score >= 80) return 'B';
if (score >= 70) return 'C';
if (score >= 60) return 'D';
return 'F';
}
int main() {
int scores[] = {95, 75, 65, 55};
for (int i = 0; i < 4; i++) {
std::cout << "スコア: " << scores[i]
<< " 判定: " << getGrade(scores[i]) << std::endl;
}
return 0;
}
スコア: 95 判定: A
スコア: 75 判定: C
スコア: 65 判定: D
スコア: 55 判定: F
例2: 素数判定関数
#include <iostream>
bool isPrime(int num) {
if (num <= 1) return false;
if (num == 2) return true;
if (num % 2 == 0) return false;
for (int i = 3; i * i <= num; i += 2) {
if (num % i == 0) return false;
}
return true;
}
int main() {
for (int i = 1; i <= 20; i++) {
if (isPrime(i)) {
std::cout << i << " ";
}
}
std::cout << std::endl;
return 0;
}
2 3 5 7 11 13 17 19
ポイント
- 関数はコードの再利用と整理に必須
- 関数は戻り値の型・名前・引数・処理で構成
- void は戻り値がない場合に使用
- 関数内の変数はそのスコープ内でのみ有効
- 関数の宣言と定義を分けることで順序の問題を解決
よくある誤り
誤り1: 戻り値の型がない
add(int a, int b) { // 戻り値の型がない!
return a + b;
}
誤り2: return を忘れる
int multiply(int a, int b) {
int result = a * b;
// return を忘れた!
}
誤り3: 関数の宣言より先に使う
int main() {
int x = add(3, 5); // add はまだ宣言されていない!
return 0;
}
int add(int a, int b) {
return a + b;
}
やってみよう
練習1: 2つの点 (x1, y1) と (x2, y2) の距離を計算する関数を作成。
練習2: 3つの点の座標を受け取り、三角形の面積を計算する関数。
練習3: N番目のフィボナッチ数を計算する関数。
チャレンジ: ユーザーから得点を5つ受け取り、平均をともに出力する関数。関数内で入力を処理。
まとめ
- 関数で処理をまとめて再利用性を高める
- 戻り値・引数・スコープの概念を理解することが重要
- void で戻り値を返さない関数も作成できる
- プログラムが複雑になるほど、関数の価値が増す