洛谷P1572题解:分数运算的奥秘,新手也能看懂的超详细教程

二、详细技术讲解
1. 分数表示与运算
我们使用一个简单的结构体Fraction来表示分数,包含分子和分母两个成员变量。结构体中实现了两个关键方法:
simplify(): 用于化简分数,通过计算分子分母的最大公约数,并将分数化为最简形式operator+: 重载加法运算符,实现分数的加法运算
2. 字符串解析
解析输入字符串是本题的关键难点。我们需要处理以下几种情况:
正负号的处理:每个分数可能有自己的正负号
分子和分母的分离:通过'/'字符分隔
运算符的识别:'+'或'-'符号
解析过程采用逐个字符扫描的方式:
首先处理可能的符号位
然后读取数字部分作为分子
如果遇到'/',则继续读取分母
否则视为整数(分母为1)
最后记录运算符
3. 计算过程
计算过程相对简单:
初始化结果为第一个分数
根据运算符决定后续分数是加还是减
逐个进行分数运算
每次运算后自动化简结果
4. 结果输出
最终结果需要根据分母是否为1决定输出形式:
分母为1:输出整数形式
否则:输出分数形式
三、完整代码
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
// 计算最大公约数
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
// 分数结构体
struct Fraction {
int numerator; // 分子
int denominator; // 分母
// 化简分数
void simplify() {
int common = gcd(abs(numerator), abs(denominator));
numerator /= common;
denominator /= common;
// 确保分母为正
if (denominator < 0) {
numerator *= -1;
denominator *= -1;
}
}
// 分数加法
Fraction operator+(const Fraction& other) const {
Fraction result;
result.numerator = numerator * other.denominator + other.numerator * denominator;
result.denominator = denominator * other.denominator;
result.simplify();
return result;
}
};
int main() {
string s;
getline(cin, s);
vector<Fraction> fractions;
vector<char> operators;
// 解析字符串
int i = 0;
while (i < s.size()) {
// 解析分子
int sign = 1;
if (s[i] == '-') {
sign = -1;
i++;
} else if (s[i] == '+') {
i++;
}
int num = 0;
while (i < s.size() && isdigit(s[i])) {
num = num * 10 + (s[i] - '0');
i++;
}
num *= sign;
// 解析分母
if (i < s.size() && s[i] == '/') {
i++;
int den = 0;
while (i < s.size() && isdigit(s[i])) {
den = den * 10 + (s[i] - '0');
i++;
}
fractions.push_back({num, den});
} else {
// 整数视为分母为1的分数
fractions.push_back({num, 1});
}
// 记录运算符
if (i < s.size() && (s[i] == '+' || s[i] == '-')) {
operators.push_back(s[i]);
i++;
}
}
// 计算结果
Fraction result = fractions[0];
for (int j = 0; j < operators.size(); j++) {
Fraction next = fractions[j + 1];
if (operators[j] == '-') {
next.numerator *= -1;
}
result = result + next;
}
// 输出结果
if (result.denominator == 1) {
cout << result.numerator << endl;
} else {
cout << result.numerator << "/" << result.denominator << endl;
}
return 0;
}四、常见问题解答
Q: 如何处理连续的运算符?
A: 题目保证输入合法,不会出现连续的运算符。
Q: 如何处理分母为0的情况?
A: 题目保证输入合法,不会出现分母为0的情况。
Q: 为什么要在化简函数中处理分母的符号?
A: 这是为了统一分数的表示形式,确保分母始终为正数,便于比较和后续处理。
五、扩展思考
如何扩展支持乘除法运算?
如何处理带括号的表达式?
如何支持混合数(如3又1/2)的输入?
六、总结
通过这道题目,我们学习了:
字符串解析的技巧
分数运算的原理
运算符重载的应用
代码结构化的设计方法
掌握这些基础知识对于解决更复杂的计算问题至关重要。
原创内容 转载请注明出处
