I made a function infixToPostfix() which converts an infix expression to a postfix expression. But my program generates no output on running. Please point out the errors in my program.
Code:
#include <iostream>
#include <cstring>
#include <stack>
#include <cstdlib>
using namespace std;
int isOperator(char x)
{
return (x == '-' || x == '+' || x == '/' || x == '*');
}
int precedenceOfOperators(char x)
{
if (x == '+' || x == '-')
{
return 1;
}
else if (x == '/' || x == '*')
{
return 2;
}
return 0;
}
char *infixToPostfix(char infix[])
{
int i = 0, j = 0;
stack<char> lobby;
char *postfix = (char *)malloc((strlen(infix + 1)) * sizeof(char));
while (infix[i] != '\0')
{
if (!isOperator(infix[i]))
{
postfix[j] = infix[i];
i++;
j++;
}
else
{
if (!lobby.empty())
{
if (precedenceOfOperators(infix[i]) > precedenceOfOperators(lobby.top()))
{
lobby.push(infix[i]);
}
else
{
postfix[j] = lobby.top();
lobby.pop();
j++;
}
}
else if (lobby.empty())
{
lobby.push(infix[i]);
}
}
}
while (!lobby.empty())
{
postfix[j] = lobby.top();
lobby.pop();
j++;
}
return postfix;
}
Implementation:
int main()
{
char infix[] = {'a', '-', 'b', '+', 'c', '*', 'd'};
char *postfix = infixToPostfix(infix);
for (int j = 0; postfix[j] != '\0'; j++)
{
cout << postfix[j];
}
return 0;
}
Logic:
I created a character pointer variable that will hold our postfix expression. Now, we iterate over our infix expression. If we receive an operand, we concatenate it to the postfix variable. Else if we encounter an operator, we proceed with the following steps:
Keep in account the operator and its relative precedence ('/' and '*' have more precedence than '+' and '-').
If either the stack is empty or its topmost operator has lower relative precedence, push this operator-precedence pair inside the stack 'lobby'.
Else, keep popping operators from the stack 'lobby' and concatenate them to the postfix expression until the topmost operator becomes weaker in precedence relative to the current operator.
If you reach the EOE, pop every element from the stack 'lobby', if there is any, and concatenate them as well to the postfix expression.
Your code is exceeding the time limit because it is stuck in the infinite loop. You have not updated the i variable- which is the index of the infix array in the else part of the loop i.e when infix[i] is an operator. i.e. in this part of the code
else
{
if (!lobby.empty())
{
if (precedenceOfOperators(infix[i]) > precedenceOfOperators(lobby.top()))
{
lobby.push(infix[i]);
}
else
{
postfix[j] = lobby.top();
lobby.pop();
j++;
}
}
else if (lobby.empty())
{
lobby.push(infix[i]);
}
}
Here is the updated code which is giving perfect output. ( I have made some minor changes as per my convenience, you can keep the code the same and add the i++ in the else part)
#include <iostream>
#include <cstring>
#include <stack>
#include <cstdlib>
using namespace std;
int isOperator(char x)
{
return (x == '-' || x == '+' || x == '/' || x == '*');
}
int precedenceOfOperators(char x)
{
if (x == '+' || x == '-')
{
return 1;
}
else if (x == '/' || x == '*')
{
return 2;
}
return 0;
}
string infixToPostfix(char infix[])
{
int i = 0, j = 0;
if(sizeof(infix)==0)
{
return "";
}
int n=sizeof(infix)/sizeof(infix[0]);
stack<char> lobby;
string postfix = "";
while (i < n)
{
if (!isOperator(infix[i]))
{ postfix=postfix+infix[i];
i++;
j++;
}
else
{
if (!lobby.empty())
{
if (precedenceOfOperators(infix[i]) > precedenceOfOperators(lobby.top()))
{
lobby.push(infix[i]);
}
else
{
postfix = postfix+lobby.top();
lobby.pop();
j++;
}
}
else if (lobby.empty())
{
lobby.push(infix[i]);
}
i++;
}
}
while (lobby.empty()==false)
{
postfix = postfix+lobby.top();
lobby.pop();
j++;
}
return postfix;
}
int main()
{
char infix[] = {'a', '-', 'b', '+', 'c', '*', 'd'};
string postfix = infixToPostfix(infix);
for (int j = 0; j < postfix.size() ; j++)
{
cout << postfix[j];
}
return 0;
}
After going through my code again I found some other logical errors too. I have found a better way and have restructured the else part of while loop of function infixToPostfix().
And rather than taking the Infix expression as a character array, I have taken it as a string and similarly Postfix expression is also considered as a string.
Updated infixToPostfix():
string infixToPostfix(string infix)
{
int i = 0;
stack<char> lobby;
string postfix;
if (infix.size() == 0)
{
return "";
}
while (infix[i] != '\0')
{
if (!isOperator(infix[i]))
{
postfix = postfix + infix[i];
i++;
}
else
{
while (!lobby.empty() && precedenceOperator(infix[i]) <= precedenceOperator(lobby.top()))
{
postfix += lobby.top();
lobby.pop();
}
lobby.push(infix[i]);
i++;
}
}
while (!lobby.empty())
{
postfix = postfix + lobby.top();
lobby.pop();
}
return postfix;
}
And as mentioned in other answers, i variable should also be updated in the else part of the while loop.
Related
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>
using namespace std;
class Stack {
public:
string stack[100][1];
int size;
Stack() { size = 0; }
~Stack() {};
void push(string data) {
stack[size][0] = data;
size += 1;
}
bool empty() {
if (size == 0)
{
return true;
}
else
{
return false;
}
}
string pop() {
size -= 1;
return stack[size][0];
}
string top() {
if (empty())
cout << "Stack is empty";
return stack[size - 1][0];
}
};
int pre(char op)
{
switch (op)
{
case '(': case ')': return 0;
case '+': case '-': return 1;
case '*': case '/': return 2;
}
return -1;
}
vector<string> infix_to_postfix(const vector<string>& expr) {
vector<string> postfix;
string op;
Stack st;
for (int i = 0; i < expr.size(); i++) {
if (expr[i][0] == '+' || expr[i][0] == '-' || expr[i][0] == '*' || expr[i][0] == '/') {
while (!st.empty()) {
op = (st.top()[0]);
if (pre(expr[i][0]) <= pre(op[0]))
postfix.push_back(st.pop());
else break;
}
postfix.push_back(expr[i]);
}
else if (expr[i][0] == '(') {
st.push(expr[i]);
}
else if (expr[i][0] == ')') {
while (!st.empty()) {
op = st.pop();
if (op[0] == '(') break;
else {
postfix.push_back(op);
}
}
}
else {
postfix.push_back(expr[i]);
}
}
return postfix;
}
int main() {
auto expr = infix_to_postfix({ "(", "2", "+", "3", ")", "*", "7" });
for (auto& elem : expr)
{
std::cout << elem << ", ";
}
std::cout << "\n";
return 0;
}
This program is supposed to convert from infix to postfix but it is not producing the correct output. I'm expecting the output to be:
2, 3, +, 7, *,
but the output is
2, +, 3, *, 7,
You have two issues.
When handling an operator, after popping the lower precedence operators you need to push the new operator onto the stack rather than adding it to the result:
if (expr[i][0] == '+' || expr[i][0] == '-' || expr[i][0] == '*' || expr[i][0] == '/') {
while (!st.empty()) {
op = (st.top()[0]);
if (pre(expr[i][0]) <= pre(op[0]))
postfix.push_back(st.pop());
else break;
}
st.push(expr[i]);
}
At the end of the function you need to pop any remaining operators off the stack:
while (!st.empty())
{
postfix.push_back(st.pop());
}
return postfix;
I have implemented Shunting yard algorithm using stack in c++.
Well it is working quite well on inputs from SPOJ example inputs but when I input:
1
(((a+b) * (c+r)^(t+b)-n)^(c-(d * e))-b)+(c+(e-(d^r)))
I get a runtime error.
Note: I only get a runtime error when I call infixToPostfix() and use the above input and not when I comment it out.
Submission to SPOJ and running on ideone(with input above) results in a runtime error.
I really can't understand this behaviour of my program, so any help is welcomed.
I have tried some random inputs and it seems to work fine on them.
Even though they had spaces around operators.
#include<iostream>
#include<vector>
#include<math.h>
#include<stack>
#include<strings.h>
using namespace std;
void infixToPostfix(string st);
int pr(char s);
int main() {
int t;
scanf("%d",&t);
cin.ignore();
string st; // input string
while(t--)
{
getline(cin,st);
cin.sync();
cout<<st<<endl;
infixToPostfix(st);
}
return 0;
}
int pr(char s) // to check precedence
{
if(s == '^')
{
return 4;
}
else if(s == '*')
{
return 3;
}
else if(s == '/')
{
return 3;
}
else if(s == '+')
{
return 2;
}
else if(s == '-')
{
return 2;
}
else {
return 0;
}
}
void infixToPostfix(string st)
{
stack<char>op; //stack to hold operators and bracket
st += 'n';
int l = st.size();
op.push('0');
string fst; //final string
for(int x = 0;x<l;x++)
{
if(st[x] == '(')
{
op.push(st[x]);
}
else if(st[x] == ')')
{
while(op.top() != '(' && !op.empty())
{
fst +=op.top();
op.pop();
}
op.pop();
}
else if(st[x] == '+' || st[x] == '-' || st[x] == '*' ||st[x] == '/' ||st[x] == '^')
{
if(pr(st[x]) <= pr(op.top()))
{
fst += op.top();
op.pop();
op.push(st[x]);
}
else{
op.push(st[x]);
}
}
else if(st[x] == 'n'){
while(op.size() != 0)
{
if(op.top() != '0')
{fst += op.top();}
op.pop();
}
}
else if((st[x] >= 'a' || st[x] <= 'z' )&& st[x] != ' ')
{
fst += st[x];
}
}
printf("%s\n",fst.c_str());
}
So I am working on some homework for my uni and need to convert a string to a float. For whatever reason g++ is complaining that the 'stof' function doesn't exist. Although I have included the required header. Here is my code, the error is on the line that says
holder = stof(x.substr(0, end_of_num));
#include <iostream>
#include <string>
#include <list>
using namespace std;
float process_func(string x);
bool isPartOfNum(char x);
int main() {
string x;
while (true) {
cout << "input a string" << endl;
getline(cin, x);
cout << process_func(x);
}
return 0;
}
float process_func(string x) {
int end_of_num =0;// used to find last index from num
int negMult = 1; //used to multiply value at end if there was a negative
bool onNum = false; //used to
list <float> numList;
list <char> operList;
if ((x.at(0) < 48 || x.at(0) > 57) && x.at(0) != '-') //check if start of string doesnt have a number or negative symbol
return -1;
if (x.at(0) != '-')
negMult = -1;
float holder;// temp holder for floats
int i = 0;
while (i<x.length()) {
if (isPartOfNum(x.at(i))) {
end_of_num++;
onNum = true;
}
else if (onNum) {
holder = stof(x.substr(0, end_of_num));
numList.push_back(holder); //adds num as float to list
x.erase(0, end_of_num + 1); //+1 removes the space after the number before the operator
end_of_num = 0;
onNum = false;
}
if (x.at(i) == '+' || x.at(i) == '-' || x.at(i) == '*' || x.at(i) == '/') {
operList.push_back(x.at(i));
}
} //at this point both lists should be full of all needed pieces of info
int answer = 0;
int temp;
bool firstOper=true; // used to hold first operation
while (numList.size() >=2) { //requires at least 2 entries for last operation
while (!operList.empty()) {
temp = numList.front();
numList.pop_front();
if (operList.front() == '+') {
if (firstOper) {
answer = temp + numList.front();
numList.pop_front();
firstOper = false;
}
else {
answer += temp;
}
}
else if (operList.front() == '-') {
if (firstOper) {
answer = temp - numList.front();
numList.pop_front();
firstOper = false;
}
else {
answer -= temp;
}
}
else if (operList.front() == '*') {
if (firstOper) {
answer = temp * numList.front();
numList.pop_front();
firstOper = false;
}
else {
answer *= temp;
}
}
else if (operList.front() == '/') {
if (firstOper) {
answer = temp / numList.front();
numList.pop_front();
firstOper = false;
}
else {
answer /= temp;
}
}
operList.pop_front();
}
}
return answer;
}
bool isPartOfNum(char x) {
if ((x >= 48 && x <= 57) || (x == '-' || x == '.'))
return true;
return false;
}
Solved by compiling using c++ 11
I've got a few different functions that on their own work fine. Now I am trying to put them together into one file. My debugger is throwing segmentation faults in the infixToPostfix function.
When I watch the ns variable, it does not show anything getting assigned to it, but it prints out the postfix expression when I actually run the code. When ns passes into PostfixEvaulation, it runs to the top member function of TemplateStack and crashes with:
terminate called after throwing an instance of "std::string"
This only happens when I pass a string with an operator. When I pass a string of just numbers, everything runs fine,
but it still does not seem to call PostfixEvaluation.
#include <iostream>
#include <sstream>
#include <string>
#include <typeinfo>
using namespace std;
//Class Template Stack declaration
template <class T>
class TemplateStack {
public:
typedef T type;
TemplateStack()
{
max_size_ = 50;
TopOfStack = 0;
data_ = new T[max_size_];
} //Default Constructor taking no parameters
void push(T element)
{
if (TopOfStack == max_size_)
throw string("Stack's underlying storage is overflow");
TopOfStack++;
data_[TopOfStack] = element;
}
void pop() {
if (TopOfStack == -1)
throw string("Stack is empty");
TopOfStack--;
}
T top() {
if (TopOfStack == -1)
throw string("Stack is empty");
return data_[TopOfStack];
}
private:
int TopOfStack; //Generic data type for the top element of stack
size_t max_size_;
T* data_;
};
//Function to Evauluate the Postfix notation expresion
int PostfixEvaulation(string input){
//string input;
int operand1, operand2, result,number;
TemplateStack<char>operation;
stringstream temp;
int i=0;
while (i < input.length())
{
if (isdigit(input[i]))
{
operation.push(input[i]);
}
else
{
operand2 = operation.top();
temp << operation.top();
operation.pop();
operand1 = operation.top();
temp << operation.top();
operation.pop();
switch(operand1,operand2)
{
case '+': result=operand1 + operand2;
break;
case '-': result=operand1 - operand2;
break;
case '*': result=operand1 * operand2;
break;
case '/': result=operand1 / operand2;
break;
}
operation.push(result);
}
i++;
}
cout << "The result is: "<<temp.str()<<endl;
//cin.ignore(numeric_limits<streamsize>::max(), '\n');
return 0;
}
//Function to return precedence of operators
int prec(char c)
{
if(c == '^')
return 3;
else if(c == '*' || c == '/')
return 2;
else if(c == '+' || c == '-')
return 1;
else
return -1;
}
//Function: Convert Infix to Postfix
void infixToPostfix(string s)
{
TemplateStack<char> st;
st.push('N');
int l = s.length();
string ns;
for (int i = 0; i < l; i++) {
// If the scanned character is an operand, add it to output string.
if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z')) {
ns += s[i];
}
// If the scanned character is an ‘(‘, push it to the stack.
else if (s[i] == '(') {
st.push('(');
}
// If the scanned character is an ‘)’, pop and to output string from the stack
// until an ‘(‘ is encountered.
else if (s[i] == ')') {
while (st.top() != 'N' && st.top() != '(') {
char c = st.top();
st.pop();
ns += c;
}
if (st.top() == '(') {
char c = st.top();
st.pop();
}
}
//If an operator is scanned
else {
while (st.top() != 'N' && prec(s[i]) <= prec(st.top())) {
char c = st.top();
st.pop();
ns += c;
}
st.push(s[i]);
}
}
//Pop all the remaining elements from the stack
while (st.top() != 'N') {
char c = st.top();
st.pop();
ns += c;
}
cout << "Here is the ns variable: "<< ns << endl;
PostfixEvaulation(ns);//Call the PostFixEvaluationFunction with the ns (postfix notation) variab
}
//Function: User inputs Expression
void GetInput(){
string input;
cout << "Enter Infix Expression: ";
getline(cin, input);
infixToPostfix(input);
}
int main()
{
GetInput();
}
I am getting a segmentation fault when trying to convert an infix expression into prefix order. I have a postfix using the same logic that works fine the issue seems to be where i try to read the infix expression in reverse but I am not exactly sure why it is faulting. Any help would greatly appreciated Here is the relevant code:
int ParseTree::prefix(string infix)
{
vector<string> exp;
stringstream ss(infix);
string tok;
while(getline(ss,tok,' '))
{
exp.push_back(tok);
}
vector<string> prefix;
stack<string> s;
for(unsigned int i = exp.size() - 1; i >= 0 ; i--)
{
if(parseTry(exp[i]))
{
prefix.push_back(exp[i]);
}
if(exp[i] == "(")
{
s.push(exp[i]);
}
if(exp[i] == ")")
{
while(!s.empty() && s.top() != "(")
{
prefix.push_back(s.top());
s.pop();
}
s.pop();
}
if(isOperator(exp[i]) == true)
{
while(!s.empty() && priority(s.top()) >= priority(exp[i]))
{
prefix.push_back(s.top());
s.pop();
}
s.push(exp[i]);
}
}
while(!s.empty())
{
prefix.push_back(s.top());
s.pop();
}
for(unsigned int i = 0; i < prefix.size(); i++)
{
cout << prefix[i] << " ";
}
return 0;
}
int ParseTree::priority(const string &s)
{
if(s == "*" || s == "/")
{
return 2;
}
if(s == "+" || s == "-")
{
return 1;
}
else
{
return 0;
}
}
bool ParseTree::parseTry(const string &s)
{
bool number = false;
for(unsigned int i = 0; i < s.size(); i++)
{
if(!isdigit(s[i]))
{
number = false;
}
else
{
number = true;
}
}
return number;
}
bool ParseTree::isOperator(const string &s)
{
return (s == "+" || s == "-" || s == "*" || s == "/");
}