0

I'm working on a project where I must take an expression in reverse polish notation, push the integers and operators onto a stack, then pop them out off the stack as they are inserted into a binary search tree.

#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

struct snode 
{
  int datum;
  struct snode* bottom;
};

struct tnode
{
  int datum;
  struct tnode* left;
  struct tnode*right;
};

struct snode* 
push(struct snode* stack, int x) {
  struct snode *S = (struct snode*)malloc(sizeof(struct snode));
  S->datum = x;
  S->bottom = stack;
  return S;
}

struct snode* pop(struct snode* stack) {
  struct snode *S;
  if (stack == NULL)
    return NULL;
  S = stack->bottom;
  free(stack);
  return S;
}

int
peek(struct snode* stack){
  return stack->datum;
}


struct tnode*
create_node(int x){
  struct tnode* tmp;
  tmp = (struct tnode*)malloc(sizeof(struct tnode));
  tmp->datum = x;
  tmp->right = NULL;
  tmp->left = NULL;
  return tmp;
}

void
print_table(struct tnode *AST){
  if(AST !=NULL){
    print_table(AST->left);
    printf("%d ", AST->datum);
    print_table(AST->right);
  }
}

struct tnode*
build_tree(struct snode *S)
{
  struct tnode* root;
  if (S==NULL){
    return NULL;
  }else{
    int top = peek(S);
    if (top == 65 || top == 83 || top == 88 || top == 68 || top == 77){
      return create_node(top);
    }else{
      root= create_node(top);
      root->right = build_tree(pop(S));
      root->left = build_tree(pop(S));
      return root;
    }
  }
}

int
main(int argc, const char *argv[])
{

  int i = 1;
  struct tnode *tree = NULL;
  struct snode *stack = NULL;


  while (argv[i]!= NULL){
    stack = push(stack, argv[i][0]);
    i++;
  }

 tree =  build_tree(stack);
 print_table(tree);

 return EXIT_SUCCESS;
}

I feel like this should work. Everything compiles clean. I run it by saying

./project 5 4 A

and what comes out is

135208 135224 135208 135240 135208 135224 135208 0 135208 135224 135208 52 0 53 0 

when it should be

4 65 5

I think this is happening where because of how I'm pushing the elements on to the stack.

EDIT:

I initialized i so that i = 1.

this is the result I am getting.

134480 134496 134480 0 5 4 5 

EDIT2:

I decided to get rid of the atol(argv[i]) and change it to just argv[i][0]. see code.

Now my out put is just

65
etorr96
  • 81
  • 9
  • You're not flushing the memory before use, which is bad practice. – Sarima May 04 '15 at 21:35
  • For starters, intialize `stack` - it's starting off filled with garbage, when you want it to be `NULL`. – Paul Roub May 04 '15 at 21:35
  • Use a debugger. Step through your code. – abelenky May 04 '15 at 21:37
  • While you're at it, initialize `i`. Don't assume it's `0`. For all you know, you're starting from `argv[2074]` and moving on until you hit a `NULL` somewhere. – Paul Roub May 04 '15 at 21:38
  • I edited the question to match these suggestions – etorr96 May 04 '15 at 21:43
  • 1
    This is C, so do not cast the return of `malloc()`. Required in C++, but ***[highly discouraged](http://stackoverflow.com/q/1565496/645128)*** in C. – ryyker May 04 '15 at 21:50
  • 1
    If you think the problem is in the way you push elements onto the stack, then remove all of the code dealing with the tree and examine the stack. Personally I think there's a problem in `build_tree`. – Beta May 04 '15 at 21:50
  • 2
    I think `atol("A")` for the last arg `A` does not do what you think it does. – Jens May 04 '15 at 21:54
  • Right out of the shoot (compile time) I get a Illegal type in `main()`.. Change `int main(int argc, const char *argv[]) ` to `int main(int argc, char *argv[]) ` (get rid of the `const` keyword. The next thing I see (runtime error) is dereference of pointer to freed memory in `pop()`. You are either freeing it somewhere, or have moved the pointer. – ryyker May 04 '15 at 22:03
  • I get no errors or warnings when I compile this code. I was also taught in class to use const char * argv. @rykker – etorr96 May 04 '15 at 22:05
  • Okay, that could be an idiosyncrasy of my environment settings. But the runtime you will see. My code is identical (except my change to `main()` arguments) and I get a freed memory error on the line `S = stack->bottom;` in the `pop()` function. – ryyker May 04 '15 at 22:06
  • @etorr96 I suspect yuor teacher actually either said, or meant to say, `const char **argv` - note the extra `*`. That makes it identical to `const char *argv[]` – kdopen May 04 '15 at 22:32
  • 1
    seems you were assigned the same task as http://stackoverflow.com/questions/30008377/printing-abstract-syntax-tree-infinite-recursion-issue/30009012#30009012 - build_tree is your problem, not your stack implementation! in fact the argv array already forms some kind of a stack, so moving values from there on the stack is quite useless. try pushing nodes of the syntax tree on the stack instead and try not to call the tree you are constructing a search tree. – mikyra May 04 '15 at 23:58

1 Answers1

0

Finally figured out what was going on!

Here is the newly modified sections that should make your code work (please view the // <== EDIT comments) :

struct tnode*
build_tree(struct snode *S)
{

  struct tnode* root;
  if (S == NULL)
    return NULL;

  int top = peek(S);

  if (top == 65 || top == 83 || top == 88 || top == 68 || top == 77)
  {
     root = create_node(top);
     S = pop(S); // <== EDIT
     root->right = build_tree(S);


     S = pop(S); // <== EDIT
     root->left = build_tree(S);
     return root;
  } 

  root= create_node(top);

  return root;
}

int
main(int argc, const char *argv[])
{

  int i = 1;
  struct tnode *tree = NULL;
  struct snode *stack = NULL;

  int value = 0;
  while (argv[i]!= NULL)
  {
    if ((value = atoi(argv[i])) == 0) // <== EDIT
        value = argv[i][0];
    stack = push(stack, value);
    i++;
  }


 tree =  build_tree(stack);
 print_table(tree);

 return EXIT_SUCCESS;
}

I have noticed 3 issues that are causing the values that you have.

First issue : The result that you are looking for is 4 65 5, which means that if the input is a number (4, 5, etc) you must use the result of atoi(). If the input is not a number, you must use the ASCII value.

To do this, I have used the following lines :

    if ((value = atoi(argv[i])) == 0) // <== EDIT
        value = argv[i][0];
    stack = push(stack, value);

In my implementation of atoi(), when the conversion fails, atoi() returns 0. Therefore, I check the value of the assignment : if atoi() returned 0, use the ASCII value.

Second issue : The second problem you are having is that the build_tree() function seems to have faulty logic. Since this is a tree, I would expect the character A to be the root and the numbers 4 and 5 to be the branches, like so :

  A
 / \
4   5

Your logic seems to reverse the situation, the way you are setup, the numbers become root values and the letters are branches. Reversing your logic solves this :

  int top = peek(S);

  if (top == 65 || top == 83 || top == 88 || top == 68 || top == 77)
  {
     root = create_node(top);
     S = pop(S); // <== EDIT
     root->right = build_tree(S);


     S = pop(S); // <== EDIT
     root->left = build_tree(S);
     return root;
  } 

  root= create_node(top);

  return root;

Last issue : This is the big one. When you call build_tree(), you pass the result of pop() directly. The problem with that, is that you are not affecting the new root value to S. Because of this :

  1. When you call build_tree(pop(S)) the first time, you end up freeing the memory space for S.

  2. Later, when you call build_tree(pop(S)) a second time, you end up calling pop(S) on the initial value (the one that has been freed early on).

The solution is to reassign S when you call pop(), and calling build_tree(S) afterwards.

     S = pop(S); // <== EDIT
     root->right = build_tree(S);


     S = pop(S); // <== EDIT
     root->left = build_tree(S);

TL;DR : I reformated your code a bit and the issue should be fixed now. Copy paste and you should be good.

Corb3nik
  • 1,177
  • 7
  • 26
  • thank you so so much. The reason why I was so confused is because in my class today, my instructor gave the class that build tree function in pseudocode. I thought I rewrote it correctly but i guess I didnt. Thats why I thought it was the way I was pushing onto the stack – etorr96 May 05 '15 at 03:28