为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, andarccos, you're just pushing an uninitializeddoublevariable (garbage value) instead of calling the actualcmathfunctions and using stack values. - Incorrect stack handling: All scientific functions need to pull values from the stack to compute results. For example,
sinshould pop the top value, calculate its sine, then push the result back—you're currently pushingsin(0)every time. - Missing required functions: You haven't implemented
chs,1/x, orlnat all, and yourarcsinuses 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 exposeM_PIfromcmath. - Function name conflicts: You declared a
sinmethod insideHPStackwhich clashes with the standard library'ssinfunction.
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
toLowerhelper 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 correctcmathfunctions (e.g.,::logfor natural log,::log10for common log). - Portable
M_PI: The_USE_MATH_DEFINESpreprocessor macro ensuresM_PIis 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
相关产品推荐
相关产品推荐

