You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为HP-35风格C++程序实现科学函数遇到问题求助

Fixing Your HP-35 Style Calculator in C++

Let's walk through the issues in your code and fix them step by step—you're close, but there are some key mistakes in how you're handling stack operations, library functions, and the required features.

Key Issues in Your Current Code

Let's break down what's going wrong:

  • Uninitialized variables & unused library functions: For functions like sqrt, exp, and arccos, you're just pushing an uninitialized double variable (garbage value) instead of calling the actual cmath functions and using stack values.
  • Incorrect stack handling: All scientific functions need to pull values from the stack to compute results. For example, sin should pop the top value, calculate its sine, then push the result back—you're currently pushing sin(0) every time.
  • Missing required functions: You haven't implemented chs, 1/x, or ln at all, and your arcsin uses the token "I" instead of matching the required "arcsin".
  • No case insensitivity: Right now, only lowercase function names work—you need to handle inputs like "SIN", "Sin", or "LOG" equally well.
  • Portability issue with M_PI: Many compilers require a preprocessor define to expose M_PI from cmath.
  • Function name conflicts: You declared a sin method inside HPStack which clashes with the standard library's sin function.

Corrected Full Code

Here's the fixed version with all required features implemented:

#define _USE_MATH_DEFINES  // Required for M_PI on most compilers
#include <string>
#include <iostream>
#include <sstream>
#include <cmath>
#include <algorithm>  // For transform() to handle case insensitivity

using namespace std;

// Helper function to convert strings to lowercase for case-insensitive matching
string toLower(string s) {
    transform(s.begin(), s.end(), s.begin(), ::tolower);
    return s;
}

class HPStack {
    double stack[100];
    int top;
public:
    HPStack() {
        top = -1;
    }

    void push(double data) {
        if (top < 99) {  // Prevent stack overflow
            top++;
            stack[top] = data;
        } else {
            cerr << "Error: Stack overflow\n";
        }
    }

    double pop() {
        if (top >= 0) {  // Prevent stack underflow
            return stack[top--];
        } else {
            cerr << "Error: Stack underflow\n";
            return 0.0;
        }
    }

    double peek() {
        if (top >= 0) {
            return stack[top];
        } else {
            cerr << "Error: Stack is empty\n";
            return 0.0;
        }
    }
};

int main(int argc, char *argv[]) {
    HPStack stack;
    string line;
    while (getline(cin, line)) {
        stringstream expression(line);
        string token;
        while (expression >> token) {
            string lowerToken = toLower(token);

            // Handle numeric inputs
            if (isdigit(lowerToken[0]) || (lowerToken[0] == '-' && lowerToken.size() > 1)) {
                stack.push(atof(token.data()));
            }
            // Unary functions (operate on top stack element)
            else if (lowerToken == "sin") {
                double x = stack.pop();
                stack.push(::sin(x));
            } else if (lowerToken == "cos") {
                double x = stack.pop();
                stack.push(::cos(x));
            } else if (lowerToken == "tan") {
                double x = stack.pop();
                stack.push(::tan(x));
            } else if (lowerToken == "arcsin") {
                double x = stack.pop();
                if (x >= -1.0 && x <= 1.0) {
                    stack.push(::asin(x));
                } else {
                    cerr << "Error: arcsin input must be between -1 and 1\n";
                    stack.push(x);  // Restore invalid input to avoid stack imbalance
                }
            } else if (lowerToken == "arccos") {
                double x = stack.pop();
                if (x >= -1.0 && x <= 1.0) {
                    stack.push(::acos(x));
                } else {
                    cerr << "Error: arccos input must be between -1 and 1\n";
                    stack.push(x);
                }
            } else if (lowerToken == "arctan") {
                double x = stack.pop();
                stack.push(::atan(x));
            } else if (lowerToken == "sqrt") {
                double x = stack.pop();
                if (x >= 0.0) {
                    stack.push(::sqrt(x));
                } else {
                    cerr << "Error: sqrt requires non-negative input\n";
                    stack.push(x);
                }
            } else if (lowerToken == "chs") {
                double x = stack.pop();
                stack.push(-x);
            } else if (lowerToken == "1/x") {
                double x = stack.pop();
                if (x != 0.0) {
                    stack.push(1.0 / x);
                } else {
                    cerr << "Error: Division by zero in 1/x\n";
                    stack.push(x);
                }
            } else if (lowerToken == "ln") {
                double x = stack.pop();
                if (x > 0.0) {
                    stack.push(::log(x));
                } else {
                    cerr << "Error: ln requires positive input\n";
                    stack.push(x);
                }
            } else if (lowerToken == "log") {
                double x = stack.pop();
                if (x > 0.0) {
                    stack.push(::log10(x));
                } else {
                    cerr << "Error: log requires positive input\n";
                    stack.push(x);
                }
            } else if (lowerToken == "exp") {
                double x = stack.pop();
                stack.push(::exp(x));
            }
            // Binary functions (operate on top two stack elements)
            else if (lowerToken == "pow") {
                double y = stack.pop();  // Top of stack is exponent
                double x = stack.pop();  // Next is base
                stack.push(::pow(x, y));
            } else if (lowerToken == "+") {
                double x = stack.pop();
                double y = stack.pop();
                stack.push(y + x);
            } else if (lowerToken == "-") {
                double x = stack.pop();
                double y = stack.pop();
                stack.push(y - x);
            } else if (lowerToken == "*") {
                double x = stack.pop();
                double y = stack.pop();
                stack.push(y * x);
            } else if (lowerToken == "/") {
                double x = stack.pop();
                double y = stack.pop();
                if (x != 0.0) {
                    stack.push(y / x);
                } else {
                    cerr << "Error: Division by zero\n";
                    stack.push(y);
                    stack.push(x);
                }
            } else if (lowerToken == "pi" || lowerToken == "m_pi") {
                stack.push(M_PI);
            }
            // Handle unknown commands
            else {
                cerr << "Error: Unknown command '" << token << "'\n";
            }
        }
        cout << stack.peek() << "\n";
    }
    return 0;
}

Key Improvements Explained

  • Case insensitivity: The toLower helper converts all input tokens to lowercase, so "SIN", "Sin", and "sin" all work the same.
  • Proper stack handling: Every function now pops the required number of elements from the stack, computes the result, and pushes it back. We also added error checking for stack underflow/overflow and invalid inputs (like sqrt of a negative number).
  • All required functions implemented: chs, 1/x, ln, and all trigonometric/inverse trig functions are now present, using the correct cmath functions (e.g., ::log for natural log, ::log10 for common log).
  • Portable M_PI: The _USE_MATH_DEFINES preprocessor macro ensures M_PI is available on most compilers.
  • Error handling: We added basic error messages for invalid inputs, division by zero, and unknown commands, while preserving stack state to avoid crashes.

内容的提问来源于stack exchange,提问作者applexr501

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 14:37:53