4

My program is supposed to convert a prompt from infix to postfix. So far, through a debugger and various other methods, I have located the exact point at which I segfault, but don't understand why.

Here's my code:

Here's itop.h:

using namespace std;
#include <cstdlib>
#include <iostream>

class sNode{
    public:
       char data;
       sNode *next;
};

class stack{
    public:
        sNode *head;
        void push (char);
        sNode pop();
        int rank(char);
        stack()
        {
        cout << "Initiliazing stack." << endl;
        }
};

This is my itop.cpp file:

    #include "itop.h"

    void stack::push (char a)
    {
            // cout << "Pushing " << a << endl;
            sNode *sn;
            sn = new sNode;
            sn->data = a;
            sn->next = head;
            head = sn;
    }

    sNode stack::pop()
    {
            // cout << "Popping stack." << endl;
            sNode *sn;
            sn = head;
            head = head->next;
            return *sn;
    }

    int stack::rank(char x)
    {
            int num = 0;
            // cout << "Checking rank." << endl;
            if(x == '\0')
            {
                    num = 1;
                    // cout << "Checking for null" << endl;
                    return num;
            }
            else if(x == '+' || x == '-')
            {
                    num = 2;
                    // cout << "Checking if + or -" << endl;
                    return num;
                    // cout << "After return." << endl;
            }
            else if(x == '*' || x == '/')
            {
                    num = 3;
                    // cout << "Checking for * or /" << endl;
                    return num;
            }
            else
                    cout << "Error! Input not valid!" << endl;
    }

And here's main.cpp:

using namespace std;
#include <iostream>
#include <cstdlib>
#include <cstring>
#include "itop.h"

int main()
{
char *temp1;            //Instantiating variables.
char *temp2;
temp1 = new char[20];
temp2 = new char [20];
stack s;
do              //Checking commands.
{
    cout << "infix_to_postfix> ";
    cin >> temp1;
    if(strcmp(temp1, "quit") == 0)
    {
        return 0;
    }
    if(strcmp(temp1, "convert") != 0)
    {
        cout << "Error! Invalid command." << endl;
    }
    cin >> temp2;
    if(strcmp(temp1, "convert") == 0)
    {
        for(int i=0; i<sizeof(temp2); i++)
        {
            if(isdigit(temp2[i]))
            {
                cout << atoi(&temp2[i]);
            }
            else if(s.rank(temp2[i]) < s.rank(s.head->data))
            {
                sNode temp = s.pop();
                cout << temp.data;
            }
            else
            {
                s.push(temp2[i]);
            }
        }
    }
    else
    {
        cout << "Error! Command not supported." << endl;
    }
}while(strcmp(temp1, "quit") != 0);

return 0;
}

The function is called at

else if(s.rank(temp2[i]) < s.rank(s.head->data))

And the problem is in here:

            else if(x == '+' || x == '-')
            {
                    num = 2;
                    // cout << "Checking if + or -" << endl;
                    return num;
                    // cout << "After return." << endl;
            }

Specifically right before return num, I get "Segmentation fault (core dumped)" error message. I have used gdb and all I know is that right after "Checking if + or -" I see "$1 = 2". I'm not quite sure what that means, but it is what I want to return.

Thank you for your help.

Manishearth
  • 14,882
  • 8
  • 59
  • 76
Sarah Awesome
  • 53
  • 1
  • 7
  • Why do you create the variable `num`? You can directly return the integers. – askmish Oct 20 '12 at 02:13
  • I was just trying to get the code simplified. :) @OP: Please show us the calling functions. – askmish Oct 20 '12 at 02:15
  • 1
    The calling functions are necessary. A segfault on return is usually a symptom of you corrupting your stack somewhere before said return - but it's rather unclear what you could be doing here that would cause that. – James Oct 20 '12 at 02:18
  • I thought maybe returning a straight int might have been the problem. I just didn't see the point in changing it back. – Sarah Awesome Oct 20 '12 at 02:23
  • returning ints would never be a problem when the function's return type is int. Of course, if you are using the return value of the function differently or with another data type, in your calling function, seg fault can occur there too. Could you post the calling function code? – askmish Oct 20 '12 at 02:27
  • `s.rank(s.head->data)` It seems s.head will be containing NULL. – askmish Oct 20 '12 at 02:51

2 Answers2

1

There are many mistakes in your code. Your stack implementation is wrong. push() for example only sets head over and over again. This results in your stack class being able to ever only hold one element. next is never set to anything, so it contains random garbage. Further down, you have this:

for(int i=0; i<sizeof(temp2); i++)

sizeof(temp2) does not give you the amount of characters of the string temp2 points to. It gives you the size of the pointer temp2 itself. Furthermore, you end up reading s.head from an empty stack, which will be a pointer to random garbage. At that point, all bets are off of course. You can't expect anything else than a crash and burn.

Nikos C.
  • 50,738
  • 9
  • 71
  • 96
  • 1
    @askmish Nope. Plain old eyes. Which means, I *could* be wrong :-) – Nikos C. Oct 20 '12 at 03:11
  • Isn't next set to the previous head by using `sn->next = head; `head=sn; Head is simply the top of the stack, so when I add something on top, the new node must become the head and next points to the old head. Thank you for the sizeof, thing though. – Sarah Awesome Oct 20 '12 at 03:35
0

Fix 1:Write a proper constructor.

    stack()
    {
    head=NULL;
    cout << "Initiliazing stack." << endl;
    } 

Fix 2:Write an extra method to check if stack is empty.

int stack::empty()
{
    if(head == NULL)
      return true;
    else
      return false;
}

Fix 3:Check if stack empty before using the stack data.

else if(!s.empty() && s.rank(temp2[i]) < s.rank(s.head->data))
{
 ...
}

Fix 4: Fix the rest of the code logic.

askmish
  • 6,464
  • 23
  • 42
  • @OP: You could also use the STL stack. – askmish Oct 20 '12 at 03:25
  • 1
    We're not allowed to use the Stack library. Thank you so much, askmish! checking for an empty stack really helped. Now I just need to figure out the correct order for infix to postfix(basically the whole point of this exercise) and then I'll be complete. – Sarah Awesome Oct 20 '12 at 04:29