`main(int argc, char *argv[])` 是程式與作業系統溝通的介面。本文實現一個接受命令列參數的整數計算器,支援加減乘除,並解析原始碼中「掃描輸入」與「命令列參數」混淆的關鍵錯誤。
**命令列參數模式**:
./calc -a 10 20 # 加法,輸出 30 ./calc -s 50 30 # 減法,輸出 20 ./calc -m 6 7 # 乘法,輸出 42 ./calc -d 100 4 # 除法,輸出 25
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int calculate(int a, int b, const char *op) {
if (strcmp(op, "-a") == 0) return a + b;
if (strcmp(op, "-s") == 0) return a - b;
if (strcmp(op, "-m") == 0) return a * b;
if (strcmp(op, "-d") == 0) {
if (b == 0) { fprintf(stderr, "除數不能為零\n"); exit(1); }
return a / b;
}
fprintf(stderr, "未知運算子: %s\n", op);
exit(1);
}
int main(int argc, char *argv[]) {
if (argc != 4) {
fprintf(stderr, "用法: %s <-a|-s|-m|-d> <整數1> <整數2>\n", argv[0]);
return 1;
}
char *endptr;
long a = strtol(argv[2], &endptr, 10);
if (*endptr != '\0') { fprintf(stderr, "無效整數: %s\n", argv[2]); return 1; }
long b = strtol(argv[3], &endptr, 10);
if (*endptr != '\0') { fprintf(stderr, "無效整數: %s\n", argv[3]); return 1; }
int result = calculate((int)a, (int)b, argv[1]);
printf("%ld %s %ld = %d\n", a, argv[1], b, result);
return 0;
}
// 原始碼錯誤邏輯:
int main() { // 非標準 main 簽名,無 argc/argv
char a, b; char *p = &b;
int num1, num2;
scanf("%d%c%d", &num1, &a, &num2); // 掃描標準輸入,非命令列參數!
// ... 將運算子映射為 -a/-s/-m/-d 字串
// 字串比較用 == (比較指標地址),非 strcmp (比較內容)
if (p == "-a") // 錯誤!應用 strcmp(p, "-a") == 0
| 錯誤類型 | 原始碼 | 正確做法 |
|---|---|---|
| main 簽名 | `int main()` | `int main(int argc, char *argv[])` |
| 參數來源 | `scanf` 讀標準輸入 | `argv[1]`, `argv[2]`, `argv[3]` |
| 字串比較 | `p == "-a"` (指標比較) | `strcmp(p, "-a") == 0` |
| 整數解析 | `scanf("%d%c%d")` 易殘留換行 | `strtol` 完整錯誤檢查 |
| 除零檢查 | 無 | `if (b==0) error` |
#includestatic struct option long_opts[] = { {"add", no_argument, 0, 'a'}, {"subtract", no_argument, 0, 's'}, {"multiply", no_argument, 0, 'm'}, {"divide", no_argument, 0, 'd'}, {0, 0, 0, 0} }; int main(int argc, char *argv[]) { int opt, op = 0; while ((opt = getopt_long(argc, argv, "asmd", long_opts, NULL)) != -1) { switch (opt) { case 'a': op = 1; break; // add case 's': op = 2; break; // subtract case 'm': op = 3; break; // multiply case 'd': op = 4; break; // divide default: return 1; } } if (optind + 2 != argc) { /* usage */ return 1; } long a = strtol(argv[optind], NULL, 10); long b = strtol(argv[optind+1], NULL, 10); // ... 計算並輸出 }
**命令列參數 ≠ 標準輸入掃描**。正確使用 `argc/argv`、`strcmp`、`strtol`、`getopt` 是系統級工具開發的基礎技能。原始碼混淆了兩種輸入模式,且字串比較用 `==` 導致邏輯失效。標準實現應支援:`./calc -a 10 20`、`./calc --add 10 20` 等多種呼叫方式,完整錯誤處理與用法提示。