编辑人:Alant
编辑时间:2023年12月7日
题目链接
完整题目
题目描述:
写一个C程序求一元一次方程的根。方程的基本形式如下: ax op1 b=cx op2 d
a、b、c、d均为大于1且不超过100的整数,其中a-c不等于0,op1和op2为‘+’或'-'。等式的一侧最多两项,最少一项。等号两边的px op q也可能写成q op px。另外,方程中可能有空格。
下面是几个方程的例子: 2x+2=3x+3 2 x + 2 = 4 - 3 x 2-5x = 2 2=4x 4x=2
输入:
一个一元一次方程。其中30%的数据是ax=b的形式,不会做复杂的可以只按这种方式处理。
输出:
输出如"x=root"的形式。根为整数直接输出,如果为分数则输出最简分数形式。
样例输入1
3x+2=2x+4
样例输出1
x=2
样例输入2
3-6x=6
样例输出2
x=-1/2
样例输入3
2=4x
样例输出3
x=1/2
考点解析
-
特殊输入:当字符串内部含有特殊字符时,应该采取什么样的策略?可以使用
while(scanf("...",&...)!=EOF)
的形式对特殊字符进行过滤,笔者这里采用的是getline函数。 -
分数最简化:如何判断结果是否最简以及如何正确化简,进一步说就是如何求两数的最大公因子,可以使用辗转相除法递归求取。
注意事项
-
笔者并不是专业的算法爱好者,本题解仅提供一种融合
面向对象思想
的题解示例,希望以此抛砖引玉,其中不乏不规范、不简洁、不标准以及现阶段课程未学习的用法,请各位读者见谅,必要时可借助GPT辅助理解。 -
本题解并未经过全面覆盖测试,可能存在并未考虑到的极端特殊情况,请各位读者慎重参考。
核心思想
将方程式化为形如ax=b
的格式
代码流程
-
对输入的方程式进行数据预处理(即删除空格)
-
在字符串中搜索下一个“数据项”的开始、结束下标(数据项:形如
x
、5x
、-3x
、678
、-48
的子串)并更新 -
提取每一个数据项包含的数据
-
如果该数据是变量的系数,则放入a;如果是常数,则放入b(如果跨越
=
会对符号产生变化) -
重复2-4直至所有数据项均被处理
完整代码
#include <iostream>
using namespace std;
// 在字符串s中寻找下一个数据项的开始、结束下标
void nextData(int* start, int* end, string s) {
for (*end = *start; *end <= s.length(); (*end)++) {
if (s[*end] == '=') {
(*end)--;
return;
}
if (*end + 1 >= s.length() || s[*end + 1] == '+' || s[*end + 1] == '-') {
return;
}
}
}
// 提取每一个数据项包含的数据
int getNumFromData(string s) {
int symbol = s[0] == '-' ? -1 : 1;
int num = 0;
if (s[0] == '-' && s[1] == 'x')return -1;
if (s[0] == 'x' || (s[0] == '+' && s[1] == 'x'))return 1;
for (int i = 0; i < s.length(); i++) {
if (s[i] < '0' || s[i] > '9')continue;
else {
num = num * 10 + int(s[i] - '0');
}
}
return num * symbol;
}
// 计算a、b的最大公因子
int getMaxCommonFactor(int a, int b) {
int commonFactor = 1;
for (int i = 2; i <= min(a, b); i++) {
if (a % i == 0 && b % i == 0)commonFactor = i;
}
return commonFactor;
}
// 打印结果,该函数还包含了化简的业务功能
void printAns(int a, int b) {
int maxCommonFactor = getMaxCommonFactor(abs(a), abs(b));
a /= maxCommonFactor;
b /= maxCommonFactor;
if (a < 0 && b < 0) {
a *= -1;
b *= -1;
}
if (a == 1) {
cout << "x=" << b;
return;
}
if (b == 0) {
cout << "x=0";
return;
}
if (b < a) {
if (a * b > 0) {
cout << "x=" << to_string(abs(b)) + "/" + to_string(abs(a));
} else {
cout << "x=-" << to_string(abs(b)) + "/" + to_string(abs(a));
}
} else {
if (a * b > 0) {
if (b % a == 0)cout << "x=" + to_string(b / a);
else cout << "x=" << to_string(b) << "/" << to_string(a);
} else {
if (b % a == 0)cout << "x=-" + to_string(b / a);
else cout << "x=-" << to_string(abs(b)) << "/" << to_string(abs(a));
}
}
}
// 主函数
int main() {
string _s;
getline(cin, _s);
string s;
for (int i = 0; i < _s.length(); i++) {
if (_s[i] != ' ') {
s += _s[i];
}
}
int a = 0, b = 0;
int start = 0, end = 999999;
int equal = 1;
while (s[equal] != '=')equal++;
while (start < s.length()) {
nextData(&start, &end, s);
int num = getNumFromData(s.substr(start, end - start + 1));
if (s[end] == 'x' && start < equal)a += num;
else if (s[end] == 'x' && start > equal)a += num * -1;
else if (s[end] != 'x' && start > equal)b += num;
else if (s[end] != 'x' && start < equal)b += num * -1;
start = end + 1;
if (start < s.length() && s[start] == '=')start++;
}
printAns(a, b);
return 0;
}
更多测试数据
99+6x=5+2x
16+3x = 4 +12x
5+2x=6x+99
5x=100
8x=12
5+3x = 2x-3
5+ 3 x = 2 x- 3
-999=x
x=0
扩展思考
-
op如果包含*、/,如何求解?
-
如果是二元一次方程,如何求解?
-
如果是多元一次方程组,如何求解?
友情链接
Homemade Strategic Office Capability 国产战略办公能力
青年大学习之高效使用办公软件(持续更新Word、PPT、Excel的使用技巧,不定期分享免费PPT模板)
详情请至gitee搜索开源库Alant/HSOC ☆