C言語のきほん「簡易電卓プログラム(3)改良第2版」

スポンサーリンク
C言語

前回の「簡易電卓プログラム(2)改良版」をさらに改良してみよう。

✅ 改良点

  • 関数分割
    初期処理、入力処理、演算処理などを関数化する。
  • 重複除去
    q/cの処理や演算処理を共通化する。
  • コメント追加
    読みやすさを向上する。
  • 変数名の明確化
    意味が分かるように命名する。
//簡易電卓(改良第2版)

#include <stdio.h>
#include <string.h>
#include <ctype.h>

#define STR_SIZE 100

// 入力バッファをクリア
void clear_input_buffer(void) {
    int c;
    while ((c = getchar()) != '\n' && c != EOF) {}
}

// 初期メッセージを表示
void print_intro(void) {
    printf("\n--- 簡易電卓プログラム ---\n");
    printf("四則演算 (+ - * /) に対応\n");
    printf("最初の入力例: 3+5\n");
    printf("続けて入力: *8\n");
    printf("計算リセット: c\n");
    printf("終了: q\n");
    printf("--------------------------\n");
}

// 入力末尾の改行を取り除く
void strip_newline(char *str) {
    size_t len = strlen(str);
    if (len > 0 && (str[len - 1] == '\n' || str[len - 1] == '\r')) {
        str[len - 1] = '\0';
    }
}

// コマンドチェック
char check_command(const char *input) {
    if (strcmp(input, "q") == 0) return 'q';
    if (strcmp(input, "c") == 0) return 'c';
    return '\0';
}

// 演算処理
int apply_operator(double *result, char op, double num) {
    switch (op) {
        case '+': *result += num; break;
        case '-': *result -= num; break;
        case '*': *result *= num; break;
        case '/':
            if (num == 0.0) {
                printf("エラー: 0で割ることはできません。\n");
                return 0;
            }
            *result /= num;
            break;
        default:
            printf("無効な演算子が入力されました。\n");
            return 0;
    }
    return 1;
}

int main(void) {
    double result = 0.0;
    double num;
    char input[STR_SIZE];
    char op;
    int is_first_input = 1;

    print_intro();

    while (1) {
        if (is_first_input) {
            printf("最初の数式を入力してください (例: 3+5): ");
            if (!fgets(input, sizeof(input), stdin)) break;
            strip_newline(input);

            char cmd = check_command(input);
            if (cmd == 'q') break;
            if (cmd == 'c') {
                printf("計算結果をリセットしました。\n");
                result = 0.0;
                print_intro();
                continue;
            }

            if (sscanf(input, "%lf%c%lf", &result, &op, &num) == 3) {
                if (!apply_operator(&result, op, num)) {
                    result = 0.0;
                    continue;
                }
                printf("現在の計算結果: %g\n", result);
                printf("--------------------------\n");
                is_first_input = 0;
            } else {
                printf("無効な入力です。再度お試しください。\n");
            }
        } else {
            printf("続けて演算子と数値を入力してください (例: *8), c(クリア), q(終了): ");
            if (!fgets(input, sizeof(input), stdin)) break;
            strip_newline(input);

            char cmd = check_command(input);
            if (cmd == 'q') break;
            if (cmd == 'c') {
                printf("計算結果をリセットしました。\n");
                result = 0.0;
                is_first_input = 1;
                print_intro();
                continue;
            }

            if (sscanf(input, "%c%lf", &op, &num) == 2) {
                if (!apply_operator(&result, op, num)) continue;
                printf("現在の計算結果: %g\n", result);
                printf("--------------------------\n");
            } else {
                printf("無効な入力です。再度お試しください。\n");
            }
        }
    }

    printf("プログラムを終了します!\n");
    return 0;
}

実行結果

--- 簡易電卓プログラム ---
四則演算 (+ - * /) に対応
最初の入力例: 3+5
続けて入力: *8
計算リセット: c
終了: q
--------------------------
最初の数式を入力してください (例: 3+5): 4+7
現在の計算結果: 11
--------------------------
続けて演算子と数値を入力してください (例: *8), c(クリア), q(終了): /0
エラー: 0で割ることはできません。
続けて演算子と数値を入力してください (例: *8), c(クリア), q(終了): /5
現在の計算結果: 2.2
--------------------------
続けて演算子と数値を入力してください (例: *8), c(クリア), q(終了): *7
現在の計算結果: 15.4
--------------------------
続けて演算子と数値を入力してください (例: *8), c(クリア), q(終了): *23
現在の計算結果: 354.2
--------------------------
続けて演算子と数値を入力してください (例: *8), c(クリア), q(終了): q
プログラムを終了します!

✅ 改良ポイントまとめ

改善項目内容
strip_newline() を追加改行コードの違いによる比較失敗を回避する
check_command() の信頼性UP改行除去後の文字列と比較している
コマンド入力の安定動作“q\n”, “c\n” に依存しないため OS 依存を解消した
エラー発生時の明確な挙動入力ミス・0除算などに対して丁寧に対応する

コメント

タイトルとURLをコピーしました