Вот простое решение проблемы. Извините, у меня такое приятное место для моей любимой HP 35 много лет назад, что мне пришлось пойти немного дальше. Эта версия использует целые числа и использует стек строк. Это можно легко преобразовать в удвоения, заменив int
на double
по всему файлу,
Используется getline () и istringstream для разбора ввода.
Он также использует stringstream для преобразования чисел в строки и обратно.
Вы должны быть осторожны при разборе нескольких слов из каждой строки. Этот код перенаправляет входную строку в ss, объект istringstream, а затем получает токены из этого объекта.
Кроме того, будет напечатан стек, если вы введете «s».
Наконец, вы можете произвольно загрузить стек последовательностью разделенных пробелами чисел или можете вводить числа по одному за раз. Стек используется при вводе оператора.
Удачи.
#include <iostream>
#include <stack>
#include <string>
#include <sstream>
///////////////////////
/// top_and_pop()
/// Save the top value from a stack, and then pop the stack
/// If the stack is empty, return the string "0".
/// If the stack was not empty, return the popped element.
std::string top_and_pop(std::stack<std::string> &stack)
{
std::string return_string;
if (stack.empty()) {
return_string = "0";
std::cout << "Stack Empty, returning 0" << std::endl;
} else {
return_string = stack.top();
std::cout << "Popping " << return_string << std::endl;
stack.pop();
}
return return_string;
}
//////////////////////
/// is_number
/// Parse number into a int using std::stringstream.
/// If successful, then, the stringstream will be empty.
/// Return: true if the str would successfully parse as a int
bool is_number(const std::string &str)
{
std::istringstream ss(str);
int number;
ss >> number;
if (!ss.fail() && ss.eof())
return true;
ss >> std::ws; // not needed in this program, because we already parsed the
// input to a single word without whitespace. Needed for parsing a single line
// that may contain any set of chars.
return !ss.fail() && ss.eof();
}
/////////////////////
/// is_operator
/// return false if str is not a single character or if an operator is not found
/// acceptable operators are anyof "+-*/"
bool is_operator(const std::string &str)
{
return (str.length() == 1 &&
str.find_first_not_of("+-*/") == std::string::npos);
}
/////////////////////
/// string_to_int
/// convert string to int
/// Check to be sure string can convert to a int before calling
/// if conversion fails, return 0;
int string_to_int(const std::string &str)
{
std::stringstream stream;
int number = 0;
stream << str;
stream >> number;
return number;
}
//////////////////////
/// stack_to_string
///
/// print elements of stack
std::string stack_to_string(std::stack<std::string> stack)
{
std::string return_string;
while (!stack.empty()) {
return_string += stack.top() + " ";
stack.pop();
}
return return_string;
}
int main()
{
std::stack<std::string> mystack;
std::string input_line;
bool done = false; /// flag to indicate that calcualtor is closing
std::string token_str;
int operand1, operand2, result;
std::cout
<< "Please enter an RPN expression. Expression may consist of any \n"
"combination of space-separated numbers or operators.\n"
"Operators may include '+', '-', '*', '/'. The stack is initialized\n"
"with an unlimited supply of zeroes.\n\n"
"Type 's' to print the current stack.\n"
"To exit, type a 'y'" << std::endl;
do {
getline(std::cin, input_line);
std::stringstream ss(input_line);
/// loop through all tokens in this input line
while (ss >> token_str) {
// Only numbers are allowed on the stack.
// If the current token is a number, push it on the stack as a string
if (is_number(token_str)) {
mystack.push(token_str);
} else if (is_operator(token_str)) {
operand2 = (int) string_to_int(top_and_pop(mystack));
operand1 = (int) string_to_int(top_and_pop(mystack));
// switch does not accept string as a type, and we checked to ensure
// it is a single character operand that is handled in the switch
switch (token_str[0]) {
case '+':result = operand1 + operand2;
break;
case '-':result = operand1 - operand2;
break;
case '*':result = operand1 * operand2;
break;
case '/':
if (operand2 == 0) {
std::cout << "Error: Cannot divide by zero" << std::endl;
continue; // don't push result, take new input.
} else {
result = operand1 / operand2;
}
break;
// default case not needed as we already checked operator, but
// for error checking, we include it
default:std::cout << "Operator not found" << std::endl;
continue;
}
mystack.push(std::to_string(result));
std::cout << " Push result " << result << " " << std::endl;
} else if ("Y" == token_str || "y" == token_str) {
done = true;
} else if ("stack" == token_str || "s" == token_str) {
std::cout << "stack: ";
std::string stack_dump = stack_to_string(mystack);
std::cout << stack_dump << std::endl;
} else {
std::cout << "Invalid input." << std::endl;
}
}
}
while (!done);
}