前回の「簡易電卓プログラム(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除算などに対して丁寧に対応する |
コメント