在c++中使用堆栈计算后缀
Evaluate postfix using a stack in C++
#include <iostream>
#include <sstream>
#include <stack>
#include <limits>
#include <string>
using namespace std;
int main()
{
string input;
cout << "Enter a postfix expression: " << endl;
getline(cin, input);
int operand1, operand2, result,number;
stack<char>operation;
stringstream temp;
int i=0;
while (i < input.length())
{
if (isdigit(input[i]))
{
operation.push(input[i]);
}
else
{
operand2 = operation.top();
temp << operation.top();
operation.pop();
operand1 = operation.top();
temp << operation.top();
operation.pop();
switch(operand1,operand2)
{
case '+': result=operand1 + operand2;
break;
case '-': result=operand1 - operand2;
break;
case '*': result=operand1 * operand2;
break;
case '/': result=operand1 / operand2;
break;
}
operation.push(result);
}
i++;
}
cout << "The result is: "<<temp.str()<<endl;
cin.ignore(numeric_limits<streamsize>::max(), 'n');
return 0;
}
我已经改变了代码,并设法获得"pop"值,但操作不起作用。
你可能意味着
switch(input[i])
而不是switch(operation.top())
更新对代码更改的响应
我可以确认你更改了代码,但不是很好。
- 代码大部分已经有了所有的缺陷,还有一些。
- 你现在把操作数组合成一个stringstream有什么好处?
- 现在打开(operand1,operand2)…
- 都是未初始化的
- (operand1,operand2)在此上下文中基本上表示(operand2)(序列操作符)
- 你的分支标签是…运算符(+ -/*)
- 你现在打印一个最终的结果,这是输入中所有数字的连接(如果你曾经达到程序的结束而没有崩溃)?
在之前的错误中,仍然需要修复
- 堆栈计算器的心智模型。
- 数字(整数)是操作数(所以9,100,39829是有效的操作数)
- +-/*为操作符(
operators
对operands
进行操作) - 堆栈是操作数堆栈,不是操作符堆栈(操作符不需要记住,因为它们立即被求值)
- 号码由一行1个或多个
digits
(0123456789)组成;因此,在operand stack
上'push' -
operators
+-/*取2operands
,所以对大小为<2的堆栈的任何操作都是错误的(您需要检查,否则程序将在试图访问不存在或包含垃圾的内存时崩溃)。
number
之前,您需要阅读几个字符。
这应该足够让你开始了。
我认为有两件事是积极的:
- 程序编译。+1对于你实际使用编译器:)
- 您将重复的
operation.push(result)
从开关中取出,因此它不再重复。编码风格+1…
我希望你能从这里收集到代码不是很好(委婉地说),我真的认为一些基本的练习是有序的:1. 编写一个简单的for循环,将数字1到10打印到控制台1. 编写一个简单的while循环,打印用户输入的单词1. 使用一个简单的循环打印1到50之间所有是7的倍数的数字1. 当用户输入字母a、b、k或z时,使用switch语句打印"yes"2. 创建一个简单的循环,只打印相同字符后面的每个字符的输入字符(因此'abccdefgghijkllmabcdd'将变成' cld ')1. 使用相同的循环,但这次打印紧跟在相同单词后面的每个单词(因此"no, no, you should not pop, pop, but push, pop"变成了"no pop")
这应该会给你一种感觉是如何真正工作的,没有猜测或"神奇因素"。
哦,别忘了,我在下面为你实现了整个东西。我不建议你盲目地抄(这对你的老师来说是相当明显的:)),但如果你想知道我上面所有的话是什么意思,你可以看一看:)
-
您正在推送松散的数字,而不是解析过的数字
-
在第31行你弹出一个可能空的堆栈(导致段错误,除非你在编译器上使用调试模式STL标志)
只是为了好玩:
#include <iostream>
#include <stack>
#include <vector>
#include <limits>
#include <string>
#include <stdexcept>
#include <iterator>
#include <fstream>
using namespace std;
template <class T>
static void dumpstack(std::stack<T> s/*byval!*/)
{
std::vector<T> vec;
while (!s.empty())
{
vec.push_back(s.top());
s.pop();
}
std::copy(vec.rbegin(), vec.rend(), std::ostream_iterator<int>(std::cout, " "));
}
class calc
{
private:
std::stack<int> _stack;
int _accum;
bool _pending;
void store(/*store accumulator if pending*/)
{
if (_pending)
{
_stack.push(_accum);
_pending = false;
_accum = 0;
}
}
public:
calc() : _accum(0), _pending(false)
{
}
void handle(char ch)
{
switch (ch)
{
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
_pending = true;
_accum *= 10;
_accum += ch-'0';
break;
case '+': case '-': case '/': case '*':
{
store();
if (_stack.size()<2)
throw std::runtime_error("stack underflow");
int op2 = _stack.top(); _stack.pop();
int op1 = _stack.top(); _stack.pop();
switch (ch)
{
case '+': _stack.push(op1 + op2); break;
case '-': _stack.push(op1 - op2); break;
case '/': _stack.push(op1 / op2); break;
case '*': _stack.push(op1 * op2); break;
}
// feedback to console:
std::cout << std::endl << "(evaluated: " << op1 << " " << ch << " " << op2 << " == " << _stack.top() << ")" << std::endl;
dump();
}
break;
default:
store(); // todo: notify of ignored characters in input?
}
}
void dump() const
{
dumpstack(_stack);
}
};
int main()
{
cout << "Enter postfix expressions: " << endl;
calc instance;
try
{
while (std::cin.good())
{
char ch = std::cin.get();
instance.handle(ch);
}
std::cout << "Final result: ";
instance.dump();
return 0;
} catch(const std::exception& e)
{
std::cerr << "E: " << e.what() << std::endl;
return 255;
}
}
测试输出:(注意,按回车键后,可以继续执行剩余的部分求值的堆栈)
Enter postfix expressions:
1 2 3 +4 * - / 1333 *
(evaluated: 2 + 3 == 5)
1 5
(evaluated: 5 * 4 == 20)
1 20
(evaluated: 1 - 20 == -19)
-19 E: stack underflow
代码有很多错误,首先是对输入表达式的解析。实际的崩溃很可能是由于这样一个事实,如果你输入像"12+"
这样的东西,你会把'1'
和'2'
推入堆栈(注意:字符1和2,而不是值1和2!!),然后试图提取两个操作数和一个你从未插入到堆栈中的操作符。
在解析输入时,您逐个字符读取,并且仅使用第一个数字,解析无法处理空格或任何其他分隔符…试着把问题分成两部分:解析和处理。解析问题可以通过不使用实际读取的值,而只是打印它们(或以某种形式存储,然后打印整个读取表达式)来解决,这可以作为第一步。确保解析器能够以健壮的方式处理常见表达式,如"1 2+"、"10 20 +"、"1 2+"、"1 2+"(注意空格的不同位置)。而且它无法优雅地解析"+"、"1 +"、"1 ++"等表达式……你永远不能相信用户的输入,他们会犯错误,但这不应该让你的程序崩溃。
一旦确定能够解析输入,就开始实际的算法。使其对以前可能无法处理的无效用户输入(如"10 0/")具有健壮性,并进行实际处理。
学会使用调试器,它将帮助你了解当事情出错的原因是什么。调试器会在不到一秒钟的时间内指出上面代码中的特定问题,它不会告诉你为什么它会失败,但它会告诉你它是如何失败的,以及程序的状态。如果我的预感是正确的,那么它将指向operation.top()
指令作为罪魁祸首,并且您将能够看到您试图提取的元素多于插入的元素。一步一步地执行程序的一部分来理解它实际在做什么,你会注意到,当你读到"12+"时,你实际上是将两个看似无关的整数存储到堆栈中('1'
和'2'
的ASCII值…
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- 递归函数计算序列中的平方和(并输出过程)
- (C++)分析树以计算返回错误值的简单算术表达式
- 使用指针计算堆栈问题的大 O 表示法
- RPN计算器使用头文件进行计算操作和堆栈;用于堆栈的矢量
- 如何在不导致堆栈溢出的情况下计算非常大的数字和很小的 HCF.我正在使用欧几里得算法
- 堆栈后缀表示法评估等于中缀计算得到的不同
- 如何使用 ASCII 转换使用字符堆栈计算后缀表达式
- 根据堆栈操作 c++ 计算元素的最大数量
- 使用条件运算符递归计算模板化值或函数时出现错误 C1202(堆栈溢出)
- 使用c++中的堆栈计算后缀时处理十进制值
- 计算C++堆栈需求;如何获得可读的交易品种表
- 试图计算fibonacci(n)的变量“f”周围的堆栈损坏
- 从缓冲区指针计算堆栈中的返回地址
- 为什么我在计算帕斯卡三角形元素时在递归 C 程序中出现堆栈溢出错误
- 在c++中计算后缀表达式时接收堆栈错误
- 在c++中将两个相关的std::堆栈合并为std::map的计算效率如何?
- C++-如何增加堆栈大小以允许Kosaraju算法进行更多递归以计算强连接组件
- 在堆栈程序中实现一个计数器,用于计算对象移动的次数
- 在c++中使用堆栈计算后缀