Using Stacks in C++ to Evaluate the Postfix Expression - c++

Ok, I already have it in postfix notation and I am sending over a string variable that will have the postfix notation as something such as: 5 15 2 *+
Here is my code:
int evaluatePostFix(string postfix_expression){
//Create a new stack
stack<int> theStack;
//Loops while the postfix expression string still contains values
while(postfix_expression.length()>=1){
//Loops on a number an whitespace
while(isdigit(postfix_expression.at(0)) || isspace(postfix_expression.at(0))){
//Holds a number that is above two digits to be added to the stack
string completeNum;
if(isdigit(postfix_expression.at(0))){
//Add the digit so it can become a full number if needed
completeNum+=postfix_expression.at(1);
}
else {
//Holds the integer version of completeNum
int intNum;
//Make completeNum an int
intNum=atoi(completeNum.c_str());
//push the number onto the stack
theStack.push(intNum);
}
//Check to see if it can be shortened
if(postfix_expression.length()>=1){
//Shorten the postfix expression
postfix_expression=postfix_expression.substr(1);
}
}
//An Operator has been found
while(isOperator(postfix_expression.at(0))){
int num1, num2;
char op;
//Grabs from the top of the stack
num1=theStack.top();
//Pops the value from the top of the stack - kinda stupid how it can return the value too
theStack.pop();
//Grabs the value from the top of the stack
num2=theStack.top();
//Pops the value from the top of the stack
theStack.pop();
//Grab the operation
op=postfix_expression.at(0);
//Shorten the postfix_expression
postfix_expression=postfix_expression.substr(1);
//Push result onto the stack
theStack.push(Calculate(num1,num2, op));
}
}
return theStack.top();
}
The error I get is "Deque iterator not deferencable"
Any help that I can get on this error would be much appreciated.
btw I haven't used C++ in a couple of years so I'm a bit rusty.

It would be easier if you told us which line was causing the error by stepping through with a debugger. However, I think I may have spotted the error.
In this block of code
if(isdigit(postfix_expression.at(0))){
//Add the digit so it can become a full number if needed
completeNum+=postfix_expression.at(1);
}
You ask for the postfix_expression.at(1) without ever checking if that element exists. Since there is no check, you might be accessing bad memory locations.

Related

Converting infix to postfix using c++

I'm trying to convert infix to postfix. I don't think my code is wrong but apparently it is because it doesn't work. I don't know what to change to make my code work properly.
(It worked for a bit before and now it doesn't)
I followed this code from geeksforgeeks: https://www.geeksforgeeks.org/stack-set-2-infix-to-postfix/ but I changed some of it because the code from the website was also wrong.
Sorry if my explanation is a bit unclear. Here's my code:
#include <bits/stdc++.h>
using namespace std;
int checks(char c)
{
if (c=='^')
{
return 1;
}
else if (c=='+' || c=='-')
{
return 2;
}
else if (c=='*' || c=='/')
{
return 3;
} else
{
return -1;
}
}
int main()
{
stack <char> stack;
string result, input;
cout<<"Enter your equation: ";
cin>> input;
for (int i=0; i<input.length(); i+=1)
{
if (input[i]=='(')
{
stack.push(input[i]);
} else if (isalnum(input[i]))
{
result+=input[i];
} else if (input[i]==')')
{
while(!stack.empty() && stack.top() != '(')
{
char c = stack.top();
stack.pop();
result += c;
}
if(stack.top() == '(')
{
char c = stack.top();
stack.pop();
}
} else
{
if (checks(stack.top()) >= checks(input[i]))
{
result+=stack.top();
stack.pop();
} else
{
stack.push(input[i]);
}
}
}
while(!stack.empty())
{
if (stack.top()=='(' || stack.top()==')')
{
stack.pop();
} else
{
result+=stack.top();
stack.pop();
}
}
cout<<"Result is: ";
cout<<result<<endl;
return 0;
}
Are your infix expressions using standard mathematical precedence? If so this will change things significantly compared to simple left to right evaluation.
You need to split your program into two phases. In the first phase you will parse the expression and build up the stack. In the second you will iterate over the stack and evaluate the result.
As I said, the parsing will be determined by the precedence. If you are using standard precedence then the usual approach (which you can read in Stroustrup's "The C++ Programming Language") is to use recursive descent. You would then have different precedences for parens, terms, factors, unary operators and literals. Use an enum for these, not magic numbers like 1, 2, 3.
You may skip step to actually create a tree structure , but have to keep in mind that infix notation is representable by tree while Polish notation is representable by stack. In (a+b)*(c+d) the * is topmost node, next level are two + and a, b,c,d. it's a symmetric tree because all operations commutative. But ((a+b)*(c+d))/3 is asymmetric, topmost node / is not commutative. Similar problem arise with -, because it's not commutative either.
E.g. possible option at each step can be (not a strict algorithm, but illustration how one should act, irt requires defense against malformed syntax)
Token is an "id".It's current level of tree node, scan further right
Token is a commutative operation. It's upper level of node. Next token would be a node of same level
Token is a non-commutative operation, / or -. It's upper level of node. Next token relates to node between current one and operation.
* and / have precedence above + and -, so they are nodes of lower level. E.g. a+b*c, First our tree was +: [a,b], then it is +:[a,*:[b,c]].
Token is (. Scan string and count all braces until you find matching ). E.g. each ( increases counter, each ) decreases. You found match if counter is 0. You have syntax error at hand if you get positive or negative while reaching terminal character..
Everything inside of () is a node of lower level. Scan it after finishing all upper levels.
To actually scan string, a state machine running in loop is required, the sign of finishing would be that there will be no tokens left to process. Can be recursive or not.
If you avoid creating tree, you have to go down and up along tokens in string itself, finding topmost node, push it to stack, then right and left nodes (in that order), push to stack, etc. When you pop stack, last-in first-out, operations would appear in proper order.
Paul Floyd is right to remind of that operator precedence can be used to sort order nodes or tokens, albeit doing it in std::stack is not possible because it got only push and pop operations and no reordering is possible, so you have to store that separately or scan and rescan string to push appropriate elements in.
(Note, than when you use some RPN calculator like on of those TI ones the stack of operations acts as a LILO stack, while when convert from syntax tree to RPN, it's LIFO)

Stack with char array.How to execute "+" and "*" operations?

I need to sum up or multiplie(it depends on which operation i push in array) first two numbers in stack. If I push operation + and my first two numbers are one and two then my stack value where I pushed + must be 3 , but in my result i get some symbol.
#include<iostream>
using namespace std;
#define MAX 10
int sp=-1;
char stack[MAX];
void push(){
if(sp==MAX-1){
cout<<"Error: stack overflow"<<endl;
return;
}
else{
char x;
cout<<"Insert value in stack: ";
cin>>x;
if(x=='*'){
if(sp>=1){
stack[++sp]=stack[1]*stack[0];
return;
}
else {
stack[++sp]=x;
return;
}
}
else if(x=='+'){
if(sp>=1){
stack[++sp]=stack[0]+stack[1];
return;
}
else {
stack[++sp]=x;
return;
}
}
else stack[++sp]=x;
}
}
void pop(){
if(sp==-1){
cout<<"Error: Stack empty";
return;
}
else{
cout<<stack[sp]<<endl;
sp--;
}
}
void top(){
if(sp==-1){
cout<<"Error: Stack empty";
return;
}
else{
cout<<stack[sp]<<endl;
}
}
void isEmpty(){
if(sp==-1){
cout<<"Stack is empty"<<endl;
return;
}
else{
cout<<"Stack is not empty"<<endl;
}
}
int main(){
for(int i=0;i<8;i++){
push();
}
top();
return 0;
}
Original stack:
3 4 3 + 1 2 * *
Stack that I need to get:
3 4 3 7 1 2 12 12
Stack that I get:
3 4 3 \ 1 2 _ _ (let's say something like that)
So you wanted to implement some postfix calculator. Very good that you noticed that a stack is needed.
For calculators you normally parse the input, store some results on a stack and then operate on the stack elements.
In contrast to what timo said, a parse stack can never be implemented with a std::stack because several top stack elements must be matched against the production in the grammar. For that reason a std::vector is the ideal container.
Now to the problem in the program. OP tries to store integer values and operators like "+" and "*" and results of calculations in the same datatype char. That cannot work. char stores characters like '+' or '*' or '1' but not 1. Internally a character is also encoded as a number (for example using ASCII) and a '1' would be equal to 49. And, if you look at results you cannot store '12' (for all the pros. Yes of course I know) in a char. 12 is a number, not a character.
And if you mix these types and do calculations with that then you get wrong results.
The solutions is to use Tokens and implement them as a std::variant. The variant can have a char an an int. Then your parse stack should be a std:::vector of Token.
This the right approach.
Additionally. In all standard recursive descent parsers you do not operate always on elements 0 and 1. You would replace the used values with the newly calculated one.
There is always the same approach
Read next Token and shift it on a stack
Match the top elements of the stack against a production
Reduce. Replace used elements with result
Some example of a different parser: See here.
This is somehow complicated. You may want to read about formal languages and parser.

What is wrong with the following code to identify balanced parentheses using stack?

Problem:
Given a sequence consisting of parentheses, determine whether the expression is balanced. A sequence of parentheses is balanced if every open parentheses can be paired uniquely with a closed parentheses that occurs after the former. Also, the interval between them must be balanced. You will be given three types of parentheses: (, {, and [.
{[()]} - This is a balanced parentheses.
{[(])} - This is not a balanced parentheses.
Input Format:
*The first line of input contains the number of test cases.
*Each test case consists of a single line with the sequence of parentheses.
stack <char> stk;
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int n;
cin>>n;
for(int i=0;i<n;i++)
{
string s;
cin>>s;cout<<s;
int j=0;
while(j!=s.length())
{
if(stk.size()==0&&(s[j]==')'||s[j]==']'||s[j]=='}'))
{stk.push('z');}
if(s[j]=='('||s[j]=='['||s[j]=='{')
stk.push(s[j]);
if(stk.top()=='('&&s[j]==')')
stk.pop();
if(stk.top()=='['&&s[j]==']')
stk.pop();
if(stk.top()=='{'&&s[j]=='}')
stk.pop();
j++;
}
if(stk.size()==0)
cout<<"YES"<<endl;
else
{
cout<<"NO"<<endl;
while(stk.size()!=0)
stk.pop();
}
}
return 0;
}
It is a code for checking for balanced parentheses. Its working fine with strings starting with a '{' but fails with strings like "[]"
You must be getting a Segmentation Fault.
Suppose,
s = "[]";
After 1st iteration your stack contains only "[".
During 2nd iteration,
if(stk.top()=='['&&s[j]==']')
stk.pop();
above code makes your stack empty.
In next line you are calling
stk.top() // But your stack is empty
in
if(stk.top()=='{'&&s[j]=='}')
stk.pop();
This is the problem. So before calling
stk.top();
make sure that your stack is not empty.
Check this tutorial on balanced parentheses.

Recursive String Transformations

EDIT: I've made the main change of using iterators to keep track of successive positions in the bit and character strings and pass the latter by const ref. Now, when I copy the sample inputs onto themselves multiple times to test the clock, everything finishes within 10 seconds for really long bit and character strings and even up to 50 lines of sample input. But, still when I submit, CodeEval says the process was aborted after 10 seconds. As I mention, they don't share their input so now that "extensions" of the sample input work, I'm not sure how to proceed. Any thoughts on an additional improvement to increase my recursive performance would be greatly appreciated.
NOTE: Memoization was a good suggestion but I could not figure out how to implement it in this case since I'm not sure how to store the bit-to-char correlation in a static look-up table. The only thing I thought of was to convert the bit values to their corresponding integer but that risks integer overflow for long bit strings and seems like it would take too long to compute. Further suggestions for memoization here would be greatly appreciated as well.
This is actually one of the moderate CodeEval challenges. They don't share the sample input or output for moderate challenges but the output "fail error" simply says "aborted after 10 seconds," so my code is getting hung up somewhere.
The assignment is simple enough. You take a filepath as the single command-line argument. Each line of the file will contain a sequence of 0s and 1s and a sequence of As and Bs, separated by a white space. You are to determine whether the binary sequence can be transformed into the letter sequence according to the following two rules:
1) Each 0 can be converted to any non-empty sequence of As (e.g, 'A', 'AA', 'AAA', etc.)
2) Each 1 can be converted to any non-empty sequences of As OR Bs (e.g., 'A', 'AA', etc., or 'B', 'BB', etc) (but not a mixture of the letters)
The constraints are to process up to 50 lines from the file and that the length of the binary sequence is in [1,150] and that of the letter sequence is in [1,1000].
The most obvious starting algorithm is to do this recursively. What I came up with was for each bit, collapse the entire next allowed group of characters first, test the shortened bit and character strings. If it fails, add back one character from the killed character group at a time and call again.
Here is my complete code. I removed cmd-line argument error checking for brevity.
#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
using namespace std;
//typedefs
typedef string::const_iterator str_it;
//declarations
//use const ref and iterators to save time on copying and erasing
bool TransformLine(const string & bits, str_it bits_front, const string & chars, str_it chars_front);
int main(int argc, char* argv[])
{
//check there are at least two command line arguments: binary executable and file name
//ignore additional arguments
if(argc < 2)
{
cout << "Invalid command line argument. No input file name provided." << "\n"
<< "Goodybe...";
return -1;
}
//create input stream and open file
ifstream in;
in.open(argv[1], ios::in);
while(!in.is_open())
{
char* name;
cout << "Invalid file name. Please enter file name: ";
cin >> name;
in.open(name, ios::in);
}
//variables
string line_bits, line_chars;
//reserve space up to constraints to reduce resizing time later
line_bits.reserve(150);
line_chars.reserve(1000);
int line = 0;
//loop over lines (<=50 by constraint, ignore the rest)
while((in >> line_bits >> line_chars) && (line < 50))
{
line++;
//impose bit and char constraints
if(line_bits.length() > 150 ||
line_chars.length() > 1000)
continue; //skip this line
(TransformLine(line_bits, line_bits.begin(), line_chars, line_chars.begin()) == true) ? (cout << "Yes\n") : (cout << "No\n");
}
//close file
in.close();
return 0;
}
bool TransformLine(const string & bits, str_it bits_front, const string & chars, str_it chars_front)
{
//using iterators so store current length as local const
//can make these const because they're not altered here
int bits_length = distance(bits_front, bits.end());
int chars_length = distance(chars_front, chars.end());
//check success rule
if(bits_length == 0 && chars_length == 0)
return true;
//Check fail rules:
//1. next bit is 0 but next char is B
//2. bits length is zero (but char is not, by previous if)
//3. char length is zero (but bits length is not, by previous if)
if((*bits_front == '0' && *chars_front == 'B') ||
bits_length == 0 ||
chars_length == 0)
return false;
//we now know that chars_length != 0 => chars_front != chars.end()
//kill a bit and then call recursively with each possible reduction of front char group
bits_length = distance(++bits_front, bits.end());
//current char group tracker
const char curr_char_type = *chars_front; //use const so compiler can optimize
int curr_pos = distance(chars.begin(), chars_front); //position of current front in char string
//since chars are 0-indexed, the following is also length of current char group
//start searching from curr_pos and length is relative to curr_pos so subtract it!!!
int curr_group_length = chars.find_first_not_of(curr_char_type, curr_pos)-curr_pos;
//make sure this isn't the last group!
if(curr_group_length < 0 || curr_group_length > chars_length)
curr_group_length = chars_length; //distance to end is precisely distance(chars_front, chars.end()) = chars_length
//kill the curr_char_group
//if curr_group_length = char_length then this will make chars_front = chars.end()
//and this will mean that chars_length will be 0 on next recurssive call.
chars_front += curr_group_length;
curr_pos = distance(chars.begin(), chars_front);
//call recursively, adding back a char from the current group until 1 less than starting point
int added_back = 0;
while(added_back < curr_group_length)
{
if(TransformLine(bits, bits_front, chars, chars_front))
return true;
//insert back one char from the current group
else
{
added_back++;
chars_front--; //represents adding back one character from the group
}
}
//if here then all recursive checks failed so initial must fail
return false;
}
They give the following test cases, which my code solves correctly:
Sample input:
1| 1010 AAAAABBBBAAAA
2| 00 AAAAAA
3| 01001110 AAAABAAABBBBBBAAAAAAA
4| 1100110 BBAABABBA
Correct output:
1| Yes
2| Yes
3| Yes
4| No
Since a transformation is possible if and only if copies of it are, I tried just copying each binary and letter sequences onto itself various times and seeing how the clock goes. Even for very long bit and character strings and many lines it has finished in under 10 seconds.
My question is: since CodeEval is still saying it is running longer than 10 seconds but they don't share their input, does anyone have any further suggestions to improve the performance of this recursion? Or maybe a totally different approach?
Thank you in advance for your help!
Here's what I found:
Pass by constant reference
Strings and other large data structures should be passed by constant reference.
This allows the compiler to pass a pointer to the original object, rather than making a copy of the data structure.
Call functions once, save result
You are calling bits.length() twice. You should call it once and save the result in a constant variable. This allows you to check the status again without calling the function.
Function calls are expensive for time critical programs.
Use constant variables
If you are not going to modify a variable after assignment, use the const in the declaration:
const char curr_char_type = chars[0];
The const allows compilers to perform higher order optimization and provides safety checks.
Change data structures
Since you are perform inserts maybe in the middle of a string, you should use a different data structure for the characters. The std::string data type may need to reallocate after an insertion AND move the letters further down. Insertion is faster with a std::list<char> because a linked list only swaps pointers. There may be a trade off because a linked list needs to dynamically allocate memory for each character.
Reserve space in your strings
When you create the destination strings, you should use a constructor that preallocates or reserves room for the largest size string. This will prevent the std::string from reallocating. Reallocations are expensive.
Don't erase
Do you really need to erase characters in the string?
By using starting and ending indices, you overwrite existing letters without have to erase the entire string.
Partial erasures are expensive. Complete erasures are not.
For more assistance, post to Code Review at StackExchange.
This is a classic recursion problem. However, a naive implementation of the recursion would lead to an exponential number of re-evaluations of a previously computed function value. Using a simpler example for illustration, compare the runtime of the following two functions for a reasonably large N. Lets not worry about the int overflowing.
int RecursiveFib(int N)
{
if(N<=1)
return 1;
return RecursiveFib(N-1) + RecursiveFib(N-2);
}
int IterativeFib(int N)
{
if(N<=1)
return 1;
int a_0 = 1, a_1 = 1;
for(int i=2;i<=N;i++)
{
int temp = a_1;
a_1 += a_0;
a_0 = temp;
}
return a_1;
}
You would need to follow a similar approach here. There are two common ways of approaching the problem - dynamic programming and memoization. Memoization is the easiest way of modifying your approach. Below is a memoized fibonacci implementation to illustrate how your implementation can be speeded up.
int MemoFib(int N)
{
static vector<int> memo(N, -1);
if(N<=1)
return 1;
int& res = memo[N];
if(res!=-1)
return res;
return res = MemoFib(N-1) + MemoFib(N-2);
}
Your failure message is "Aborted after 10 seconds" -- implying that the program was working fine as far as it went, but it took too long. This is understandable, given that your recursive program takes exponentially more time for longer input strings -- it works fine for the short (2-8 digit) strings, but will take a huge amount of time for 100+ digit strings (which the test allows for). To see how your running time goes up, you should construct yourself some longer test inputs and see how long they take to run. Try things like
0000000011111111 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBAAAAAAAA
00000000111111110000000011111111 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBAAAAAAAA
and longer. You need to be able to handle up to 150 digits and 1000 letters.
At CodeEval, you can submit a "solution" that just outputs what the input is, and do that to gather their test set. They may have variations so you may wish to submit it a few times to gather more samples. Some of them are too difficult to solve manually though... the ones you can solve manually will also run very quickly at CodeEval too, even with inefficient solutions, so there's that to consider.
Anyway, I did this same problem at CodeEval (using VB of all things), and my solution recursively looked for the "next index" of both A and B depending on what the "current" index is for where I was in a translation (after checking stoppage conditions first thing in the recursive method). I did not use memoization but that might've helped speed it up even more.
PS, I have not run your code, but it does seem curious that the recursive method contains a while loop within which the recursive method is called... since it's already recursive and should therefore encompass every scenario, is that while() loop necessary?

infinite loop in stack implementation c++

this is my first data structure program. I am implementing a simple stack using array with push, pop and initialize functions. I am getting an infinite loop as the output. Could you please tell me why is this so?
#include<iostream>
using namespace std;
# define SIZE 6
class stack{
public:
void init();
void push(int i);
int pop();
int top;
int stck[SIZE];//bydefault private
};
void stack::init()
{
top=0;
return;
}
void stack::push(int i)
{
if(top==SIZE)
{
cout<<"stack is full";
return;
}
else
{
top=top+1;
stck[top]= i;
return;
}
}
int stack::pop()
{
if(top==0)
{
cout<<"stack is empty. \n";
return 0;
}
else
{
top = top-1;
return(stck[top-1]);
}
}
int main()
{
stack stack1;
stack1.init();
int a;
int m;
while(a!=4)
{
cout<<"1. push 2. pop 3.display 4.exit .\n";
cin>>a;
if(a==1){
cout<< "enter value";
cin>>m;
stack1.push(m);
}
if(a==2)
{
cout<<"popped"<< stack1.pop();
}
if(a==3)
{
for(int k=0; k<=stack1.top;k++)
{
cout<<stack1.stck[k];
}
}
}
}
You never initialize a, so your program has undefined behaviour. Specifically, the while (a != 4) line performs an lvalue-to-rvalue conversion of a while its value is indeterminate, which the C++ standard explicitly states as undefined behaviour in section 4.1.
However, I doubt this is causing the issue at hand. In practice, unless the optimizer just optimized all your code out, your program should usually behave as expected; it's only when a == 4 on the first loop that you have problems. This doesn't make the code acceptable, but there's probably more to it.
I suspect the problem is that you use top to represent one past the number of elements. When you have zero elements, you point to the first; when you have one, you point to the second, etc. This means you're pointing to the first unused element.
However, in both your push and pop functions, you change top first and only then access the stack, but acting as if you didn't change it:
top = top + 1;
stck[top] = i;
When your stack is empty, this will set top to 1 and then access stck[1]. Meanwhile, stck[0] is left unset. When popping, you have the opposite:
top = top - 1;
return stck[top-1];
This sets top back to 0, but returns stck[-1], which is out of bounds.
I suspect that if you push SIZE values onto the stack, you will end up overwriting unrelated memory, which could cause all kinds of trouble. I still don't see how an infinite loop will follow, but given the behaviour is undefined, it is certainly a possible result.
(The alternative is that you at some point enter something other than a number. Seeing as you never check whether your input succeeded, if a != 4 and you enter something invalid, all further reads will fail, and a will remain unequal to 4. You could fix this by making changing your while to be
while (a != 4 && std::cin)
In that case, if you enter something invalid and std::cin goes into a non-good state, your loop (and thus program) will end.)
You only have a single loop, terminated based on user input.
If cin>>a fails, a will have whatever value it started with (undefined in your code), and you will loop on that unchanging value.
Typical ways for the input call to fail include
pressing control+D (on a *nix system)
pressing control+Z (on a Windows system)
redirected input from a pipe or file which is exhausted
There may be other causes of failed input as well.