novice coder here and I've been asking around how I should go about creating a two stack algorithm for calculating simple expressions (Dijkstra's Two Stack Algorithm) in C++. A quick refresher for anybody that need it:
Two Stack Algorithm:
Value - Push onto value stack
Operator - Push onto operator stack
Left Parenthesis - Ignore
Right Parenthesis - Pop two values from value stack and one value from operator stack and push the result
It appears that using istringstream, which was recommended to me, should allow me to separate the user inputted expression into basic, doubles, and non-doubles. This should allow me to populate my vals and ops stack respectively, however upon debugging, I realized that my vals stack ended up empty at the end (causing a segmentation fault)
I've got no idea what I'm doing wrong, and any help would be appreciated! Keep in mind I am relatively new to coding and my syntax is probably horrible, therefore any type of criticism is welcome.
For reference an input of:
( 1 + ( ( 2 + 3 ) * ( 4 * 5 ) ) )
Should output:
101
Thus far my code looks like this:
stack<string> ops;
stack<double> vals;
string input;
getline(cin, input);
istringstream scanner(input);
while(true){
double num;
scanner >> num;
if(scanner.fail() && scanner.eof()) break;
else if(!scanner.fail()) vals.push(num);
else{
scanner.clear();
string token;
scanner >> token;
if(token == "(") ;
else if(token == "+") ops.push(token);
else if(token == "*") ops.push(token);
/*Add more operations here (Log, sin, cos...)*/
else if(token == ")"){
string op = ops.top();
ops.pop();
if(op == "+"){
double a, b;
a = vals.top();
vals.pop();
b = vals.top();
vals.pop();
vals.push(a+b);
}
else if(op == "*"){
double a, b;
a = vals.top();
vals.pop();
b = vals.top();
vals.pop();
vals.push(a*b);
}
/*Add more operations here*/
}
}
return vals.top();
}
Thank you for your help!
Turns out the problem was with this:
scanner >> num;
if (scanner.fail() && scanner.eof()) break;
else if (!scanner.fail()) vals.push(num);
Changing it to the following fixed the problem:
if (scanner >> num) vals.push(num);
if (scanner.fail() && scanner.eof()) break;
else {
// ...
}
And putting the return statement below the loop also helped.
Live example
Not a straightforward answer to what you asked, but I reworked your example with out the use of stringstreams, which might be confusing to you. You can use the following code as an alternative:
#include <iostream>
#include <string>
#include <stack>
#include <ctype.h>
double parseExpression(std::string const &expr)
{
std::stack<char> ops;
std::stack<double> vals;
std::string num;
for (auto c : expr) {
if (c == '+' || c == '*') {
if(!num.empty()) vals.push(std::stod(num));
num.clear();
ops.push(c);
} else if (c == ')') {
if (!num.empty()) vals.push(std::stod(num));
num.clear();
char op = ops.top();
ops.pop();
switch (op) {
case '+': {
double tmp = vals.top();
vals.pop();
tmp += vals.top();
vals.pop();
vals.push(tmp);
} break;
case '*': {
double tmp = vals.top();
vals.pop();
tmp *= vals.top();
vals.pop();
vals.push(tmp);
} break;
};
num.clear();
} else if(isdigit(c) || c == '.') {
num.push_back(c);
} else if (isspace(c)) {
if (!num.empty()) vals.push(std::stod(num));
num.clear();
} else if(c != '(') {
throw std::runtime_error("Unknown character in expression!");
}
}
return vals.top();
}
int main()
{
std::string expr("( 1.00 + ( ( 2.000000 + 3.00 ) * ( 4.00 * 5.00 ) ) )");
std::cout << expr << " = " << parseExpression(expr) << std::endl;
return 0;
}
HTH
Related
This question already has answers here:
What is causing the "error LNK2005: already defined in .obj" s errors in my code?
(1 answer)
What does this error mean and how do I solve it: error LNK2005: "<symbol>" already defined in <file.obj>
(1 answer)
Closed 2 months ago.
I'm trying to import a lightweight maths parsing library. It is only available as a .cpp file. (this is the library)
When I import it using #include mathparser.cpp, I get loads of LNK2005 errors, saying it is defining all the class methods again.
I'm not actually defining them in the main file though, why might these errors be occuring, and what should I do to fix them?
You should never #include a cpp file. You should include header files, and ensure they have header guards (or use #pragma once). In this case the mathparser.cpp should be split up such that the parser class is in its own header and cpp file, then just main is in the cpp file.
mathparser.h
#pragma once
#include < iostream >
#include < cstdlib >
#include < cctype >
#include < cstring >
#include < math.h >
#define PI 3.14159265358979323846
using namespace std;
enum types { DELIMITER = 1, VARIABLE, NUMBER, FUNCTION };
const int NUMVARS = 26;
class parser {
char *exp_ptr; // points to the expression
char token[256]; // holds current token
char tok_type; // holds token's type
double vars[NUMVARS]; // holds variable's values
void eval_exp1(double &result);
void eval_exp2(double &result);
void eval_exp3(double &result);
void eval_exp4(double &result);
void eval_exp5(double &result);
void eval_exp6(double &result);
void get_token();
public:
parser();
double eval_exp(char *exp);
char errormsg[64];
};
mathparser.cpp
#include "stdafx.h"
#include "mathparser.h"
// Parser constructor.
parser::parser()
{
int i;
exp_ptr = NULL;
for (i = 0; i < NUMVARS; i++)
vars[i] = 0.0;
errormsg[0] = '\0';
}
// Parser entry point.
double parser::eval_exp(char *exp)
{
errormsg[0] = '\0';
double result;
exp_ptr = exp;
get_token();
if (!*token)
{
strcpy(errormsg, "No Expression Present"); // no expression present
return (double)0;
}
eval_exp1(result);
if (*token) // last token must be null
strcpy(errormsg, "Syntax Error");
return result;
}
// Process an assignment.
void parser::eval_exp1(double &result)
{
int slot;
char temp_token[80];
if (tok_type == VARIABLE)
{
// save old token
char *t_ptr = exp_ptr;
strcpy(temp_token, token);
// compute the index of the variable
slot = *token - 'A';
get_token();
if (*token != '=')
{
exp_ptr = t_ptr; // return current token
strcpy(token, temp_token); // restore old token
tok_type = VARIABLE;
}
else {
get_token(); // get next part of exp
eval_exp2(result);
vars[slot] = result;
return;
}
}
eval_exp2(result);
}
// Add or subtract two terms.
void parser::eval_exp2(double &result)
{
register char op;
double temp;
eval_exp3(result);
while ((op = *token) == '+' || op == '-')
{
get_token();
eval_exp3(temp);
switch (op)
{
case '-':
result = result - temp;
break;
case '+':
result = result + temp;
break;
}
}
}
// Multiply or divide two factors.
void parser::eval_exp3(double &result)
{
register char op;
double temp;
eval_exp4(result);
while ((op = *token) == '*' || op == '/')
{
get_token();
eval_exp4(temp);
switch (op)
{
case '*':
result = result * temp;
break;
case '/':
result = result / temp;
break;
}
}
}
// Process an exponent.
void parser::eval_exp4(double &result)
{
double temp;
eval_exp5(result);
while (*token == '^')
{
get_token();
eval_exp5(temp);
result = pow(result, temp);
}
}
// Evaluate a unary + or -.
void parser::eval_exp5(double &result)
{
register char op;
op = 0;
if ((tok_type == DELIMITER) && *token == '+' || *token == '-')
{
op = *token;
get_token();
}
eval_exp6(result);
if (op == '-')
result = -result;
}
// Process a function, a parenthesized expression, a value or a variable
void parser::eval_exp6(double &result)
{
bool isfunc = (tok_type == FUNCTION);
char temp_token[80];
if (isfunc)
{
strcpy(temp_token, token);
get_token();
}
if ((*token == '('))
{
get_token();
eval_exp2(result);
if (*token != ')')
strcpy(errormsg, "Unbalanced Parentheses");
if (isfunc)
{
if (!strcmp(temp_token, "SIN"))
result = sin(PI / 180 * result);
else if (!strcmp(temp_token, "COS"))
result = cos(PI / 180 * result);
else if (!strcmp(temp_token, "TAN"))
result = tan(PI / 180 * result);
else if (!strcmp(temp_token, "ASIN"))
result = 180 / PI*asin(result);
else if (!strcmp(temp_token, "ACOS"))
result = 180 / PI*acos(result);
else if (!strcmp(temp_token, "ATAN"))
result = 180 / PI*atan(result);
else if (!strcmp(temp_token, "SINH"))
result = sinh(result);
else if (!strcmp(temp_token, "COSH"))
result = cosh(result);
else if (!strcmp(temp_token, "TANH"))
result = tanh(result);
else if (!strcmp(temp_token, "ASINH"))
result = asinh(result);
else if (!strcmp(temp_token, "ACOSH"))
result = acosh(result);
else if (!strcmp(temp_token, "ATANH"))
result = atanh(result);
else if (!strcmp(temp_token, "LN"))
result = log(result);
else if (!strcmp(temp_token, "LOG"))
result = log10(result);
else if (!strcmp(temp_token, "EXP"))
result = exp(result);
else if (!strcmp(temp_token, "SQRT"))
result = sqrt(result);
else if (!strcmp(temp_token, "SQR"))
result = result*result;
else if (!strcmp(temp_token, "ROUND"))
result = round(result);
else if (!strcmp(temp_token, "INT"))
result = floor(result);
else
strcpy(errormsg, "Unknown Function");
}
get_token();
}
else
switch (tok_type)
{
case VARIABLE:
result = vars[*token - 'A'];
get_token();
return;
case NUMBER:
result = atof(token);
get_token();
return;
default:
strcpy(errormsg, "Syntax Error");
}
}
// Obtain the next token.
void parser::get_token()
{
register char *temp;
tok_type = 0;
temp = token;
*temp = '\0';
if (!*exp_ptr) // at end of expression
return;
while (isspace(*exp_ptr)) // skip over white space
++exp_ptr;
if (strchr("+-*/%^=()", *exp_ptr))
{
tok_type = DELIMITER;
*temp++ = *exp_ptr++; // advance to next char
}
else if (isalpha(*exp_ptr))
{
while (!strchr(" +-/*%^=()\t\r", *exp_ptr) && (*exp_ptr))
*temp++ = toupper(*exp_ptr++);
while (isspace(*exp_ptr)) // skip over white space
++exp_ptr;
tok_type = (*exp_ptr == '(') ? FUNCTION : VARIABLE;
}
else if (isdigit(*exp_ptr) || *exp_ptr == '.')
{
while (!strchr(" +-/*%^=()\t\r", *exp_ptr) && (*exp_ptr))
*temp++ = toupper(*exp_ptr++);
tok_type = NUMBER;
}
*temp = '\0';
if ((tok_type == VARIABLE) && (token[1]))
strcpy(errormsg, "Only first letter of variables is considered");
}
main.cpp
#include "mathparser.h"
int main()
{
char expstr[256];
parser ob;
cout << "Math expression parser. Enter a blank line to stop.\n\n";
do
{
cout << "Enter expression: ";
cin.getline(expstr, 255);
double ans = ob.eval_exp(expstr);
if (*ob.errormsg)
cout << "Error: " << ob.errormsg << "\n\n";
else
cout << "Answer: " << ans << "\n\n";
} while (*expstr);
return 0;
}
Then in your code you can #include "mathparser.h" to instantiate the parser class for your purposes.
Note that this code itself is full of poor practices and therefore a bad reference to study for learning modern C++, but that is outside the scope of your current question.
My lecturer gave me an assignment to create a program to convert and infix expression to postfix using Stacks. I've made the stack classes and some functions to read the infix expression.
But this one function, called convertToPostfix(char * const inFix, char * const postFix) which is responsible to convert the inFix expression in the array inFix to the post fix expression in the array postFix using stacks, is not doing what it suppose to do. Can you guys help me out and tell me what I'm doing wrong?
The following is code where the functions to convert from inFix to postFix is and convertToPostfix(char * const inFix, char * const postFix) is what I need help fixing:
void ArithmeticExpression::inputAndConvertToPostfix()
{
char inputChar; //declaring inputChar
int i = 0; //inizalize i to 0
cout << "Enter the Arithmetic Expression(No Spaces): ";
while( ( inputChar = static_cast<char>( cin.get() ) ) != '\n' )
{
if (i >= MAXSIZE) break; //exits program if i is greater than or equal to 100
if(isdigit(inputChar) || isOperator(inputChar))
{
inFix[i] = inputChar; //copies each char to inFix array
cout << inFix[i] << endl;
}
else
cout << "You entered an invalid Arithmetic Expression\n\n" ;
}
// increment i;
i++;
convertToPostfix(inFix, postFix);
}
bool ArithmeticExpression::isOperator(char currentChar)
{
if(currentChar == '+')
return true;
else if(currentChar == '-')
return true;
else if(currentChar == '*')
return true;
else if(currentChar == '/')
return true;
else if(currentChar == '^')
return true;
else if(currentChar == '%')
return true;
else
return false;
}
bool ArithmeticExpression::precedence(char operator1, char operator2)
{
if ( operator1 == '^' )
return true;
else if ( operator2 == '^' )
return false;
else if ( operator1 == '*' || operator1 == '/' )
return true;
else if ( operator1 == '+' || operator1 == '-' )
if ( operator2 == '*' || operator2 == '/' )
return false;
else
return true;
return false;
}
void ArithmeticExpression::convertToPostfix(char * const inFix, char * const postFix)
{
Stack2<char> stack;
const char lp = '(';
stack.push(lp); //Push a left parenthesis ‘(‘ onto the stack.
strcat(inFix,")");//Appends a right parenthesis ‘)’ to the end of infix.
// int i = 0;
int j = 0;
if(!stack.isEmpty())
{
for(int i = 0;i < 100;){
if(isdigit(inFix[i]))
{
postFix[j] = inFix[i];
cout << "This is Post Fix for the first If: " << postFix[j] << endl;
i++;
j++;
}
if(inFix[i] == '(')
{
stack.push(inFix[i]);
cout << "The InFix was a (" << endl;
i++;
//j++;
}
if(isOperator(inFix[i]))
{
char operator1 = inFix[i];
cout << "CUrrent inFix is a operator" << endl;
if(isOperator(stack.getTopPtr()->getData()))
{
cout << "The stack top ptr is a operator1" << endl;
char operator2 = stack.getTopPtr()->getData();
if(precedence(operator1,operator2))
{
//if(isOperator(stack.getTopPtr()->getData())){
cout << "The stack top ptr is a operato2" << endl;
postFix[j] = stack.pop();
cout << "this is post fix " << postFix[j] << endl;
i++;
j++;
// }
}
}
else
stack.push(inFix[i]);
// cout << "Top Ptr is a: "<< stack.getTopPtr()->getData() << endl;
}
for(int r = 0;r != '\0';r++)
cout << postFix[r] << " ";
if(inFix[i] == ')')
{
while(stack.stackTop()!= '(')
{
postFix[j] = stack.pop();
i++;
j++;
}
stack.pop();
}
}
}
}
Note the function convertToPostfix was made using this algorithm:
Push a left parenthesis ‘(‘ onto the stack.
Append a right parenthesis ‘)’ to the end of infix.
While the stack is not empty, read infix from left to right and do the following:
If the current character in infix is a digit, copy it to the next element of postfix.
If the current character in infix is a left parenthesis, push it onto the stack.
If the current character in infix is an operator,
Pop operator(s) (if there are any) at the top of the stack while they have equal or higher precedence than the current operator, and insert the popped operators in postfix.
Push the current character in infix onto the stack.
If the current character in infix is a right parenthesis
Pop operators from the top of the stack and insert them in postfix until a left parenthesis is at the top of the stack.
Pop (and discard) the left parenthesis from the stack.
This is basically a comment to the answer from Yuushi.
The outer while(!stack.empty()) loop is wrong. just remove it. (keep the loop body ofc). At the end of the function, check that the stack is empty, else the expression had syntax errors.
As Yuushi already said the precedence function looks bogus. First you should give the parameters better names: one is the operator to the left, and the other to the right. (Right now you call it precedence(rightOp, leftOp)). Then you should document what the result means - right now you return true if a rOp b lOp c == (a rOp b) lOp c (yes, the operator order doesn't match what you call - "+" and "-" are not the same in both orders for example).
If you find a new operator you need to loop over the old operators on the stack, for example after reading a - b * c your output is a b c and the stack is [- *]. now you read a +, and you need to pop both operators, resulting in a b c * -. I.e., the input a - b * c + d should result in a b c * - d +
Update: appended complete solution (based on Yuushi's answer):
bool isOperator(char currentChar)
{
switch (currentChar) {
case '+':
case '-':
case '*':
case '/':
case '^':
case '%':
return true;
default:
return false;
}
}
// returns whether a `lOp` b `rOp` c == (a `lOp` b) `rOp` c
bool precedence(char leftOperator, char rightOperator)
{
if ( leftOperator == '^' ) {
return true;
} else if ( rightOperator == '^' ) {
return false;
} else if ( leftOperator == '*' || leftOperator == '/' || leftOperator == '%' ) {
return true;
} else if ( rightOperator == '*' || rightOperator == '/' || rightOperator == '%' ) {
return false;
}
return true;
}
#include <stdexcept>
#include <cctype>
#include <sstream>
#include <stack>
std::string convertToPostfix(const std::string& infix)
{
std::stringstream postfix; // Our return string
std::stack<char> stack;
stack.push('('); // Push a left parenthesis ‘(‘ onto the stack.
for(std::size_t i = 0, l = infix.size(); i < l; ++i) {
const char current = infix[i];
if (isspace(current)) {
// ignore
}
// If it's a digit or '.' or a letter ("variables"), add it to the output
else if(isalnum(current) || '.' == current) {
postfix << current;
}
else if('(' == current) {
stack.push(current);
}
else if(isOperator(current)) {
char rightOperator = current;
while(!stack.empty() && isOperator(stack.top()) && precedence(stack.top(), rightOperator)) {
postfix << ' ' << stack.top();
stack.pop();
}
postfix << ' ';
stack.push(rightOperator);
}
// We've hit a right parens
else if(')' == current) {
// While top of stack is not a left parens
while(!stack.empty() && '(' != stack.top()) {
postfix << ' ' << stack.top();
stack.pop();
}
if (stack.empty()) {
throw std::runtime_error("missing left paren");
}
// Discard the left paren
stack.pop();
postfix << ' ';
} else {
throw std::runtime_error("invalid input character");
}
}
// Started with a left paren, now close it:
// While top of stack is not a left paren
while(!stack.empty() && '(' != stack.top()) {
postfix << ' ' << stack.top();
stack.pop();
}
if (stack.empty()) {
throw std::runtime_error("missing left paren");
}
// Discard the left paren
stack.pop();
// all open parens should be closed now -> empty stack
if (!stack.empty()) {
throw std::runtime_error("missing right paren");
}
return postfix.str();
}
#include <iostream>
#include <string>
int main()
{
for (;;) {
if (!std::cout.good()) break;
std::cout << "Enter the Arithmetic Expression: ";
std::string infix;
std::getline(std::cin, infix);
if (infix.empty()) break;
std::cout << "Postfix: '" << convertToPostfix(infix) << "'\n";
}
return 0;
}
So there are a number of problems with your code. I'll post what (should be) a corrected solution, which has copious comments to explain what's happening and where you've made mistakes. A few things up front:
I'll use std::string instead of char * because it makes things much cleaner, and honestly, you should be using it in C++ unless you have a very good reason not to (such as interoperability with a C library). This version also returns a string instead of taking a char * as a parameter.
I'm using the stack from the standard library, <stack>, which is slightly different to your home-rolled one. top() shows you the next element without removing it from the stack, and pop() returns void, but removes the top element from the stack.
It's a free function, not part of a class, but that should be easy to modify - it's simply easier for me to test this way.
I'm not convinced your operator precedence tables are correct, however, I'll let you double check that.
#include <stack>
#include <cctype>
#include <iostream>
std::string convertToPostfix(std::string& infix)
{
std::string postfix; //Our return string
std::stack<char> stack;
stack.push('('); //Push a left parenthesis ‘(‘ onto the stack.
infix.push_back(')');
//We know we need to process every element in the string,
//so let's do that instead of having to worry about
//hardcoded numbers and i, j indecies
for(std::size_t i = 0; i < infix.size(); ++i) {
//If it's a digit, add it to the output
//Also, if it's a space, add it to the output
//this makes it look a bit nicer
if(isdigit(infix[i]) || isspace(infix[i])) {
postfix.push_back(infix[i]);
}
//Already iterating over i, so
//don't need to worry about i++
//Also, these options are all mutually exclusive,
//so they should be else if instead of if.
//(Mutually exclusive in that if something is a digit,
//it can't be a parens or an operator or anything else).
else if(infix[i] == '(') {
stack.push(infix[i]);
}
//This is farily similar to your code, but cleaned up.
//With strings we can simply push_back instead of having
//to worry about incrementing some counter.
else if(isOperator(infix[i]))
{
char operator1 = infix[i];
if(isOperator(stack.top())) {
while(!stack.empty() && precedence(operator1,stack.top())) {
postfix.push_back(stack.top());
stack.pop();
}
}
//This shouldn't be in an else - we always want to push the
//operator onto the stack
stack.push(operator1);
}
//We've hit a right parens - Why you had a for loop
//here originally I don't know
else if(infix[i] == ')') {
//While top of stack is not a right parens
while(stack.top() != '(') {
//Insert into postfix and pop the stack
postfix.push_back(stack.top());
stack.pop();
}
// Discard the left parens - you'd forgotten to do this
stack.pop();
}
}
//Remove any remaining operators from the stack
while(!stack.empty()) {
postfix.push_back(stack.top());
stack.pop();
}
}
Here's mine using C with multiple digits evaluation.
#include <stdio.h>
#include <math.h>
#define MAX 50
void push(char[],char);
void in_push(double[], double);
int pop();
int prec(char);
double eval(char[],int,double[]);
int top = 0;
void main() {
double eval_stack[MAX];
int op_count=0;
char stack[MAX], exps[MAX], symbols[MAX];
int i=0,j=0,len,check;
while((symbols[i]=getchar())!='\n') {
if(symbols[i]!=' ' || symbols[i]!='\t') {
if(symbols[i]=='+' || symbols[i]=='-' || symbols[i]=='/' || symbols[i]=='*' || symbols[i]=='^')
op_count++;
i++;
}
}
symbols[i]='#';
symbols[++i]='\0';
len = strlen(symbols);
stack[top] = '#';
for(i=0; i<=len; i++) {
if(symbols[i]>='a' && symbols[i]<='z') {
exps[j]=symbols[i];
j++;
}
switch(symbols[i]) {
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
//if(symbols[i]>='a' && symbols[i]<='z') {
exps[j]=symbols[i];
j++;
break;
case '+': case '-': case '*': case '/': case '^':
exps[j++] = ' ';
while(prec(symbols[i]) <= prec(stack[top])) {
exps[j] = stack[top];
pop();
//printf("\n\t\t%d\t\t%d\n", top,j);
j++;
}
if(prec(symbols[i]) > prec(stack[top])) {
push(stack,symbols[i]);
}
break;
case '(':
push(stack,symbols[i]);
break;
case ')':
while(stack[top]!='(') {
exps[j] = stack[top];
pop();
j++;
}
pop();
break;
case '#':
exps[j++] = ' ';
while(stack[top]!='#') {
exps[j] = stack[top];
pop();
j++;
}
pop();
break;
}
}
exps[j]='\0';
printf("Postfix: %s", exps);
for(i=0; i<j; i++)
if(exps[i]=='a')
check = 1;
if(check!=1)
printf("\nSolution: %.1f", eval(exps,j,eval_stack));
}
double eval(char exps[],int exps_len,double eval_stack[]) {
int i; int len=exps_len,temp;
double in_temp[MAX],t;
int count,power,j,in_count;
count=power=j=t=in_count=0;
double result;
for(i=0; i<len; i++) {
switch(exps[i]) {
case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
in_temp[i] = exps[i]-'0';
j=i+1;
while(exps[j]>='0' && exps[j]<='9') {
in_temp[j] = exps[j]-'0';
j++; // 2
}
count = i; // 3
while(in_temp[count]<='0' && in_temp[count]<='9') {
power = (j-count)-1;
t = t + in_temp[count]*(pow(10,power));
power--;
count++;
}
in_push(eval_stack,t);
i=j-1;
t=0;
break;
case '+':
temp = pop();
pop();
result = eval_stack[temp] + eval_stack[temp+1];
in_push(eval_stack,result);
break;
case '-':
temp = pop();
pop();
result = eval_stack[temp] - eval_stack[temp+1];
in_push(eval_stack,result);
break;
case '*':
temp = pop();
pop();
result = eval_stack[temp] * eval_stack[temp+1];
in_push(eval_stack,result);
break;
case '/':
temp = pop();
pop();
result = eval_stack[temp] / eval_stack[temp+1];
in_push(eval_stack,result);
break;
case '^':
temp = pop();
pop();
result = pow(eval_stack[temp],eval_stack[temp+1]);
in_push(eval_stack,result);
break;
}
}
return eval_stack[top];
}
int prec(char a) {
if(a=='^')
return 3;
else if(a=='*' || a=='/' || a=='%')
return 2;
else if(a=='+' || a=='-')
return 1;
else if(a=='(')
return 0;
else
return -1;
}
void push(char stack[], char ele) {
if(top>=MAX) {
printf("\nStack Overflow");
exit(1);
}
stack[++top] = ele;
}
void in_push(double stack[], double ele) {
if(top>=MAX) {
printf("\nStack Overflow");
exit(1);
}
stack[++top] = ele;
}
int pop() {
if(top<0) {
printf("\nStack Underflow");
exit(1);
}
top = top - 1;
return top;
}
This is my implementation of converting infix to postfix expression
//Infix to Postfix conversion
#include <bits/stdc++.h>
using namespace std;
bool isoperator(char c) // function to check if the character is an operator
{
if(c=='+'||c=='-'||c=='*'||c=='/'||c=='^')
return true;
else
return false;
}
int precedence(char c) // function to given the precedence of the operators
{
if(c == '^')
return 3;
else if(c == '*' || c == '/')
return 2;
else if(c == '+' || c == '-')
return 1;
else
return -1;
}
void infixToPostfix(string s) // funtion to convert infix to postfix
{
stack<char>st;
string postfix;
for(int i=0;i<s.length();i++)
{
if((s[i]>='a'&&s[i]<='z')||(s[i]>='A'&&s[i]<='Z')) // if the given character is alphabet add it to the postfix string
postfix+=s[i];
else if(s[i]=='(') // if the given character is "(" add it to the postfix string
st.push('(');
else if(s[i]==')') // if we find a closing bracket we pop everything from stack till opening bracket and add it to postfix string
{
while(st.top()=='(' && !st.empty())
{
postfix+=st.top();
st.pop();
}
if(st.top()=='(') // popping the opening bracket
st.pop();
}
else if(isoperator(s[i])) // if we find a operator
{
if(st.empty()) // if stack is empty add it to the stack
st.push(s[i]);
else
{
if(precedence(s[i])>precedence(st.top())) // if operator precedence is grater push it in stack
st.push(s[i]);
else if((precedence(s[i])==precedence(st.top()))&&(s[i]=='^')) // unique case for ^ operator
st.push(s[i]);
else
{
while((!st.empty())&&(precedence(s[i])<=precedence(st.top()))) // if precedence of st.top() is greater than s[i] adding it the postfix string
{
postfix+=st.top();
st.pop();
}
st.push(s[i]); // pushing s[i] in the stack
}
}
}
}
while(!st.empty()) // popping the remaining items from the stack and adding it to the postfix string
{
postfix+=st.top();
st.pop();
}
cout<<postfix<<endl; // printing the postfix string
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
string s;
cin>>s;
infixToPostfix(s);
return 0;
}
Example:
Input: a+b*(c^d-e)^(f+g*h)-i
Output: abcd^efgh*+i-(^-(*+
ps: If you find any mistakes, comment below :)
C++ implementation is given below:
void infix2postfix(string s)
{
stack<char>st;
for(int i=0; i<s.length(); i++)
{
if(isdigit(s[i]) || isalpha(s[i])) cout<<s[i];
else if( s[i]==')' )
{
while(st.top()!='(')
{
cout<<st.top();
st.pop();
}
st.pop();
}
else st.push(s[i]);
}
}
Operator Precedence is the problem in this case. The correct operator precedence in descending order is:
mul, div, mod << *, /, % >>
add, sub << +, - >>
XOR << ^ >>
In the question above consider the precedence function
bool ArithmeticExpression::precedence(char operator1, char operator2)
{
if ( operator1 == '^' )
return true;
else if ( operator2 == '^' )
return false;
else if ( operator1 == '*' || operator1 == '/' )
return true;
else if ( operator1 == '+' || operator1 == '-' )
if ( operator2 == '*' || operator2 == '/' )
return false;
else
return true;
return false;
}
for each value in operator1 corresponding value of operator2 should be checked for precedence, according to OPERATOR PRECEDENCE TABLE mentioned above. Do not return any value without proper comparison.
Having trouble getting the correct outcome of
Infix: (A+B)/(C-D) Postfix: AB+CD-/
I keep getting Postfix: AB+C/D-
I do know that the issue is coming from it not being able to pop the last operators from the stack before pushing '(' This is why I added the if statement in the first else if condition. That also doesn't work. What is it exactly that I am doing wrong? Is there another way into tackling this problem?
#include <iostream>
#include <stack>
#include <sstream>
#include <string>
using namespace std;
int precedence(char x) {
int op;
if (x == '(' || x==')')
op = 1;
else if (x == '^')
op = 2;
else if (x == '*')
op = 3;
else if ( x == '/')
op = 4;
else if (x == '+')
op = 5;
else if (x == '-')
op = 6;
return op;
}
int main()
{
string getInfix;
cout << "Infix: ";
getline(cin, getInfix);
stack<char> opStack;
stringstream showInfix;
for (unsigned i = 0; i < getInfix.length(); i++)
{
if (getInfix[i] == '+' || getInfix[i] == '-' || getInfix[i] == '*' || getInfix[i] == '/' || getInfix[i] == '^')
{
while (!opStack.empty() && precedence(opStack.top() <= precedence(getInfix[i]))
{
showInfix << opStack.top();
opStack.pop();
}
opStack.push(getInfix[i]);
}
else if (getInfix[i] == '(')
{
opStack.push(getInfix[i]);
opStack.pop();
if (getInfix[i]=='(' && !opStack.empty())
{
opStack.push(getInfix[i]);
opStack.pop();
}
}
else if (getInfix [i]==')')
{
showInfix << opStack.top();
opStack.pop();
}
else
{
showInfix << getInfix[i];
}
}
while (!opStack.empty())
{
showInfix << opStack.top();
opStack.pop();
}
cout << "Postfix: "<<""<<showInfix.str() << endl;
cin.ignore ( numeric_limits< streamsize >:: max(),'\n');
return 0;
}
You didn't set op
const int precedence(const char x) noexcept(true) {
switch (x) {
case '(': case ')':
return 1;
case '^':
return 2;
case '*':
return 3;
case '/':
return 4;
case '+':
return 5;
case '-':
return 6;
}
return -1;
}
It returns -1 but I'll let you figure that part out.
It doesn't answer the question.
I just stopped after I saw you could be reading garbage values.
The problem comes from this line (!opStack.empty() && precedence(opStack.top() <=precedence(getInfix[i]))
You are popping the last operator you found without checking if you are in a parenthesis statement or not. You need to take parentheses characters into account before adding an operator to the output string.
Not related to your problem but some advices :
indent your code, simplifies visibility and trust me, saves you (and us) time.
Do not push and then pop for (or ) characters, this is just like ignoring them.
You are missing a ) on this line I imagine it's a copy/paste problem : while (!opStack.empty() && precedence(opStack.top() <=precedence(getInfix[i]))
You do realize you test precedence for ( and ) but you are never actually calling that method with that type of character?
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.
I attended a quiz, I gave the code but the auto-test shows that one of the eight test cases failed.
I myself tested my code many times, but all passed. I can't find where is the problem.
The question is to design a algorithm to check whether the brackets in a string match.
1) Just consider rounded brackets () and square brackets [], omit ohter chars.
2) Each pair brackets should match each other. That means ( matches ), and [ matches ].
3) Intercrossing is not allowed, such as : ([)]. There are two pairs of brackets, but they intercross each other.
To solve the problem, my method is described as follows:
Search each char in the whole input string, the index from 0 to str.size() - 1.
Use two stacks to record the opening tag (, and [, each type in one stack. When encountering one of them, push its index in the corresponding stack.
When encouterning the closing tag ) and ], we pop the corresponding stack.
Before popping, check the top of two stacks, the current stack should have the max index, otherwise that means there are unmatched opening tag with the other type, so the intercrossing can be checked this way.
My Code is Here:
#include <iostream>
#include <stack>
using namespace std;
int main()
{
string str;
cin >> str;
stack<int> s1, s2;
int result = 0;
for (int ix = 0, len = str.size(); ix < len; ix++)
{
if (str[ix] == '(')
{
s1.push(ix);
}
else if (str[ix] == '[')
{
s2.push(ix);
}
else if (str[ix] == ')')
{
if (s1.empty() || (!s2.empty() && s1.top() < s2.top()))
{
result = 1;
break;
}
s1.pop();
}
else if (str[ix] == ']')
{
if (s2.empty() || (!s1.empty() && s2.top() < s1.top()))
{
result = 1;
break;
}
s2.pop();
}
else
{
// do nothing
}
}
if (!s1.empty() || !s2.empty())
{
result = 1;
}
cout << result << endl;
}
As methoned before, this question can be solved by just on stack, so I modified my code, and here is the single stack version. [THE KEY POINT IS NOT TO ARGUE WHITCH IS BETTER, BUT WHAT'S WRONG WITH MY CODE.]
#include <iostream>
#include <stack>
using namespace std;
int main()
{
string str;
cin >> str;
stack<char> s;
const char *p = str.c_str();
int result = 0;
while (*p != '\0')
{
if (*p == '(' || *p == '[')
{
s.push(*p);
}
else if (*p == ')')
{
if (s.empty() || s.top() != '(')
{
result = 1;
break;
}
s.pop();
}
else if (*p == ']')
{
if (s.empty() || s.top() != '[')
{
result = 1;
break;
}
s.pop();
}
else
{
// do nothing
}
p++;
}
if (!s.empty())
{
result = 1;
}
cout << result << endl;
}
When using formatted input to read a std::string only the first word is read: after skipping leading whitespate a string is read until the first whitespace is encountered. As a result, the input ( ) should match but std::cin >> str would only read (. Thus, the input should probably look like this:
if (std::getline(std::cin, str)) {
// algorithm for matching parenthesis and brackets goes here
}
Using std::getline() still makes an assumption about how the input is presented, namely that it is on one line. If the algorithm should process the entire input from std::cin I would use
str.assign(std::istreambuf_iterator<char>(std::cin),
std::istreambuf_iterator<char>());
Although I think the algorithm is unnecessary complex (on stack storing the kind of parenthesis would suffice), I also think that it should work, i.e., the only problem I spotted is the way the input is obtained.