jjyz 发表于 2025-5-5 13:06:26

一个简易的C++计算器

本帖最后由 jjyz 于 2025-5-5 13:06 编辑

作为一个初一的学生,有点兴趣爱好是正常的,这是我用空闲时间搓出来的一个作品(根据其他人的作品改编,增加了步骤以及解一元一次方程):
我就只展示我更改的部分吧
1.计算步骤解析:double getVal(double &s, double e, string str) {
        if (str == '(' || str == '[' || str == '{') {
                double news, newe, i;
                i = 1;
                news = s + 1;
                while (i) {
                        s++;
                        if (s == e)
                                break;
                        if (str == '(' || str == '[' || str == '{')
                                i++;
                        else if (str == ')' || str == ']' || str == '}')
                                i--;
                }
                newe = s - 1;
                s++;
                double result = cal(news, newe, str);
                cout << "计算括号内表达式 " << str.substr(news, newe - news + 1) << " 的值为: " << result << endl;
                return result;
        }
        double val;
        if (str == 's') {
                s = s + 3;
                double arg = getVal(s, e, str);
                val = sin(arg);
                cout << "计算 sin(" << arg << ") 的值为: " << val << endl;
        } else if (str == 'c') {
                s = s + 3;
                double arg = getVal(s, e, str);
                val = cos(arg);
                cout << "计算 cos(" << arg << ") 的值为: " << val << endl;
        } else if (str == 't') {
                s = s + 3;
                double arg = getVal(s, e, str);
                val = tan(arg);
                cout << "计算 tan(" << arg << ") 的值为: " << val << endl;
        } else if (str == 'a') {
                s++;
                if (str == 's') {
                        s = s + 3;
                        double arg = getVal(s, e, str);
                        val = asin(arg);
                        cout << "计算 asin(" << arg << ") 的值为: " << val << endl;
                } else if (str == 'c') {
                        s = s + 3;
                        double arg = getVal(s, e, str);
                        val = acos(arg);
                        cout << "计算 acos(" << arg << ") 的值为: " << val << endl;
                } else if (str == 't') {
                        s = s + 3;
                        double arg = getVal(s, e, str);
                        val = atan(arg);
                        cout << "计算 atan(" << arg << ") 的值为: " << val << endl;
                }
        } else if (str >= '0' && str <= '9') {
                val = str - '0';
                while (s < e && str >= '0' && str <= '9') {
                        val *= 10;
                        val += str - '0';
                }
                if (str == '!') {
                        int n = static_cast<int>(val);
                        val = f(n);
                        cout << "计算 " << n << "! 的值为: " << val << endl;
                        s++;
                }
                if (str == '.') {
                        s = s + 1;
                        double val2 = str - '0';
                        while (s < e && str >= '0' && str <= '9') {
                                val2 *= 10;
                                val2 += str - '0';
                        }
                        while (val2 >= 1) {
                                val2 /= 10;
                        }
                        val = val + val2;
                        cout << "处理小数部分,得到值为: " << val << endl;
                }
        }
        return val;
}
2:解一元一次方程:// 解析方程,将方程分为左右两部分
void parseEquation(const string& equation, string& left, string& right) {
        size_t equalPos = equation.find('=');
        if (equalPos != string::npos) {
                left = equation.substr(0, equalPos);
                right = equation.substr(equalPos + 1);
        }
}

// 合并同类项,计算 x 的系数和常数项
void collectTerms(const string& expr, double& xCoeff, double& constant) {
        double currentCoeff = 1;
        double currentSign = 1;
        double num = 0;
        bool hasX = false;
        for (size_t i = 0; i < expr.length(); ++i) {
                if (isdigit(expr)) {
                        num = num * 10 + (expr - '0');
                } else if (expr == 'x') {
                        hasX = true;
                        if (i == 0 || !isdigit(expr)) {
                                num = 1;
                        }
                } else if (expr == '+' || expr == '-') {
                        if (hasX) {
                                xCoeff += currentSign * currentCoeff * num;
                        } else {
                                constant += currentSign * num;
                        }
                        num = 0;
                        hasX = false;
                        currentSign = (expr == '+') ? 1 : -1;
                        currentCoeff = 1;
                }
        }
        if (hasX) {
                xCoeff += currentSign * currentCoeff * num;
        } else {
                constant += currentSign * num;
        }
}

// 解一元一次方程
double solveEquation(const string& equation) {
        string left, right;
        parseEquation(equation, left, right);

        double leftXCoeff = 0, leftConstant = 0;
        double rightXCoeff = 0, rightConstant = 0;

        collectTerms(left, leftXCoeff, leftConstant);
        collectTerms(right, rightXCoeff, rightConstant);

        double totalXCoeff = leftXCoeff - rightXCoeff;
        double totalConstant = rightConstant - leftConstant;

        if (totalXCoeff == 0) {
                if (totalConstant == 0) {
                        cout << "方程有无数解。" << endl;
                } else {
                        cout << "方程无解。" << endl;
                }
                return 0;
        }

        return totalConstant / totalXCoeff;
}
这是整体代码:#include <iostream>
#include <string>
#include <cmath>
using namespace std;

// 快速幂函数,用于计算 a 的 b 次幂
long long Poww(long long a, long long b) {
        long long ans = 1;
        long long base = a;
        while (b != 0) {
                if (b & 1)
                        ans *= base;
                base *= base;
                b >>= 1;
        }
        return ans;
}

// 阶乘函数,计算 n 的阶乘
long long f(int n) {
        if (n == 1)
                return 1;
        if (n > 1)
                return n * f(n - 1);
}

// 计算表达式的值,并输出每一步的计算过程
double cal(double s, double e, string str);

// 获取一个操作数或括号内表达式的值,并输出计算过程
double getVal(double &s, double e, string str) {
        if (str == '(' || str == '[' || str == '{') {
                double news, newe, i;
                i = 1;
                news = s + 1;
                while (i) {
                        s++;
                        if (s == e)
                                break;
                        if (str == '(' || str == '[' || str == '{')
                                i++;
                        else if (str == ')' || str == ']' || str == '}')
                                i--;
                }
                newe = s - 1;
                s++;
                double result = cal(news, newe, str);
                cout << "计算括号内表达式 " << str.substr(news, newe - news + 1) << " 的值为: " << result << endl;
                return result;
        }
        double val;
        if (str == 's') {
                s = s + 3;
                double arg = getVal(s, e, str);
                val = sin(arg);
                cout << "计算 sin(" << arg << ") 的值为: " << val << endl;
        } else if (str == 'c') {
                s = s + 3;
                double arg = getVal(s, e, str);
                val = cos(arg);
                cout << "计算 cos(" << arg << ") 的值为: " << val << endl;
        } else if (str == 't') {
                s = s + 3;
                double arg = getVal(s, e, str);
                val = tan(arg);
                cout << "计算 tan(" << arg << ") 的值为: " << val << endl;
        } else if (str == 'a') {
                s++;
                if (str == 's') {
                        s = s + 3;
                        double arg = getVal(s, e, str);
                        val = asin(arg);
                        cout << "计算 asin(" << arg << ") 的值为: " << val << endl;
                } else if (str == 'c') {
                        s = s + 3;
                        double arg = getVal(s, e, str);
                        val = acos(arg);
                        cout << "计算 acos(" << arg << ") 的值为: " << val << endl;
                } else if (str == 't') {
                        s = s + 3;
                        double arg = getVal(s, e, str);
                        val = atan(arg);
                        cout << "计算 atan(" << arg << ") 的值为: " << val << endl;
                }
        } else if (str >= '0' && str <= '9') {
                val = str - '0';
                while (s < e && str >= '0' && str <= '9') {
                        val *= 10;
                        val += str - '0';
                }
                if (str == '!') {
                        int n = static_cast<int>(val);
                        val = f(n);
                        cout << "计算 " << n << "! 的值为: " << val << endl;
                        s++;
                }
                if (str == '.') {
                        s = s + 1;
                        double val2 = str - '0';
                        while (s < e && str >= '0' && str <= '9') {
                                val2 *= 10;
                                val2 += str - '0';
                        }
                        while (val2 >= 1) {
                                val2 /= 10;
                        }
                        val = val + val2;
                        cout << "处理小数部分,得到值为: " << val << endl;
                }
        }
        return val;
}

// 处理乘、除、幂运算,并输出计算过程
double getVal1(double &s, double e, string str) {
        double val;
        val = getVal(s, e, str);
        while (1) {
                if (s < e && str == '*') {
                        double right = getVal(++s, e, str);
                        double prev = val;
                        val *= right;
                        cout << "计算 " << prev << " * " << right << " 的值为: " << val << endl;
                } else if (s < e && str == '/') {
                        double right = getVal(++s, e, str);
                        double prev = val;
                        val /= right;
                        cout << "计算 " << prev << " / " << right << " 的值为: " << val << endl;
                } else if (s < e && str == '^') {
                        double right = getVal(++s, e, str);
                        double prev = val;
                        val = Poww(static_cast<long long>(val), static_cast<long long>(right));
                        cout << "计算 " << prev << " ^ " << right << " 的值为: " << val << endl;
                } else
                        return val;
        }
}

// 处理加、减运算,并输出计算过程
double cal(double s, double e, string str) {
        double sum = 0;
        if (str != '-')
                sum = getVal1(s, e, str);
        while (s < e) {
                if (str == '+') {
                        double right = getVal1(++s, e, str);
                        double prev = sum;
                        sum += right;
                        cout << "计算 " << prev << " + " << right << " 的值为: " << sum << endl;
                } else if (str == '-') {
                        double right = getVal1(++s, e, str);
                        double prev = sum;
                        sum -= right;
                        cout << "计算 " << prev << " - " << right << " 的值为: " << sum << endl;
                }
        }
        return sum;
}

// 解析方程,将方程分为左右两部分
void parseEquation(const string& equation, string& left, string& right) {
        size_t equalPos = equation.find('=');
        if (equalPos != string::npos) {
                left = equation.substr(0, equalPos);
                right = equation.substr(equalPos + 1);
        }
}

// 合并同类项,计算 x 的系数和常数项
void collectTerms(const string& expr, double& xCoeff, double& constant) {
        double currentCoeff = 1;
        double currentSign = 1;
        double num = 0;
        bool hasX = false;
        for (size_t i = 0; i < expr.length(); ++i) {
                if (isdigit(expr)) {
                        num = num * 10 + (expr - '0');
                } else if (expr == 'x') {
                        hasX = true;
                        if (i == 0 || !isdigit(expr)) {
                                num = 1;
                        }
                } else if (expr == '+' || expr == '-') {
                        if (hasX) {
                                xCoeff += currentSign * currentCoeff * num;
                        } else {
                                constant += currentSign * num;
                        }
                        num = 0;
                        hasX = false;
                        currentSign = (expr == '+') ? 1 : -1;
                        currentCoeff = 1;
                }
        }
        if (hasX) {
                xCoeff += currentSign * currentCoeff * num;
        } else {
                constant += currentSign * num;
        }
}

// 解一元一次方程
double solveEquation(const string& equation) {
        string left, right;
        parseEquation(equation, left, right);

        double leftXCoeff = 0, leftConstant = 0;
        double rightXCoeff = 0, rightConstant = 0;

        collectTerms(left, leftXCoeff, leftConstant);
        collectTerms(right, rightXCoeff, rightConstant);

        double totalXCoeff = leftXCoeff - rightXCoeff;
        double totalConstant = rightConstant - leftConstant;

        if (totalXCoeff == 0) {
                if (totalConstant == 0) {
                        cout << "方程有无数解。" << endl;
                } else {
                        cout << "方程无解。" << endl;
                }
                return 0;
        }

        return totalConstant / totalXCoeff;
}
void jsqbegin() {
        string x;
        while (cin >> x) {
                if (x == "exit") break;
                if (x.find('x') != string::npos && x.find('=') != string::npos) {
                        // 包含未知数 x 且有等号,认为是一元一次方程
                        cout << "开始解方程: " << x << endl;
                        double solution = solveEquation(x);
                        if (solution != 0) {
                                cout << "方程的解为: x = " << solution << endl;
                        }
                } else {
                        // 普通表达式,进行计算并输出步骤
                        cout << "开始计算表达式: " << x << endl;
                        double result = cal(0, x.length(), x);
                        cout << "最终计算结果为: " << result << endl;
                }
        }
}
int main() {
        jsqbegin();
        return 0;
}
ok,快来运行试试

FishC 发表于 2025-5-5 13:09:01

代码问题分析
我看到你尝试实现括号解析功能,但代码有几个需要修正的地方:


[*]字符串比较错误:应使用 str 访问字符串中的字符,而不是直接比较整个字符串
[*]符号判断错误:'{' 被错误地写成 ' == '{'
[*]括号匹配问题:缺少对三种括号类型的完整判断


修正建议
这是修改后的代码示例:

#include <iostream>
using namespace std;

double getVal(int &s, int e, string str) { // 注意参数类型改为int
    if (str == '(' || str == '{') {
      double result;
      int news = s + 1;
      int i = 1; // 用于括号层数计数
      
      while (i > 0 && s < e) {
            s++; // 移动指针
            if (str == '(' || str == '{') i++;
            if (str == ')' || str == '}') i--;
      }
      
      int newe = s - 1;
      s++; // 跳过当前括号
      result = cal(news, newe, str);
      cout << "步骤:" << str.substr(news-1, newe-news+2) << " = " << result << endl;
      return result;
    }
    // 其他处理...
}

改进说明

[*]使用 str 来访问字符串中的具体字符
[*]增加 s < e 的边界条件判断,防止越界
[*]简化括号匹配逻辑,使用计数器跟踪括号层数
[*]添加计算步骤的输出提示


测试建议
可以尝试输入这些表达式测试:

[*] (2+3)*4
[*] {5*(3-1)}/2
[*] 2*(1+{3+4})


如果还有疑问,欢迎继续提问!记得在测试时先去掉方程求解部分的代码,先确保基础运算功能正常。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页: [1]
查看完整版本: 一个简易的C++计算器