23 関数

処理に名前をつけて再利用できる「関数」を学ぶ。
関数を使うとコードが整理され、同じ処理を何度でも呼び出せるようになる。


23-1 関数とは

これまでのプログラムはすべて main() の中に書いてきた。
処理が増えると main がどんどん長くなり、読みにくくなる。

関数は「ひとまとまりの処理に名前をつけて、呼び出せるようにしたもの」。

要素意味なくてもよいか
引数(パラメータ)呼び出し元から受け取る値なくてもよい(void)
戻り値(返却値)呼び出し元へ返す値なくてもよい(void)

23-2 引数なし・戻り値なし

void 関数名(void) {
    /* 処理 */
}
23_01_hello.c
#include <stdio.h>

void hello(void)
{
    printf("Hello, World!\n");
}

int main(void)
{
    hello();   /* 関数を呼び出す */
    hello();   /* 何度でも呼び出せる */
    return 0;
}
Hello, World!
Hello, World!
✅ 同じ処理を繰り返したいとき、関数にしておくと1か所を直すだけで全体に反映できる。

23-3 引数あり・戻り値なし

void 関数名(データ型 引数名) {
    /* 処理 */
}
23_02_greet.c
#include <stdio.h>

void printTimes(int times)   /* times という名前で int を受け取る */
{
    int i;
    for (i = 0; i < times; i++) {
        printf("こんにちは\n");
    }
}

int main(void)
{
    printTimes(3);   /* 3 を渡す */
    printTimes(1);   /* 1 を渡す */
    return 0;
}
こんにちは
こんにちは
こんにちは
こんにちは
23_03_printSum.c
#include <stdio.h>

void printSum(int a, int b)   /* 2つの引数を受け取る */
{
    printf("%d + %d = %d\n", a, b, a + b);
}

int main(void)
{
    printSum(10, 5);
    printSum(3, 7);
    return 0;
}
10 + 5 = 15
3 + 7 = 10

23-4 引数なし・戻り値あり

データ型 関数名(void) {
    return 値;
}
23_04_getValue.c
#include <stdio.h>

int getFixed(void)
{
    return 7 * 3;   /* 計算結果を返す */
}

int main(void)
{
    int result = getFixed();
    printf("結果: %d\n", result);
    return 0;
}
結果: 21

23-5 引数あり・戻り値あり

最もよく使う形。受け取った値を計算して返す。

23_05_add.c
#include <stdio.h>

int add(int a, int b)
{
    return a + b;
}

int main(void)
{
    int result = add(10, 15);
    printf("合計: %d\n", result);
    return 0;
}
合計: 25
23_06_multiply.c
#include <stdio.h>

double multiply(int x, double y)
{
    return x * y;
}

int main(void)
{
    double result = multiply(3, 2.5);
    printf("積: %.2f\n", result);
    return 0;
}
積: 7.50

23-6 4パターンのまとめ

引数戻り値定義の形用途例
なしなしvoid f(void)メッセージ表示など
ありなしvoid f(int x)受け取った値を表示
なしありint f(void)固定値・設定値を返す
ありありint f(int a, int b)計算・変換など

23-7 演習

📝 演習① 絶対値を返す関数

整数を受け取り、絶対値を返す関数 absVal(int x) を作れ。

23_07_absVal.c
#include <stdio.h>

int absVal(int x)
{
    /* ここを書く */
}

int main(void)
{
    printf("%d\n", absVal(-5));   /* 5 */
    printf("%d\n", absVal(3));    /* 3 */
    printf("%d\n", absVal(0));    /* 0 */
    return 0;
}
答えの例を表示
int absVal(int x)
{
    if (x < 0) {
        return -x;
    }
    return x;
}
📝 演習② 大きい方を返す関数

2つの整数を受け取り、大きい方を返す関数 maxOf(int a, int b) を作れ。

23_08_maxOf.c
#include <stdio.h>

int maxOf(int a, int b)
{
    /* ここを書く */
}

int main(void)
{
    printf("%d\n", maxOf(10, 5));    /* 10 */
    printf("%d\n", maxOf(3, 8));     /* 8 */
    printf("%d\n", maxOf(-2, -5));   /* -2 */
    return 0;
}
答えの例を表示
int maxOf(int a, int b)
{
    if (a >= b) {
        return a;
    }
    return b;
}
📝 演習③ 合計と平均を表示する関数

配列と要素数を受け取り、合計と平均を表示する関数 printStats を作れ。

23_09_stats.c
#include <stdio.h>

void printStats(int data[], int n)
{
    /* ここを書く */
}

int main(void)
{
    int scores[5] = {80, 70, 90, 60, 85};
    printStats(scores, 5);
    return 0;
}
答えの例を表示
void printStats(int data[], int n)
{
    int i, sum = 0;
    for (i = 0; i < n; i++) {
        sum += data[i];
    }
    printf("合計: %d\n", sum);
    printf("平均: %.1f\n", (double)sum / n);
}

23-8 理解度チェック

Q1. 次のプログラムの出力として正しいものはどれか。

#include <stdio.h>
void printLine(void)
{
    printf("AAAA");
}
int main(void)
{
    printLine();
    printLine();
    return 0;
}
解説を表示

正解:イ

printLine() が2回呼ばれ、\n がないため「AAAA」が続けて出力される。

Q2. 次のプログラムの出力として正しいものはどれか。

#include <stdio.h>
int add(int a, int b)
{
    return a + b;
}
int main(void)
{
    printf("%d\n", add(3, add(4, 5)));
    return 0;
}
解説を表示

正解:ウ(12)

内側の add(4, 5) = 9 が先に評価され、add(3, 9) = 12 になる。

Q3. 戻り値なし・引数なしの関数定義として正しいものはどれか。

解説を表示

正解:ウ

戻り値なしは void、引数なしも void と書く。順番は「戻り値の型 関数名(引数)」。

Q4. 関数を使う利点として正しいものはどれか。

解説を表示

正解:イ

再利用性・可読性・保守性の向上が関数の主な利点。修正が1か所で済む。