使用堆栈的 C++ 后缀表达式求值。我认为我没有正确转换数据
C++ Postfix expression evaluation using stacks. I dont think I'm converting the data correctly
我目前正在尝试让这个后缀表达式 eval 起作用,但我相信在 int EvaluatePostfix
函数中我使用的 stackPtr->peek()
不正确,因为每当我尝试获取最高值并减去它通过'0'(未在代码中显示,mb)将其转换为 int 它说它是一个“std::basic_string-char-”所以它不能用 char.
类型做减法
postfix.cpp:
#include <iostream>
#include <string>
#include "ArrayStack.h"
bool IsNumericDigit(char C)
{
if(C >= '0' && C <= '9') return true;
return false;
}
// Function to verify whether a character is operator symbol or not.
bool IsOperator(char C)
{
if(C == '+' || C == '-' || C == '*' || C == '/')
return true;
return false;
}
// Function to perform an operation and return output.
int PerformOperation(char operation, int operand1, int operand2)
{
if(operation == '+') return operand1 +operand2;
else if(operation == '-') return operand1 - operand2;
else if(operation == '*') return operand1 * operand2;
else if(operation == '/') return operand1 / operand2;
else std::cout<<"Unexpected Error \n";
return -1;
}
int EvaluatePostfix(std::string expression, StackInterface<std::string>* stackPtr)
{
for(int i = 0;i< expression.length();i++)
{
// Scanning each character from left.
// If character is a delimiter, move on.
if(expression[i] == ' ' || expression[i] == ',') continue;
// If character is operator, pop two elements from stack, perform operation and push the result back.
else if(IsOperator(expression[i]))
{
// Pop two operands.
int operand2 = stackPtr->peek();
stackPtr->pop();
int operand1 = stackPtr->peek();
stackPtr->pop();
//operand1 and operand2 are reversed in case of Prefix Expression
// Perform operation
int result = PerformOperation(expression[i], operand1, operand2);
//Push back result of operation on stack.
stackPtr->push(result);
}
else if(IsNumericDigit(expression[i]))
{
// Extract the numeric operand from the string
// Keep incrementing i as long as you are getting a numeric digit.
int operand = 0;
while(i<expression.length() && IsNumericDigit(expression[i]))
{
// For a number with more than one digits, as we are scanning from left to right.
// Everytime , we get a digit towards right, we can multiply current total in operand by 10
// and add the new digit.
operand = (operand*10) + (expression[i] - '0');
std::cout << operand << std::endl;
i++;
}
// Finally, you will come out of while loop with i set to a non-numeric character or end of string
// decrement i because it will be incremented in increment section of loop once again.
// We do not want to skip the non-numeric character by incrementing i twice.
i--;
// Push operand on stack.
stackPtr->push(operand);
}
}
// If expression is in correct format, Stack will finally have one element. This will be the output.
return stackPtr->top();
}
int main(){
StackInterface<std::string>* stackPtr = new ArrayStack<std::string>();
std::string expression;
std::cout<<"Enter Postfix Expression \n";
std::getline(std::cin,expression);
EvaluatePostfix(expression, stackPtr)
std::cout << stackPtr->push(expression);
}
ArrayStack.h:
#ifndef ARRAY_STACK_EXCEPTIONS
#define ARRAY_STACK_EXCEPTIONS
#include "StackInterface.h"
#include "PrecondViolatedExcep.h"
const int MAX_STACK = 1000;
template<class ItemType>
class ArrayStack : public StackInterface<ItemType>
{
private:
ItemType items[MAX_STACK]; // Array of stack items
int top; // Index to top of stack
public:
ArrayStack();
bool isEmpty() const;
bool push(const ItemType& newEntry);
bool pop();
ItemType peek() const;
}; // end ArrayStack
template<class ItemType>
ArrayStack<ItemType>::ArrayStack() : top(-1)
{
} // end default constructor
// Copy constructor and destructor are supplied by the compiler
template<class ItemType>
bool ArrayStack<ItemType>::isEmpty() const
{
return top < 0;
} // end isEmpty
template<class ItemType>
bool ArrayStack<ItemType>::push(const ItemType& newEntry)
{
bool result = false;
if (top < MAX_STACK - 1)
{
// Stack has room for another item
top++;
items[top] = newEntry;
result = true;
} // end if
return result;
} // end push
template<class ItemType>
bool ArrayStack<ItemType>::pop()
{
bool result = false;
if (!isEmpty())
{
result = true;
top--;
} // end if
return result;
} // end pop
template<class ItemType>
ItemType ArrayStack<ItemType>::peek() const
{
// Enforce precondition
if (isEmpty())
throw PrecondViolatedExcep("peek() called with empty stack");
// Stack is not empty; return top
return items[top];
} // end peek
编辑:我在用“0”减去 stackPtr->peek()
时得到的错误是“与 'operator-' 不匹配(操作数类型是 'std::basic_stringchar' 和
字符'"
谢谢!
这里的问题是您正在交替使用 std::string
、char
和 int
,而它们不是。
请注意,您堆栈的数据类型是 string
,并且没有从 string
更改为 int
或 string
到 [=] 的默认方法14=].
根据您的描述,您试图从 string
中获取第一个 char
,您可能会称其为:
c = stackPtr->peek()[0];
或
c = stackPtr->peek().front();
string
到 int
会调用 std::stoi(stackPtr->peek())
,但不确定您是否需要它,因为您正在自己实施它。
所以您可能想将这部分提取为一个单独的函数:
while(i<expression.length() && IsNumericDigit(expression[i]))
{
operand = (operand*10) + (expression[i] - '0');
std::cout << operand << std::endl;
i++;
}
因此,当您从堆栈中获得 string
时,您可以轻松地重复使用它。
我目前正在尝试让这个后缀表达式 eval 起作用,但我相信在 int EvaluatePostfix
函数中我使用的 stackPtr->peek()
不正确,因为每当我尝试获取最高值并减去它通过'0'(未在代码中显示,mb)将其转换为 int 它说它是一个“std::basic_string-char-”所以它不能用 char.
postfix.cpp:
#include <iostream>
#include <string>
#include "ArrayStack.h"
bool IsNumericDigit(char C)
{
if(C >= '0' && C <= '9') return true;
return false;
}
// Function to verify whether a character is operator symbol or not.
bool IsOperator(char C)
{
if(C == '+' || C == '-' || C == '*' || C == '/')
return true;
return false;
}
// Function to perform an operation and return output.
int PerformOperation(char operation, int operand1, int operand2)
{
if(operation == '+') return operand1 +operand2;
else if(operation == '-') return operand1 - operand2;
else if(operation == '*') return operand1 * operand2;
else if(operation == '/') return operand1 / operand2;
else std::cout<<"Unexpected Error \n";
return -1;
}
int EvaluatePostfix(std::string expression, StackInterface<std::string>* stackPtr)
{
for(int i = 0;i< expression.length();i++)
{
// Scanning each character from left.
// If character is a delimiter, move on.
if(expression[i] == ' ' || expression[i] == ',') continue;
// If character is operator, pop two elements from stack, perform operation and push the result back.
else if(IsOperator(expression[i]))
{
// Pop two operands.
int operand2 = stackPtr->peek();
stackPtr->pop();
int operand1 = stackPtr->peek();
stackPtr->pop();
//operand1 and operand2 are reversed in case of Prefix Expression
// Perform operation
int result = PerformOperation(expression[i], operand1, operand2);
//Push back result of operation on stack.
stackPtr->push(result);
}
else if(IsNumericDigit(expression[i]))
{
// Extract the numeric operand from the string
// Keep incrementing i as long as you are getting a numeric digit.
int operand = 0;
while(i<expression.length() && IsNumericDigit(expression[i]))
{
// For a number with more than one digits, as we are scanning from left to right.
// Everytime , we get a digit towards right, we can multiply current total in operand by 10
// and add the new digit.
operand = (operand*10) + (expression[i] - '0');
std::cout << operand << std::endl;
i++;
}
// Finally, you will come out of while loop with i set to a non-numeric character or end of string
// decrement i because it will be incremented in increment section of loop once again.
// We do not want to skip the non-numeric character by incrementing i twice.
i--;
// Push operand on stack.
stackPtr->push(operand);
}
}
// If expression is in correct format, Stack will finally have one element. This will be the output.
return stackPtr->top();
}
int main(){
StackInterface<std::string>* stackPtr = new ArrayStack<std::string>();
std::string expression;
std::cout<<"Enter Postfix Expression \n";
std::getline(std::cin,expression);
EvaluatePostfix(expression, stackPtr)
std::cout << stackPtr->push(expression);
}
ArrayStack.h:
#ifndef ARRAY_STACK_EXCEPTIONS
#define ARRAY_STACK_EXCEPTIONS
#include "StackInterface.h"
#include "PrecondViolatedExcep.h"
const int MAX_STACK = 1000;
template<class ItemType>
class ArrayStack : public StackInterface<ItemType>
{
private:
ItemType items[MAX_STACK]; // Array of stack items
int top; // Index to top of stack
public:
ArrayStack();
bool isEmpty() const;
bool push(const ItemType& newEntry);
bool pop();
ItemType peek() const;
}; // end ArrayStack
template<class ItemType>
ArrayStack<ItemType>::ArrayStack() : top(-1)
{
} // end default constructor
// Copy constructor and destructor are supplied by the compiler
template<class ItemType>
bool ArrayStack<ItemType>::isEmpty() const
{
return top < 0;
} // end isEmpty
template<class ItemType>
bool ArrayStack<ItemType>::push(const ItemType& newEntry)
{
bool result = false;
if (top < MAX_STACK - 1)
{
// Stack has room for another item
top++;
items[top] = newEntry;
result = true;
} // end if
return result;
} // end push
template<class ItemType>
bool ArrayStack<ItemType>::pop()
{
bool result = false;
if (!isEmpty())
{
result = true;
top--;
} // end if
return result;
} // end pop
template<class ItemType>
ItemType ArrayStack<ItemType>::peek() const
{
// Enforce precondition
if (isEmpty())
throw PrecondViolatedExcep("peek() called with empty stack");
// Stack is not empty; return top
return items[top];
} // end peek
编辑:我在用“0”减去 stackPtr->peek()
时得到的错误是“与 'operator-' 不匹配(操作数类型是 'std::basic_stringchar' 和
字符'"
谢谢!
这里的问题是您正在交替使用 std::string
、char
和 int
,而它们不是。
请注意,您堆栈的数据类型是 string
,并且没有从 string
更改为 int
或 string
到 [=] 的默认方法14=].
根据您的描述,您试图从 string
中获取第一个 char
,您可能会称其为:
c = stackPtr->peek()[0];
或
c = stackPtr->peek().front();
string
到 int
会调用 std::stoi(stackPtr->peek())
,但不确定您是否需要它,因为您正在自己实施它。
所以您可能想将这部分提取为一个单独的函数:
while(i<expression.length() && IsNumericDigit(expression[i]))
{
operand = (operand*10) + (expression[i] - '0');
std::cout << operand << std::endl;
i++;
}
因此,当您从堆栈中获得 string
时,您可以轻松地重复使用它。