讀取多行 a/b+c/d 或 a/b-c/d,輸出最簡分數結果。分子分母為整數,結果須約分、分母為正、整數輸出無分母、零輸出 0。
typedef struct { int num; int den; } Fraction; // 分子、分母
scanf("%d / %d %c %d / %d", &a, &b, &op, &c, &d),允許空白。op=='-' ? c=-c : 0。lcm = lcm(b, d),num = a*lcm/b + c*lcm/d,den = lcm。g = gcd(|num|, |den|),num/=g; den/=g;。0。#include <stdio.h>
#include <stdlib.h>
typedef struct { int num, den; } Fraction;
int gcd(int a, int b) { return b ? gcd(b, a%b) : a; }
int lcm(int a, int b) { return a / gcd(a,b) * b; }
void reduce(Fraction *f) {
int g = gcd(abs(f->num), abs(f->den));
f->num /= g; f->den /= g;
if (f->den < 0) { f->num = -f->num; f->den = -f->den; }
}
void print_frac(Fraction f) {
if (f.num == 0) { puts("0"); return; }
if (f.num < 0) { putchar('-'); f.num = -f.num; }
if (f.den == 1) printf("%d\n", f.num);
else printf("%d/%d\n", f.num, f.den);
}
int read_frac(Fraction *f) {
return scanf("%d / %d", &f->num, &f->den) == 2;
}
int read_expr(Fraction *f1, char *op, Fraction *f2) {
if (!read_frac(f1)) return 0;
if (scanf(" %c", op) != 1) return 0;
if (*op != '+' && *op != '-') return 0;
if (!read_frac(f2)) return 0;
return 1;
}
int main() {
Fraction f1, f2; char op;
while (read_expr(&f1, &op, &f2)) {
if (f1.den == 0 || f2.den == 0) { puts("分母不可為零"); continue; }
if (op == '-') f2.num = -f2.num;
int L = lcm(abs(f1.den), abs(f2.den));
f1.num = f1.num * (L / f1.den) + f2.num * (L / f2.den);
f1.den = L;
reduce(&f1);
print_frac(f1);
}
return 0;
}
輸入: 1/8+3/8 1/4-1/2 1/3-1/3 輸出: 1/2 -1/4 0
scanf("%d / %d") 中的空白可匹配任意空白字元,極具彈性。lcm 計算先除後乘避免溢位:a/gcd*a*b。0,避免 0/1。| 錯誤 | 錯誤代碼 | 正確做法 |
|---|---|---|
| 未檢查分母為零 | 直接通分 | 讀入後立即判斷 |
| 減法未轉加法 | 分開邏輯 | if(op=='-') c=-c; 統一加法 |
| 約分用輾轉相除但未取絕對值 | gcd(a,b) 直接用負數 | gcd(abs(a),abs(b)) |
| 輸出格式不符 | 負號在分母、整數仍印分母 | 統一格式化函數處理 |