C言語における関数設計とマクロ活用の実践

関数ベースのモジュール化プログラミング演習

本演習では、C言語における再利用可能な関数の設計・実装を主眼に、数学的アルゴリズムの実装と構造化されたプログラム構成を学ぶ。各課題は独立した機能単位(モジュール)として実装され、引数渡し、戻り値の取り扱い、条件検証などの基本概念を実践的に理解する。

1. 三角形面積の計算(ヘロンの公式)

三辺の長さから三角形の面積を求める関数 computeTriangleArea を実装する。入力値が三角形成立条件(任意の2辺の和 > 残り1辺)を満たすかを事前に検証し、不正な入力に対してはエラーメッセージを出力する。

#include <stdio.h>
#include <math.h>

double computeTriangleArea(double sideA, double sideB, double sideC) {
    double semiPerimeter = (sideA + sideB + sideC) / 2.0;
    double squaredArea = semiPerimeter * 
                         (semiPerimeter - sideA) * 
                         (semiPerimeter - sideB) * 
                         (semiPerimeter - sideC);
    return sqrt(squaredArea);
}

int main() {
    double a, b, c;
    printf("3辺の長さを入力してください(スペース区切り): ");
    if (scanf("%lf %lf %lf", &a, &b, &c) != 3) {
        printf("入力エラー\n");
        return 1;
    }

    if (a + b > c && a + c > b && b + c > a) {
        printf("面積: %.3f\n", computeTriangleArea(a, b, c));
    } else {
        printf("無効な三角形です\n");
    }
    return 0;
}

2. 階乗の逐次計算(非再帰・静的ローカル変数活用)

階乗を逐次生成する関数 nextFactorial を定義。静的変数を用いて前回の計算結果を保持し、呼び出し毎に次の整数の階乗値を返す。この手法は累積的な計算処理に適している。

#include <stdio.h>

long nextFactorial(int current) {
    static long result = 1;
    result *= current;
    return result;
}

int main() {
    const int LIMIT = 6;
    printf("1〜%d の階乗:\n", LIMIT);
    for (int i = 1; i <= LIMIT; ++i) {
        printf("%d! = %ld\n", i, nextFactorial(i));
    }
    return 0;
}

3. 最大公約数の算出(ユークリッドの互除法)

2つの整数の最大公約数(GCD)をユークリッドの互除法で求める関数 calculateGCD を実装。負の値やゼロへの対応を含め、堅牢な入力処理を行う。

#include <stdio.h>
#include <stdlib.h>

int calculateGCD(int x, int y) {
    x = abs(x); y = abs(y);
    while (y != 0) {
        int remainder = x % y;
        x = y;
        y = remainder;
    }
    return x;
}

int main() {
    int num1, num2;
    printf("2つの整数を入力: ");
    if (scanf("%d %d", &num1, &num2) == 2) {
        printf("GCD(%d, %d) = %d\n", num1, num2, calculateGCD(num1, num2));
    }
    return 0;
}

4. パターン描画(高さ指定のピラミッド)

指定された高さ n の星号ピラミッドを出力する関数 drawPyramid を作成。各行の先頭空白数と星号数を正確に制御し、整列された出力を実現する。

#include <stdio.h>

void drawPyramid(int height) {
    for (int row = 1; row <= height; ++row) {
        // 空白
        for (int space = 0; space < height - row; ++space) {
            putchar(' ');
        }
        // 星号
        for (int star = 0; star < 2 * row - 1; ++star) {
            putchar('*');
        }
        putchar('\n');
    }
}

int main() {
    int n;
    printf("ピラミッドの高さを入力: ");
    if (scanf("%d", &n) == 1 && n > 0) {
        drawPyramid(n);
    }
    return 0;
}

5. 友愛数ペアの探索(500未満)

友愛数(amicable numbers)とは、2つの異なる正の整数で、それぞれの「真の約数の和」が他方と等しくなる組のこと。関数 sumOfProperDivisors を用いて500未満の全友愛数ペアを列挙する。

#include <stdio.h>

int sumOfProperDivisors(int n) {
    if (n <= 1) return 0;
    int total = 1;
    for (int f = 2; f * f <= n; ++f) {
        if (n % f == 0) {
            total += f;
            if (f != n / f) total += n / f;
        }
    }
    return total;
}

int main() {
    const int UPPER_BOUND = 500;
    printf("500未満の友愛数ペア:\n");
    for (int a = 2; a < UPPER_BOUND; ++a) {
        int b = sumOfProperDivisors(a);
        if (b > a && b < UPPER_BOUND && sumOfProperDivisors(b) == a) {
            printf("(%d, %d)\n", a, b);
        }
    }
    return 0;
}

タグ: c-language function-design modular-programming euclidean-algorithm amicable-numbers

7月20日 22:20 投稿