most effective & easiest solution for expression evaluation c++ - c++

many programs needs to evaluate expressions like:
input: (T(TF)) ---> output: false (T as true, and F as false)
OR
input (a (b c 2) 3)$ ---> output: abcbcabcbcabcbc
in other words,how to deal with expressions that contain braces?
I used to push to stack until I reach ')'.
then, pop until I reach '(', and so on.
but that would take a long execution time and missy code!
and if I tried to take good of #Henrik code to solve arithmetic expression, I end up with a wrong answer
#include <iostream>
using namespace std;
const char * expressionToParse = "(T(TT))";
char peek()
{
return *expressionToParse;
}
char get()
{
return *expressionToParse++;
}
bool expression();
bool number()
{
bool result = get() - '0';
//even if I remove -'0'
cout<<"number() result:"<<result<<endl;
while (peek() == 'T' || peek() == 'F')
{
if (peek()=='T' && get()=='T') {
result=true;
}
else{
result=false;
}
}
return result;
}
bool factor()
{
if (peek() == 'T' && peek() <= 'F')
return number();
else if (peek() == '(')
{
get(); // '('
bool result = expression();
get(); // ')'
return result;
}
return 0; // error
}
bool expression()
{
bool result = factor();
return result;
}
int main()
{
bool result = expression();
if(result){
cout<<"true";
}
else{
cout<<"false";
}
return 0;
}
Thanks in Advance

This is an expression in postfix form. The easiest way to evaluate a postfix expression can be done using a stack. Search for "postfix expression evaluation" tutorials.

Related

C++ Postfix expression evaluation using stacks. I dont think I'm converting the data correctly

I'm currently trying to get this postfix expression eval to work but I believe within the int EvaluatePostfix function I'm using stackPtr->peek() incorrectly because whenever I try and get the top value and subtract it by '0' (not shown in code, mb) to convert it to int it says it's a "std::basic_string-char-" so it cant do the subtraction with type 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
Edit: The error I get when subtracting stackPtr->peek() by '0' is "no match for 'operator-' (operand types are 'std::basic_stringchar' and
char'"
Thanks!
The problem here is that you are using std::string, char, and int interchangeably, while they are not.
Notice that your data type for you stack is string, and there isn't default way to change from string to int or string to char.
Based on your descriptions, you were trying to get the first char out of the string, which you would probably call either:
c = stackPtr->peek()[0];
or
c = stackPtr->peek().front();
string to int would call std::stoi(stackPtr->peek()), but not sure if you want it as you are implementing it yourself.
So you probably want to extract this part as a separate function:
while(i<expression.length() && IsNumericDigit(expression[i]))
{
operand = (operand*10) + (expression[i] - '0');
std::cout << operand << std::endl;
i++;
}
so you can easily reuse it when you get a string from your stack.

Stack Question (Balanced Expression problem set)

I have solved a problem set for a CPSC class where we have to implement a stack to check if an expression is balanced. For example, when a user enters {a}, the program would check if it has been properly closed and return true or false. My program is running accordingly, but only for char values such as. {, ( & and [. When I enter an input of (2(1+2)) it returns false. The algorithm makes sense and works, but I cannot seem to find the issue with my isBalanced function.
I could really use some help
#ifndef BALANCED_H
#define BALANCED_H
#include<string>
class Balanced {
public:
Balanced(std::string);
bool isBalanced();
bool isMatch(char c, char d);
private:
std::string expression;
};
#endif // BALANCED_H
#include "Balanced.h"
#include <string>
#include<iostream>
#include <stack>
Balanced::Balanced(std::string s) : expression(s)
{
}
bool Balanced::isBalanced()
{
std::stack<char> b;
for(unsigned int i=0; i < expression.size(); i++)
{
if(expression[i]=='{'|| expression[i] == '[' || expression[i] == '(')
{
b.push(expression[i]);
continue;
}
if(b.empty() || !isMatch(b.top(), expression[i]))
{
return false;
}
else{
b.pop();
}
}
return b.empty();
}
bool Balanced::isMatch(char c, char d)
{
if(c == '{' && d == '}')
{
return true;
}
else if(c == '[' && d == ']')
{
return true;
}
else if(c == '(' && d == ')')
{
return true;
}
else
{
return false;
}
}
int main()
{
std::string s;
std::string expression;
std::cout<<"Welcome to balance expression program" <<std::endl;
do{
std::cout<<"Enter any key to continue or type 'Help' to display a help menu ";
std::cout<<"You may also type 'Exit' to exit the program: ";
std::cin>>s;
if(s=="Help")
{
displayHelp();
continue;
}
else if(s=="Exit")
{
break;
}
else{
std::cout<<"Enter an expression: ";
std::cin>>expression;
}
Balanced d(expression);
if(d.isBalanced()!=true){
std::cout<<"The expressions is not balanced";
std::cout<<std::endl;
}
else{
std::cout<<"The expression is balanced";
std::cout<<std::endl;
}
}while(s!="Exit");
return 0;
}
void displayHelp()
{
std::cout<<std::endl;
std::cout<<"The purpose of this program is to check ";
std::cout<<"if an expression is balanced ";
std::cout<<"You will enter an expression and it will check to see if there is
closing ";
std::cout<<"brackets. If the expression is balanced, then it will return true if
not ";
std::cout<<"then the program will return false ";
std::cout<<"You can enter as many expression as you like. If you like to exit
the program, ";
std::cout<<"type 'Exit'"<<std::endl;
std::cout<<std::endl;
}
It would seem that your isMatch function will return false if the current character is not an open or close bracket, thus causing the whole thing to return false.

Function to Evaluate Postfix Resulting in a Segfault

I just had a small question about my program. So, I have a function that evaluates a postfix expression and returns the integer or float calculated. Here are the following functions involved:
#include <iostream>
#include <sstream>
#include <cstring>
#include <stack>
#include <limits>
float postfixUtility::evaluatePostfix(string pexp)
{
stack<int> S;
int pexpLength = pexp.length();
cout << pexpLength << endl;
for (int i = 0; i < pexpLength; i++)
{
if(pexp[i] == ' ' || pexp[i] == ',')
{
continue;
}
else if(isOperator(pexp[i]))
{
int operand2 = S.top(); S.pop();
int operand1 = S.top(); S.pop();
int result = isOperate(pexp[i], operand1, operand2);
S.push(result);
}
else if(isDigit(pexp[i]))
{
int operand = 0;
while(i<pexp.length() && isDigit(pexp[i]))
{
operand = (operand*10) + (pexp[i] - '0');
i++;
}
i--;
S.push(operand);
}
}
return S.top();
}
bool postfixUtility::isDigit(char C)
{
if(C >= '0' && C <= '9')
{
return true;
}
return false;
}
bool postfixUtility::isOperator(char C)
{
if(C == '+' || C == '-' || C == '*' || C == '/')
{
return true;
}
return false;
}
int postfixUtility::isOperate(char operation, int operand1, int operand2)
{
if(operation == '+')
{
return operand1+operand2;
}
if(operation == '-')
{
return operand1-operand2;
}
if(operation == '*')
{
return operand1*operand2;
}
if(operation == '/')
{
return operand1/operand2;
}
}
These functions work together to solve the postfix expression inputted. The expression inputted is not empty and actually holds a postfix expression. However, every time I run the code, it results in a segfault. I am quite baffled actually because it seems to me that my code should work.
Thank you!
EDIT #1: So, the original input to my function is: "(4+3* 12)/ ( 12+ 3/ 2+ 46 /4)"
Then, I put that through another function to convert it to postfix. This is that function:
int postfixUtility::priority(char a)
{
int temp;
if (a == '^')
temp = 1;
else if (a == '*' || a == '/')
temp = 2;
else if (a == '+' || a == '-')
temp = 3;
return temp;
}
string postfixUtility::getPostfix(string nexp)
{
stack<char> operator_stack;
stringstream output;
for (unsigned i = 0; i < nexp.length(); i++) {
if (nexp[i] == '+' || nexp[i] == '-' || nexp[i] == '*' || nexp[i] == '/' || nexp[i] == '^') {
while (!operator_stack.empty() && priority(operator_stack.top()) <= priority(nexp[i])) {
output << operator_stack.top();
operator_stack.pop();
}
operator_stack.push(nexp[i]);
} else if (nexp[i] == '(') {
operator_stack.push(nexp[i]);
} else if (nexp[i] == ')') {
while (operator_stack.top() != '(') {
output << operator_stack.top();
operator_stack.pop();
}
operator_stack.pop();
} else {
output << nexp[i];
}
}
while (!operator_stack.empty()) {
output << operator_stack.top();
operator_stack.pop();
}
//cin.ignore(numeric_limits<streamsize>::max(), '\n');
return output.str();
}
Which converts it to: "43 12*+ 12 3 2/+ 46 4/+/", is that wrong? Would that be the reason why I am getting a segfault?
EDIT #2: So, I have commented out 2 lines in my code and I am no longer getting a segfault.
float postfixUtility::evaluatePostfix(string pexp)
{
stack<int> S;
int pexpLength = pexp.length();
for (int i = 0; i < pexpLength; i++)
{
if(pexp[i] == ' ' || pexp[i] == ',')
{
continue;
}
else if(isOperator(pexp[i]))
{
float operand2 = S.top();
//S.pop();
float operand1 = S.top();
//S.pop();
float result = isOperate(pexp[i], operand1, operand2);
S.push(result);
}
else if(isDigit(pexp[i]))
{
int operand = 0;
while(i<pexp.length() && isDigit(pexp[i]))
{
operand = (operand*10) + (pexp[i] - '0');
i++;
}
i--;
S.push(operand);
}
}
return S.top();
}
However, the answer is supposed to be 1.6, but I am getting 1. Any reason why that is happening?
EDIT #3: I changed the isOperate function to the following:
float postfixUtility::isOperate(char operation, float operand1, float operand2)
{
if(operation == '+')
{
return operand1+operand2;
}
else if(operation == '-')
{
return operand1-operand2;
}
else if(operation == '*')
{
return operand1*operand2;
}
else if(operation == '/')
{
return operand1/operand2;
}
}
However, I still get 1 as a result.
Those pops where important:
float operand2 = S.top();
//S.pop();
float operand1 = S.top();
//S.pop();
Without popping the last element, operand1 will always be equal to operand2 and dividing a number by itself usually results in 1.
The reason you where getting a segfault in the first place is that your postfix converter is giving you (very) wrong results (which should be clear from the fact that its output contains numbers not present in its input). Let's have look at the first part of the output you posted: 43 12*+. Your parser will identify 43 and 12 as numbers and push them on the stack. It will identify * as an operator, take the two numbers from the stack, multiply them and push the result on the stack. Then it will encounter + and try to take two operands from the stack. However, there's only one element on the stack, namely the result of the multiplication. Calling top() on an empty stack is causing your segfault.
Edit: It is generally a good idea to do a sanity check before performing a operation that could result in undefined behavior for incorrect input.This allows you to either do something to solve the problem or to produce an error message containing diagnostic information (e.g. in your case the operator, the position in the string, the string itself, etc.). This will help you identify such problems more easily.
tl;dr: Fix your postfix converter.

What '$' means when scaning if char in strings are certain symbols?

im studying c++, and im stuck on understanding certain line of code.
bool IsOperator(char C)
{
if(C == '+' || C == '-' || C == '*' || C == '/' || C== '$')
return true;
return false;
}
The program im trying to understand scans if the char in string is operator. If yes, get him a number. Inflix to postflix is the problem here.
int IsRightAssociative(char op)
{
if(op == '$') return true;
return false;
}
Here is what i cant understand, where the program finds the '$' char if i write ((3+2)*3-5)*2??
I will attach the whole code for better understanding
#include<iostream>
#include<stack>
#include<string>
using namespace std;
// Function to convert Infix expression to postfix
string InfixToPostfix(string expression);
// Function to verify whether an operator has higher precedence over other
int HasHigherPrecedence(char operator1, char operator2);
// Function to verify whether a character is operator symbol or not.
bool IsOperator(char C);
// Function to verify whether a character is alphanumeric chanaract (letter or numeric digit) or not.
bool IsOperand(char C);
int main()
{
string expression;
cout<<"Enter Infix Expression \n";
getline(cin,expression);
string postfix = InfixToPostfix(expression);
cout<<"Output = "<<postfix<<"\n";
}
// Function to evaluate Postfix expression and return output
string InfixToPostfix(string expression)
{
// Declaring a Stack from Standard template library in C++.
stack<char> S;
string postfix = ""; // Initialize postfix as empty string.
for(int i = 0;i< expression.length();i++) {
// Scanning each character from left.
// If character is a delimitter, 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]))
{
while(!S.empty() && S.top() != '(' && HasHigherPrecedence(S.top(),expression[i]))
{
postfix+= S.top();
S.pop();
}
S.push(expression[i]);
}
// Else if character is an operand
else if(IsOperand(expression[i]))
{
postfix +=expression[i];
}
else if (expression[i] == '(')
{
S.push(expression[i]);
}
else if(expression[i] == ')')
{
while(!S.empty() && S.top() != '(') {
postfix += S.top();
S.pop();
}
S.pop();
}
}
while(!S.empty()) {
postfix += S.top();
S.pop();
}
return postfix;
}
// Function to verify whether a character is english letter or numeric digit.
// We are assuming in this solution that operand will be a single character
bool IsOperand(char C)
{
if(C >= '0' && C <= '9') return true;
if(C >= 'a' && C <= 'z') return true;
if(C >= 'A' && C <= 'Z') return true;
return false;
}
// Function to verify whether a character is operator symbol or not.
bool IsOperator(char C)
{
if(C == '+' || C == '-' || C == '*' || C == '/' || C== '$')
return true;
return false;
}
// Function to verify whether an operator is right associative or not.
int IsRightAssociative(char op)
{
if(op == '$') return true;
return false;
}
// Function to get weight of an operator. An operator with higher weight will have higher precedence.
int GetOperatorWeight(char op)
{
int weight = -1;
switch(op)
{
case '+':
case '-':
weight = 1;
case '*':
case '/':
weight = 2;
case '$':
weight = 3;
}
return weight;
}
// Function to perform an operation and return output.
int HasHigherPrecedence(char op1, char op2)
{
int op1Weight = GetOperatorWeight(op1);
int op2Weight = GetOperatorWeight(op2);
// If operators have equal precedence, return true if they are left associative.
// return false, if right associative.
// if operator is left-associative, left one should be given priority.
if(op1Weight == op2Weight)
{
if(IsRightAssociative(op1)) return false;
else return true;
}
return op1Weight > op2Weight ? true: false;
}
So if anyone can help i will be very glad :(.

Boolean Function to Check Validity of Expression Recursively?

I want to create a kind of parser of the form:
#include <iostream>
#include <string>
#include <sstream>
#include <cctype>
using namespace std;
bool isValid(istringstream& is)
{
char ch;
is.get(ch); //I know get(ch) is a good start but this is as for as I got :)
.......
....
}
int main()
{
string s;
while(getline(cin,s))
{
istringstream is(s);
cout<<(isValid(is)? "Expression OK" : "Not OK")<<endl;
}
}
A boolean function that returns TRUE if the sequence of char is of the form "5" or "(5+3)" or "((5+3)+6)" or "(((4+2)+1)+6)" ...etc and FALSE for any other case
Basically, an expression will be considered as valid if it is either a single digit or of the form "open parenthesis-single digit-plus sign-single digit-close parenthesis"
Valid Expression = single digit
and
Valid Expression = (Valid Expression + Valid Expression)
Given that there is no limit to the size of the above form (number of opening and closing parenthesis..etc.) I'd like to do that using recursion
Being the newbie that I am.. Thank you for any helpful input!
To do a recursive solution you're gonna want to read the string into a buffer first, then do something like this:
int expression(char* str) {
if (*str == '(') {
int e1 = expression(str + 1);
if (e1 == -1 || *(str + 1 + e) != '+') {
return -1;
}
int e2 = expression(str + 1 + e + 1);
if (e2 == -1 || *(str + 1 + e + 1 + e2) != ')') {
return -1;
}
return 1 + e1 + 1 + e2 + 1;
}
if (*str >= '0' || *str <= '9') {
return 1;
}
return -1;
}
bool isvalid(char* str) {
int e1 = expression(str);
if (e1 < 0) {
return false;
}
if (e1 == strlen(str)) {
return true;
}
if (*(str + e1) != '+') {
return false;
}
int e2 = expression(str + e1 + 1);
if (e2 < 0) {
return false;
}
return (e1 + 1 + e2 == strlen(str));
}
Basically, the expression function returns the length of the valid expression at it's argument. If it's argument begins with a parenthesis, it gets the length of the expression after that, verifies the plus after that, then verifies the closing parenthesis after the next expression. If the argument begins with a number, return 1. If something is messed up, return -1. Then using that function we can figure out whether or not the string is valid by some sums and the length of the string.
I haven't tested the function at all, but the only case this might fail in that I can think of would be excessive parenthesis: ((5)) for example.
An alternative to recursion could be some sort of lexical parsing such as this:
enum {
ExpectingLeftExpression,
ExpectingRightExpression,
ExpectingPlus,
ExpectingEnd,
} ParseState;
// returns true if str is valid
bool check(char* str) {
ParseState state = ExpectingLeftExpression;
do {
switch (state) {
case ExpectingLeftExpression:
if (*str == '(') {
} else if (*str >= '0' && *str <= '9') {
state = ExpectingPlus;
} else {
printf("Error: Expected left hand expression.");
return false;
}
break;
case ExpectingPlus:
if (*str == '+') {
state = ExpectingRightExpression;
} else {
printf("Error: Expected plus.");
return false;
}
break;
case ExpectingRightExpression:
if (*str == '(') {
state = ExpectingLeftExpression;
} else if (*str >= '0' && *str <= '9') {
state = ExpectingEnd;
} else {
printf("Error: Expected right hand expression.");
return false;
}
break;
}
} while (*(++str));
return true;
}
That function's not complete at all, but you should be able to see where it's going. I think the recursion works better in this case anyways.