Error parsing an expression in C++ - c++

Can someone please point out the reason for the segmentation fault in my code. I am trying to convert an arithmetic expression with precedence decided by '()' into postfix form and then solve the expression.
#include<iostream>
#include<string>
#include<stack>
using namespace std;
string post(string exp)
{
cout<<"reached post";
stack<char> s2;
string new_exp="";
int length=exp.length();
for(int i=0; i<length; i++)
{
if(exp[i]=='(')
{
s2.push(exp[i]);
}
else if(exp[i]=='+'|| exp[i]=='-' || exp[i]=='*' || exp[i]=='/')
{
new_exp+=' ';
s2.push(exp[i]);
}
else if(exp[i]>='0'&& exp[i]<='9')
{
new_exp+=exp[i];
}
else if(exp[i]==')')
{
new_exp+=' ';
new_exp+=s2.top();
s2.pop();
s2.pop();
}
}
if(!s2.empty())
{
while(!s2.empty())
{
new_exp+=' ';
new_exp+=s2.top();
s2.pop();
}
}
return(new_exp);
}
int operation(char op, char op1, char op2)
{
if(op == '+') return(op1+op2);
else if(op=='-') return(op1-op2);
else if(op=='*') return(op1*op2);
else if(op=='/') return(op1/op2);
}
int solve(string expression)
{
cout<<"\nreached solve";
string postfix=post(expression);
stack<char> s;
int res;
int length=postfix.length();
for(int i=0; i<length; i++)
{
if(postfix[i]==' ')
{
continue;
}
else if(postfix[i]=='+'|| postfix[i]=='-' || postfix[i]=='*' || postfix[i]=='/')
{
char op2=s.top();
s.pop();
char op1=s.top();
s.pop();
res=operation(postfix[i],op1,op2);
s.push(res);
}
else if(postfix[i]>='0' && postfix[i]<=9)
{
int operand=0;
while(postfix[i]!=' ' || i!=length)
{
operand=(operand*10)+(postfix[i]-'0');
i++;
}
i--;
s.push(operand);
}
}
return(res);
}
int main(void)
{
string exp;
int result;
cout<<"Enter expression: ";
getline(cin,exp);
result=solve(exp);
cout<<"\nResult= "<<result;
return 0;
}
I get the following error message:
cav#cav-VirtualBox:~/src/cpp$ ./infix_postfix
Enter expression: 10+3
Segmentation fault (core dumped)

I can see at least two mistakes. First,
else if(postfix[i]>='0' && postfix[i]<=9)
You need to compare character '9', not integer 9 as you have a string here. It should be:
else if(postfix[i]>='0' && postfix[i]<='9')
^ ^
Second problem is here:
while(postfix[i]!=' ' || i!=length)
You meant and operation && here, not or ||. When it's a || it is basically true for all characters except i runs out of the length. Also i != length should be tested before postfix[i] != ' ' since when i == length postfix[i] will be out of bound. This line should be:
while(i!=length && postfix[i]!=' ')
Due to these two mistakes you are not pushing values to your stack correctly, getting erronous values at different times which is leading to segmentation fault.

Related

Infix to Postfix using stack returning error -1073741510

So, I was doing Data Structure and ALgorithm using C++ and STL, I was trying to implement Infix to postfix using stack. I am not sure what is this issue with the code? There is no compile error and when the code runs it returns -1073741510. I have rechecked the whole code, couldn't found any issues
#include<iostream>
#include<stack>
#include<string>
using namespace std;
int isOperator(char ch)
{
if(ch=='+' || ch == '-' || ch == '*' || ch == '/')
return 1;
else
return 0;
}
int precedence(char ch)
{
//for limited input only
if(ch == '*' || ch == '/')
return 3;
else if(ch=='+' || ch == '-' )
return 2;
else
return 0;
}
string infixtopostfix(string infix)
{
stack <char> st;
int i=0;
string postfix;
while(infix[i]!='\0')
{
if(!isOperator(infix[i]))
{
postfix.push_back(infix[i]);
i++;
}
else
{
if(precedence(infix[i])>precedence(st.top()))
{
st.push(infix[i]);
i++;
}
else{
postfix.push_back(st.top());
st.pop();
}
}
}
while(!st.empty())
{
postfix.push_back(st.top());
st.pop();
}
return postfix;
}
int main()
{
string infix= "a+b";
cout<<"Postfix-->"<<infixtopostfix(infix)<<endl;
return 0;
}
Your postfix string has a size of zero. This means that any attempt to access the characters of that string is an error. If you want to add characters to a string use push_back.
postfix[j] = infix[i];
should be
postfix.push_back(infix[i]);
and (twice)
postfix[j] = st.top();
should be
postfix.push_back(st.top());
and
postfix[j]='\0';
should be removed.
There is no need to nul terminate std::string. Once you have made all these changes you will also see that the j variable can be removed. A std::string knows it's own size, you don't need a separate variable to keep track. It seems that you are programming a std::string as if it's like a C string.
It seems to be a very common misunderstanding that std::string (or a std::vector) automatically grows when you subscript it. This is not true.
EDIT
You have another error here,
if(precedence(infix[i])>precedence(st.top()))
The stack maybe empty when executing this statement, leading to a crash. I'm guessing the code should read
if(st.empty() || precedence(infix[i])>precedence(st.top()))
With that change your code works for me.
Thank You everyone for the help. Here is the final answer which is running without any error.
#include<iostream>
#include<stack>
#include<string>
using namespace std;
int isOperator(char ch)
{
if(ch=='+' || ch == '-' || ch == '*' || ch == '/')
return 1;
else
return 0;
}
int precedence(char ch)
{
//for limited input only
if(ch == '*' || ch == '/')
return 3;
else if(ch=='+' || ch == '-' )
return 2;
else
return 0;
}
string infixtopostfix(string infix)
{
stack <char> st;
int i=0;
string postfix;
while(infix[i]!='\0')
{
if(!isOperator(infix[i]))
{
postfix.push_back(infix[i]);
i++;
}
else{
if(st.empty() || precedence(infix[i])>precedence(st.top()))
{
st.push(infix[i]);
i++;
}
else{
postfix.push_back(st.top());
st.pop();
}
}
}
while(!st.empty())
{
postfix.push_back(st.top());
st.pop();
}
return postfix;
}
int main()
{
string infix= "a+b";
cout<<"Postfix-->"<<infixtopostfix(infix)<<endl;
return 0;
}

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.

I have written this program for infix to postfix conversion

#include<iostream>
#include<stdio.h>
#define MAX 20
using namespace std;
char stk[MAX];
int top=-1;
void push(char c)
{
if(top==MAX-1)
cout<<"Overflow";
else
{
stk[++top]=c;
}
}
char pop()
{
if(top==-1)
{
return '\0';
}
else
return stk[top--];
}
int priority(char ch)
{
if(ch=='(')
return 1;
if(ch=='+'||ch=='-')
return 2;
if(ch=='*'||ch=='/')
return 3;
if(ch=='^')
return 4;
}
int main()
{
char exp[35],*t,x;
cout<<"Enter expression: ";
fgets(exp,35,stdin);
t=exp;
while(*t)
{
if(isalnum(*t))
cout<<*t;
else if(*t=='(')
push(*t);
else if(*t==')')
{
while((x=pop())!='(')
cout<<x;
}
else
{
if(priority(stk[top])>=priority(*t))
cout<<pop();
push(*t);
}
t++;
}
while(top!=-1)
cout<<pop();
return 0;
}
The output for input:
a+b-(c+d/e)
is
ab+cde/+
-
I don't understand why - is on a newline.
I have just started learning c++ and I am trying to implement some programs I did in c using c++. The same code in c works fine. I think there are some holes in my basic c++ knowledge and I would like to fill them up.
std::fgets does not discard the newline in the input stream like getline would. That means exp contains "a+b-(c+d/e)\n" and not "a+b-(c+d/e)". You either need to remove the newline from exp, switch to cin.getline(), or stop your processing loop when it hits the newline.
Try to change fgets to std::cin. And use std::string instead of char*:
#include <iostream>
#include <string>
int main()
{
string exp;
cout << "Enter expression: ";
std::cin >> exp;
auto t = exp.data();
char x;
for(auto &ch: exp)
{
if(isalnum(ch))
cout << ch;
else if(ch == '(')
push(ch);
else if(ch == ')')
{
while((x = pop()) != '(')
cout << x;
}
else
{
if(priority(stk[top]) >= priority(ch))
cout << pop();
push(ch);
}
}
while(top != -1)
cout << pop();
return 0;
}
In addition to the processing of '\n' as mentioned by NathanOliver, your function priority() doesn't return a value when the user entered any other character not checked in the if statements, so the behavior might be undefined.

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.

a code for infix to postfix conversion

I have written a code for infix to postfix conversion,This piece of code is not encountering any kind of compile time error but after taking the input infix expression it is giving some runtime errors which i am unable to understand these errors are something related to string as the message says.
#include<iostream>
#include<string>
#define N 50
using namespace std;
class stack
{
private:
char arr[N];
int tos;
public:
void push(char p)
{
if (tos != N)
arr[++tos] = p;
else
cout << "stack full";
}
char pop()
{
if (tos == -1)
cout << "stack Empty";
else
return (arr[tos--]);
}
bool isempty()
{
if (tos == -1)
return (true);
else
return (false);
}
char top()
{
return arr[tos];
}
stack()
{
tos = -1;
}
};
int pres(char sym)
{
if (sym == '^')
return 3;
else if (sym == '*' || '/')
return 2;
else if (sym == '+' || '-')
return 1;
else if (sym == '(')
return 0;
}
bool isoperator(char op)
{
if (op=='+' || op=='-' || op=='/' || op=='*' || op=='^')
return true;
else
return false;
}
int main()
{
string infix, postfix;
stack s;
int in=0;
int post=0;
cout << "Enter an infix expression: ";
cin >> infix;
s.push('(');
infix.append(")");
char temp;
while (!(s.isempty()))
{
if (isdigit(infix[in]))
postfix[post++] = infix[in];
else if (infix[in] == '(')
s.push(infix[in]);
else if (infix[in] == ')')
{
while (1)
{
temp = s.pop();
if (temp == '(')
break;
else
postfix[post] = infix[in];
}
}
else if (isoperator(infix[in]))
{
while (pres(s.top()) >= pres(infix[in]))
postfix[post++] = s.pop();
s.push(infix[in]);
}
in++;
}
cout << "Postfix expression is: " << postfix;
system("pause");
}
I m unable to get what's wrong with it. Can any one help??
I found the following logical errors in your code:
the result string postfix is empty at the beginning, but you're writing to single character positions using postfix[post++]=. This is not valid and is propably causing the "string related" errors. You should only use postfix.push_back() to add characters to the output string.
In the first inner while loop (while(1)) the last statement should read
postfix.push_back(temp);
since you want to append the operators from the stack to the output.
Your code falsely accept input with unbalanced additional closing parents like "1+4)". Personally, I would put the input position as outer loop condition and verify that the stack is empty after the loop (and check for empty stack in the pop() function) for detecting input errors.
The biggest error is in his pres() function, it should be:
else if (sym == '*' || sym == '/')
else if (sym == '+' || sym == '-')
I have noticed some of the errors mentioned by MartinStettner.