但是,上述的方法所提供的代码还是存在着问题,需要进一步修改。
首先,因为 frac 这个结构的成员函数和其它操作函数已被声明并定义至一个单一的文件里,
因此,首先要将它的声明和定义分开来。把 frac 结构体抽离至封装的类以外,作为前置声明。
因为原代码是直接 printf() 输出的,而我们需要的是获取它输出的结果。
所以,改变它输出的位置,声明一个 string ,将配好以后的结果直接赋值到 string 里。
最终代码实现:
[C++ 源代码]
/* Exzh Cross Platfrom Toolkit (ECPT) Qt Version
* (This file is the part of the ECPT Project)
* Author: Exzh_PMGI
* E-mail: [email protected]
* License: LGPL v3.0 / Exzh Commerical License
* Copyright: (C) Exzh_PMGI
* Qt Framework 5.10 has been tested successfully
* If you want to use the code for business,
* please contact me by my email.
*/ #include "exequationbalancer.h" #include <QDebug> int gcd(int x, int y) {
return x % y == ? y : gcd(y, x%y);
} int lcm(int x, int y) {
return x * y / gcd(x, y);
} frac createFrac(int a, int b)
{
frac tmp = { a,b };
return tmp;
} frac Abs(frac x) {
int p = x.a> ? x.a : -x.a, q = x.b> ? x.b : -x.b;
return createFrac(p, q);
} string exEquationBalancer::getResult(string inputstr)
{
strcpy(s,inputstr.c_str());
int lst = ;
for (int i = ;i<strlen(s);i++) {
if (i == strlen(s) - )scan(lst, i);
if (s[i] == '+' || s[i] == '=')
{
scan(lst, i - );
lst = i + ;
}
if (s[i] == '=')flag = -; //等号后面的系数变负
}
if (Solve())
for (int i = ;i <= c2 - ;i++)
ans[i] = M[i][N + ];
else output+="No Solution";
int tmp = lcm(ans[].b, ans[].b);
for (int i = ;i <= c2;i++)tmp = lcm(tmp, ans[i].b);
for (int i = ;i <= c2;i++)Ans[i] = ans[i].a*tmp / ans[i].b; //取分母Lcm,把分数变整数
for (int i = ;i <= c2;i++)
{
if (Ans[i]>) output+=to_string(Ans[i]);
for (int j = ;j<strlen(mat[i]);j++)
output+=mat[i][j];
if (i == c2)
{
return output;
qDebug()<<QString::fromStdString(output);
}
else if (i == c1) output+="=";
else output+="+";
}
} bool exEquationBalancer::Solve() { //解方程 (矩阵 高cnt,宽c2+1,c2+1列常数全0)
ans[c2] = ; //令最后一个解为1
for (int i = ;i <= cnt;i++) {
for (int j = ;j <= c2;j++)
M[i][j] = fun[i][j];
}
for (int i = ;i <= cnt;i++)
M[i][c2].a = -M[i][c2].a; //移到常数
//高斯消元过程
N = c2 - , K = cnt;
for (int k = ;k <= N;k++) {
frac maxm = createFrac(-, );
int maxi;
for (int i = k;i <= K;i++)
if (maxm<Abs(M[i][k]))
maxm = Abs(M[i][k]), maxi = i;
if (maxm == createFrac(, ))
return false;
if (maxi != k)
for (int j = ;j <= N + ;j++) {
swap(M[k][j], M[maxi][j]);
}
frac tmp = M[k][k];
for (int j = ;j <= N + ;j++)
M[k][j] = M[k][j] / tmp;
for (int i = k - ? : ;i <= K;i++) {
if (i == k)continue;
frac tmp = M[i][k];
for (int j = ;j <= N + ;j++)
M[i][j] = M[i][j] - tmp * M[k][j];
}
}
return true;
} void exEquationBalancer::scan(int l, int r) { //处理物质
c2++;
for (int i = ;i <= r - l;i++)mat[c2][i] = s[l + i]; //存下元素的名字
if (flag == )c1++; //统计一下反应物数量
int tmp = ; //tmp是小括号倍数
for (int i = l;i <= r;i++) {
if (s[i] == ')')tmp = ;
if (s[i] == '(') {
int j = i + ;while (s[j] != ')')j++; //找这个括号的范围
tmp = getint(j); //读")"右边的数字
}
if (s[i] >= 'A'&&s[i] <= 'Z') { //发现元素
int x = s[i] - 'A' + , y = ;
if (s[i + ] >= 'a'&&s[i] <= 'z') //看一眼是一个字母的还是两个的
y = s[i + ] - 'a' + ;
if (!Map[x][y])Map[x][y] = ++cnt; //判重
fun[Map[x][y]][c2] += flag * getint(i)*tmp; //把这个物质里的这种元素数量放进矩阵里,坐标(map[x][y],c2)
}
}
} int exEquationBalancer::getint(int pos) { //读数
pos++;
if (s[pos] >= 'a'&&s[pos] <= 'z')pos++;
if (s[pos]<'' || s[pos]>'')return ; //没数就是1
else {
int x = ;
while (s[pos] >= ''&&s[pos] <= '')x = x * + s[pos] - '', pos++; //读元素后面的数字
return x;
}
} void exEquationBalancer::print() {
output += to_string(N);
output += " ";
output += to_string(K);
output += "\n";
for (int i = ;i <= K;i++) {
for (int j = ;j <= N + ;j++)
{
output += to_string(M[i][j].a);
output += " ";
}
output += "\n";
}
output += "\n";
}
[C++ 头文件]
/* Exzh Cross Platfrom Toolkit (ECPT) Qt Version
* (This file is the part of the ECPT Project)
* Author: Exzh_PMGI
* E-mail: [email protected]
* License: LGPL v3.0 / Exzh Commerical License
* Copyright: (C) Exzh_PMGI
* Qt Framework 5.10 has been tested successfully
* If you want to use the code for business,
* please contact me by my email.
*/ #ifndef EXEQUATIONBALANCER_H
#define EXEQUATIONBALANCER_H #include <string>
#include "../exstdc++.h" using namespace std;
static string output;
int lcm(int x, int y);
int gcd(int x, int y); struct frac { //分数类
int a, b;
void reduce() {
int x = gcd(a, b);
a /= x, b /= x;
}
frac createFrac(int a, int b)
{
frac tmp = { a,b };
return tmp;
}
frac operator = (int x) {
a = x, b = ;
return *this;
}
frac operator = (const frac x) {
a = x.a, b = x.b;
reduce();
return *this;
}
frac operator + (const frac x) {
return createFrac(b*x.a + a * x.b, b*x.b);
}
frac operator - (const frac x) {
return createFrac(a*x.b - b * x.a, b*x.b);
}
frac operator * (const frac x) {
return createFrac(a*x.a, b*x.b);
}
frac operator / (const frac x) {
return createFrac(a*x.b, b*x.a);
}
bool operator < (const frac x) {
return a * x.b<b*x.a;
}
bool operator == (const frac x) {
return a * x.b == b * x.a;
}
void print() {
if (b == )
{
output += to_string(a);
output += "\n";
}
else
{
output += to_string(a);
output += "/";
output += to_string(b);
}
}
}; frac createFrac(int a, int b);
frac Abs(frac x); class exEquationBalancer
{
public:
string getResult(string inputstr); private:
bool Solve();
void scan(int l, int r);
int getint(int pos);
void print(); char s[];
int fun[][];
int Map[][]; //手动MAP
frac M[][]; //求解矩阵
frac ans[]; //解
int Ans[]; //整数解
int cnt, c1, c2, flag = , N, K; //cnt数元素,c1数反应物,c2总数 (未知数的数量)
char mat[][]; //存储物质的名称
}; #endif // EXEQUATIONBALANCER_H