使用队列和堆栈的后缀评估 C++
postfix evaluation using queues and stacks c++
主要代码相关文件将link编辑为github
https://github.com/andrew-chen/csis252/blob/master/examples/token/token.h
https://github.com/andrew-chen/csis252/blob/master/examples/stackType.h
https://github.com/andrew-chen/csis252/blob/master/examples/queueType.h
token.cpp 没有 link 所以我将复制并粘贴到这里
// File: token.cpp
// This file contains the specification for the token class.
#include <cmath>
#include <cassert>
#include <cctype>
#include "token.h"
/*
{
static bool unary; // to identify unary minus
bool isnumber; // identify whether it's a number or not
double value; // an operand
char ch; // an operator or parenthesis
bool valid; // true if Token is valid
}
*/
Token:: Token() // no argument constructor
{
valid=false;
};
Token:: Token(double d) // double constructor
{
value = d;
valid=true;
isnumber = true;
};
Token:: Token(int i) // int constructor
{
value = i;
valid = true;
isnumber = true;
};
Token:: Token(char c) // char constructor
{
ch = c;
isnumber = false;
switch (ch) {
case '(':
case ')':
case '+':
case '-':
case '*':
case '/':
case '%':
case '^':
valid = true;
return;
default:
valid = false;
};
};
bool Token:: Valid() const // true if token is valid
{return valid;};
bool Token:: IsOperand() const // true if token is an operand
{return isnumber;};
bool Token:: IsOperator() const // true if token is an operator
{
switch(ch) {
case '+':
case '-':
case '*':
case '/':
case '%':
case '^':
return true;
default:
return false;
};
};
bool Token:: IsLeftParen() const // true if token is a (
{
return (ch == '(');
};
bool Token:: IsRightParen() const // true if token is a )
{
return (ch == ')');
};
double Token:: Operand() const // returns the value of the operand
{
return value;
};
char Token:: Operator() const // returns '+' '-' '*' '/' '%' '^'
{
return ch;
};
int Token:: Precedence() const // returns precedence of operator
{
switch(ch) {
case '(': return 0;
case ')': return 0;
case '^': return 3;
case '*': return 2;
case '/': return 2;
case '%': return 2;
case '+': return 1;
case '-': return 1;
default: return 0;
};
};
Token Token:: operator + (const Token & arg) const // add Token to object
{
return Token(value + arg.value);
};
Token Token:: operator - (const Token& arg) const // subtract Token from object
{
return Token(value - arg.value);
};
Token Token:: operator * (const Token& arg) const // multiply object by Token
{
return Token(value * arg.value);
};
Token Token:: operator / (const Token& arg) const // divide object by Token
{
return Token(value / arg.value);
};
Token Token:: operator % (const Token& arg) const // modulus object by Token
{
return Token(int(value) % int(arg.value));
};
Token Token:: operator ^ (const Token& arg) const // raise object to power of Token
{
return Token(pow(value,arg.value));
};
istream& operator >> (istream&i,Token&t) // overload input
{
char c;
i.get(c);
if (isdigit(c)) {
i.putback(c);
int v;
i >> v;
t = Token(v);
} else {
t = Token(c);
};
return i;
};
// A friend function is a none member function that is given access
// to the private members of a class. Friend functions should be
// avoided if possible.
// The >> operator will skip blanks and tabs, not '\n'.
// '\n' will be read and the token is not valid.
// This provides a way to have a loop read one line of tokens
// then exit when '\n is read.
ostream& operator << (ostream&o,const Token&t) //overload output
{
assert(t.Valid());
if (t.IsOperand()) {
o << t.Operand();
} else {
o << t.Operator();
};
return o;
};
#include "token.h"
#include "queueType.h"
#include "stackType.h"
#include <iostream>
using namespace std;
int main()
{
queueType<Token> resultQue;
stackType<Token> movingStack;
stackType<Token> newResult;
queueType<Token> copyresutQue;
char exponent = '^';
Token t;
cout << "enter infix expression: ";
cin >> t;
while(t.Valid()){
if(t.IsOperand()){
resultQue.addQueue(t);
}
else if(t.IsLeftParen()){
movingStack.push(t);
}
else if(t.IsRightParen()){
while(!movingStack.isEmptyStack()){
if(movingStack.top().IsOperator()){
resultQue.addQueue(movingStack.top());
movingStack.pop();
}
if(movingStack.top().IsLeftParen()){
movingStack.pop();
break;
}
}
}
else if(t.IsOperator()){
while(!movingStack.isEmptyStack()){
if(movingStack.top().IsOperator()){
if(movingStack.top().Operator()==exponent || t.Precedence()>movingStack.top().Precedence() ||movingStack.top().IsLeftParen() ){
break;
}
resultQue.addQueue(movingStack.top());
movingStack.pop();
}
else if(movingStack.top().IsLeftParen()){
break;
}
}
movingStack.push(t);
}
cin >> t;
}
while(!movingStack.isEmptyStack()){
if(movingStack.top().IsOperator()){
resultQue.addQueue(movingStack.top());
movingStack.pop();
}
}
// while(!movingStack.isEmptyStack()){
// cout << movingStack.top() << endl;
// movingStack.pop();
// }
cout << "PostFit Express" <<endl;
while(!resultQue.isEmptyQueue()){
cout << resultQue.front()<< " ";
copyresutQue.addQueue(resultQue.front());
resultQue.deleteQueue();
}
cout << "\ncopy Result"<<endl;
while(!copyresutQue.isEmptyQueue()) {
cout << copyresutQue.front()<<endl;
if (copyresutQue.front().IsOperand()) {
newResult.push(copyresutQue.front());
copyresutQue.deleteQueue();
// cout << copyresutQue.front() <<endl;
}
if(copyresutQue.front().IsOperator()){
Token result;
while(!newResult.isEmptyStack()){
// cout << newResult.top()<<endl;
if(newResult.top().IsOperand()){
Token num1 = newResult.top().Operand();
// cout << num1 << endl;
newResult.pop();
Token num2 = newResult.top().Operand();
// cout<<num2<<endl;
newResult.pop();
cout << newResult.top()<<endl;
switch (copyresutQue.front().Operator())
{
case '+' : result = num2 + num1; break;
case '-' : result = num2 - num1; break;
case '*' : result = num2 * num1; break;
case '/' : result = num2 / num1; break;
case '%' : result = num2 % num1; break;
case '^' : result = num2 ^ num1; break;
}
// cout<<result<<endl;
newResult.push(result);
}
}
copyresutQue.deleteQueue();
}
// cout << newResult.top()<<endl;
// copyresutQue.deleteQueue();
}
return 0;
}
到目前为止,我已经能够将中缀转换为后缀表达式,现在我的问题是后缀求值。无论出于何种原因,我的副本 copyresutQue 删除了一些队列,并且不会将它们推送到我的 newResult 堆栈中。由于当 pop() 操作数执行评估的算术部分时,来自 copyresutQue 的队列被删除,它将在我的代码中显示一个空堆栈错误,因为没有任何东西可以从 newResult 堆栈中弹出。
例子:
输入 (10+3)-2
中缀表达式 10 3 + 2-
它将添加 10 + 3 并将 13 压入新结果堆栈,但随后会显示错误,因为
无论出于何种原因,队列的其余部分都将被删除。此外,其余文件由讲师提供,因此它们应该 100% 正确。对于这项作业,我必须使用队列和堆栈,我知道还有其他方法可以完成这项作业。谢谢你的时间。
最后一个 while 循环有问题。
while(!copyresutQue.isEmptyQueue()) {
if(copyresutQue.front().IsOperand()) {
newResult.push(copyresutQue.front());
copyresutQue.deleteQueue();
}
else {
Token result;
Token num1 = newResult.top();
newResult.pop();
Token num2 = newResult.top();
newResult.pop();
auto binaryOperator = copyresutQue.front();
copyresutQue.deleteQueue();
cout << binaryOperator << endl;
switch (binaryOperator.Operator())
{
case '+' : result = num2 + num1; break;
case '-' : result = num2 - num1; break;
case '*' : result = num2 * num1; break;
case '/' : result = num2 / num1; break;
case '%' : result = num2 % num1; break;
case '^' : result = num2 ^ num1; break;
}
newResult.push(result);
}
}
cout << newResult.top()<<endl;
主要代码相关文件将link编辑为github
https://github.com/andrew-chen/csis252/blob/master/examples/token/token.h
https://github.com/andrew-chen/csis252/blob/master/examples/stackType.h
https://github.com/andrew-chen/csis252/blob/master/examples/queueType.h
token.cpp 没有 link 所以我将复制并粘贴到这里
// File: token.cpp
// This file contains the specification for the token class.
#include <cmath>
#include <cassert>
#include <cctype>
#include "token.h"
/*
{
static bool unary; // to identify unary minus
bool isnumber; // identify whether it's a number or not
double value; // an operand
char ch; // an operator or parenthesis
bool valid; // true if Token is valid
}
*/
Token:: Token() // no argument constructor
{
valid=false;
};
Token:: Token(double d) // double constructor
{
value = d;
valid=true;
isnumber = true;
};
Token:: Token(int i) // int constructor
{
value = i;
valid = true;
isnumber = true;
};
Token:: Token(char c) // char constructor
{
ch = c;
isnumber = false;
switch (ch) {
case '(':
case ')':
case '+':
case '-':
case '*':
case '/':
case '%':
case '^':
valid = true;
return;
default:
valid = false;
};
};
bool Token:: Valid() const // true if token is valid
{return valid;};
bool Token:: IsOperand() const // true if token is an operand
{return isnumber;};
bool Token:: IsOperator() const // true if token is an operator
{
switch(ch) {
case '+':
case '-':
case '*':
case '/':
case '%':
case '^':
return true;
default:
return false;
};
};
bool Token:: IsLeftParen() const // true if token is a (
{
return (ch == '(');
};
bool Token:: IsRightParen() const // true if token is a )
{
return (ch == ')');
};
double Token:: Operand() const // returns the value of the operand
{
return value;
};
char Token:: Operator() const // returns '+' '-' '*' '/' '%' '^'
{
return ch;
};
int Token:: Precedence() const // returns precedence of operator
{
switch(ch) {
case '(': return 0;
case ')': return 0;
case '^': return 3;
case '*': return 2;
case '/': return 2;
case '%': return 2;
case '+': return 1;
case '-': return 1;
default: return 0;
};
};
Token Token:: operator + (const Token & arg) const // add Token to object
{
return Token(value + arg.value);
};
Token Token:: operator - (const Token& arg) const // subtract Token from object
{
return Token(value - arg.value);
};
Token Token:: operator * (const Token& arg) const // multiply object by Token
{
return Token(value * arg.value);
};
Token Token:: operator / (const Token& arg) const // divide object by Token
{
return Token(value / arg.value);
};
Token Token:: operator % (const Token& arg) const // modulus object by Token
{
return Token(int(value) % int(arg.value));
};
Token Token:: operator ^ (const Token& arg) const // raise object to power of Token
{
return Token(pow(value,arg.value));
};
istream& operator >> (istream&i,Token&t) // overload input
{
char c;
i.get(c);
if (isdigit(c)) {
i.putback(c);
int v;
i >> v;
t = Token(v);
} else {
t = Token(c);
};
return i;
};
// A friend function is a none member function that is given access
// to the private members of a class. Friend functions should be
// avoided if possible.
// The >> operator will skip blanks and tabs, not '\n'.
// '\n' will be read and the token is not valid.
// This provides a way to have a loop read one line of tokens
// then exit when '\n is read.
ostream& operator << (ostream&o,const Token&t) //overload output
{
assert(t.Valid());
if (t.IsOperand()) {
o << t.Operand();
} else {
o << t.Operator();
};
return o;
};
#include "token.h"
#include "queueType.h"
#include "stackType.h"
#include <iostream>
using namespace std;
int main()
{
queueType<Token> resultQue;
stackType<Token> movingStack;
stackType<Token> newResult;
queueType<Token> copyresutQue;
char exponent = '^';
Token t;
cout << "enter infix expression: ";
cin >> t;
while(t.Valid()){
if(t.IsOperand()){
resultQue.addQueue(t);
}
else if(t.IsLeftParen()){
movingStack.push(t);
}
else if(t.IsRightParen()){
while(!movingStack.isEmptyStack()){
if(movingStack.top().IsOperator()){
resultQue.addQueue(movingStack.top());
movingStack.pop();
}
if(movingStack.top().IsLeftParen()){
movingStack.pop();
break;
}
}
}
else if(t.IsOperator()){
while(!movingStack.isEmptyStack()){
if(movingStack.top().IsOperator()){
if(movingStack.top().Operator()==exponent || t.Precedence()>movingStack.top().Precedence() ||movingStack.top().IsLeftParen() ){
break;
}
resultQue.addQueue(movingStack.top());
movingStack.pop();
}
else if(movingStack.top().IsLeftParen()){
break;
}
}
movingStack.push(t);
}
cin >> t;
}
while(!movingStack.isEmptyStack()){
if(movingStack.top().IsOperator()){
resultQue.addQueue(movingStack.top());
movingStack.pop();
}
}
// while(!movingStack.isEmptyStack()){
// cout << movingStack.top() << endl;
// movingStack.pop();
// }
cout << "PostFit Express" <<endl;
while(!resultQue.isEmptyQueue()){
cout << resultQue.front()<< " ";
copyresutQue.addQueue(resultQue.front());
resultQue.deleteQueue();
}
cout << "\ncopy Result"<<endl;
while(!copyresutQue.isEmptyQueue()) {
cout << copyresutQue.front()<<endl;
if (copyresutQue.front().IsOperand()) {
newResult.push(copyresutQue.front());
copyresutQue.deleteQueue();
// cout << copyresutQue.front() <<endl;
}
if(copyresutQue.front().IsOperator()){
Token result;
while(!newResult.isEmptyStack()){
// cout << newResult.top()<<endl;
if(newResult.top().IsOperand()){
Token num1 = newResult.top().Operand();
// cout << num1 << endl;
newResult.pop();
Token num2 = newResult.top().Operand();
// cout<<num2<<endl;
newResult.pop();
cout << newResult.top()<<endl;
switch (copyresutQue.front().Operator())
{
case '+' : result = num2 + num1; break;
case '-' : result = num2 - num1; break;
case '*' : result = num2 * num1; break;
case '/' : result = num2 / num1; break;
case '%' : result = num2 % num1; break;
case '^' : result = num2 ^ num1; break;
}
// cout<<result<<endl;
newResult.push(result);
}
}
copyresutQue.deleteQueue();
}
// cout << newResult.top()<<endl;
// copyresutQue.deleteQueue();
}
return 0;
}
到目前为止,我已经能够将中缀转换为后缀表达式,现在我的问题是后缀求值。无论出于何种原因,我的副本 copyresutQue 删除了一些队列,并且不会将它们推送到我的 newResult 堆栈中。由于当 pop() 操作数执行评估的算术部分时,来自 copyresutQue 的队列被删除,它将在我的代码中显示一个空堆栈错误,因为没有任何东西可以从 newResult 堆栈中弹出。
例子: 输入 (10+3)-2 中缀表达式 10 3 + 2-
它将添加 10 + 3 并将 13 压入新结果堆栈,但随后会显示错误,因为 无论出于何种原因,队列的其余部分都将被删除。此外,其余文件由讲师提供,因此它们应该 100% 正确。对于这项作业,我必须使用队列和堆栈,我知道还有其他方法可以完成这项作业。谢谢你的时间。
最后一个 while 循环有问题。
while(!copyresutQue.isEmptyQueue()) {
if(copyresutQue.front().IsOperand()) {
newResult.push(copyresutQue.front());
copyresutQue.deleteQueue();
}
else {
Token result;
Token num1 = newResult.top();
newResult.pop();
Token num2 = newResult.top();
newResult.pop();
auto binaryOperator = copyresutQue.front();
copyresutQue.deleteQueue();
cout << binaryOperator << endl;
switch (binaryOperator.Operator())
{
case '+' : result = num2 + num1; break;
case '-' : result = num2 - num1; break;
case '*' : result = num2 * num1; break;
case '/' : result = num2 / num1; break;
case '%' : result = num2 % num1; break;
case '^' : result = num2 ^ num1; break;
}
newResult.push(result);
}
}
cout << newResult.top()<<endl;