So, as an exercise I wanted to make a simple binary tree as practice before moving on to other, harder things. I tried to implement a binary tree in a simple guessing game scenario. I can't test it due to issues I'm having with taking in input. But I can't reproduce the error in a smaller program, so I don't know what is going on.
testbinary.c:
//can't do default functions parameters in C
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
struct binary {
unsigned long ID;
char *guess;
char isAns;
struct binary *yes;
struct binary *no;
};
typedef struct binary Node;
char * expstrcpy(char * a);
Node *getnew(char *msg, char isAns);
void push1(Node **old,Node *nnew,char yn);
void push2(Node **old,char *str,char yn);
void replace(Node **old, Node *nnew);
void pop(Node **pop,char yn);
void destroy_node(Node **a);
void destroy_branch(Node **del, int depth);
int isyes(char *a);
int isno(char *a);
void traverse(Node **top);
char * expstrcpy(char * a)
{
char *b = malloc(sizeof(a));
while(*b++ = *a++);
return b;
}
Node * getnew(char *msg, char isAns)
{
Node *nnew = malloc(sizeof(Node));
nnew->ID=clock();
nnew->guess=msg;
isAns=isAns;
nnew->yes=0;
nnew->no=0;
return nnew;
}
void push1(Node **old,Node *nnew,char yn)
{
if(yn=='y')
nnew->yes=*old;
else
nnew->no=*old;
*old = nnew;
}
void push2(Node **old,char *str,char yn)
{
Node *nnew = getnew(str,'n');
if(yn=='y')
nnew->yes=*old;
else
nnew->no=*old;
*old = nnew;
}
void replace(Node **old, Node *nnew)
{
Node *a = *old;
nnew->yes=a->yes;
nnew->no=a->no;
free(a->guess);
a->yes=0;
a->no=0;
*old = nnew;
free(a);
}
void pop(Node **pop,char yn)
{
Node *a = *pop;
free(a->guess);
if(yn=='y')
{
printf("In pop, calling destroy_branch on a->no\n");
destroy_branch(&a->no,0);
*pop=(*pop)->yes;
}
else
{
printf("In pop, calling destroy_branch on a->yes\n");
destroy_branch(&a->yes,0);
*pop=(*pop)->no;
}
a->yes=0;
a->no=0;
free(a);
}
void destroy_node(Node **a)
{
if(*a)
{
if((*a)->yes)
printf("destroy_node: Warning: a->yes may possibly point to valid memory\n");
if((*a)->no)
printf("destroy_node: Warning: a->no may possibly point to valid memory\n");
free((*a)->guess);
(*a)->yes=0;
(*a)->no=0;
free(*a);
*a = 0;
}
}
void destroy_branch(Node **del, int depth)
{
if(*del)
{
fprintf(stdout, "In destroy_branch, ID: %lu, %i deep\n",(*del)->ID,depth);
if((*del)->yes)
destroy_branch(&(*del)->yes,depth+1);
else
destroy_node(&(*del)->yes);
if((*del)->no)
destroy_branch(&(*del)->no,depth+1);
else
destroy_node(&(*del)->no);
fprintf(stdout, "destroy_branch, at depth: %i, destroying ID:%lu\n",depth,(*del)->ID);
destroy_node(del);
}
}
int isyes(char *a) { return ((a=="y")||(a=="yes")||(a=="1")||(a=="one")||(a=="yeah")||(a=="yea")); }
int isno(char *a) { return ((a=="n")||(a=="no")||(a=="0")||(a=="zero")||(a=="nope")||(a=="nay")); }
void traverse(Node **top)
{
if(*top)
{
char ans[128] = "ok";
char ans2[128] = "ok";
if((*top)->isAns=='y')
fprintf(stdout,"Is it %s (y/n)? ",(*top)->guess);
else
fprintf(stdout,"%s (y/n)? ",(*top)->guess);
fgets(ans,128,stdin);
if((*top)->isAns=='y')
{
if(isyes(ans))
{
printf("Successful string of guesses!\n");
}
else
{
printf("Enter another question to figure out the difference: ");
fgets(ans,128,stdin);
printf("Enter the right answer: ");
fgets(ans2,128,stdin);
push1(top,getnew(ans,'n'),'n');
(*top)->yes = getnew(ans2,'y');
}
}
else
{
if(isyes(ans))
{
if((*top)->yes)
traverse(&(*top)->yes);
else
{
printf("Null node for top->yes\n");
printf("Enter an answer: ");
fgets(ans,128,stdin);
(*top)->yes=getnew(ans,'y');
}
}
else
{
if((*top)->no)
traverse(&(*top)->no);
else
{
printf("Null node for top->no\n");
printf("Enter an answer: ");
fgets(ans,128,stdin);
(*top)->no=getnew(ans,'y');
}
}
}
}
else /************** right here ***************/
{
char ques[128] = "ok";
char ans[128] = "ok";
printf("Node is null\n");
printf("Put in a question and answer to yes condition\n");
printf("Enter question: ");
while(!fgets(ques,128,stdin));
printf("Enter answer for yes condition: ");
while(!fgets(ans,128,stdin));
(*top) = getnew(ques,'n');
(*top)->yes=getnew(ans,'y');
}
printf("\n\n");
}
int main()
{
Node *top = 0;
int choice=7;
while(choice)
{
printf("What would you like to do?\n");
printf("\n\t0 -- quit\n\t1 -- traverse tree\n\t2 -- delete tree\n\n:");
scanf("%d",&choice);
if(choice==1)
{
traverse(&top);
}
else if(choice==2)
{
printf("\nWill now destroy the tree from top node:\n\n");
destroy_branch(&top,0);
}
else if((choice<0)||(choice>2))
{
printf("\nInvalid option\n");
}
}
return 0;
}
output:
What would you like to do?
0 -- quit
1 -- traverse tree
2 -- delete tree
:1
Node is null
Put in a question and answer to yes condition
Enter question: Enter answer for yes condition: what?
This works fine:
#include <stdio.h>
int main()
{
char ques[128] = "ok";
char ans[128] = "ok";
printf("Node is null\n");
printf("Put in a question and answer to yes condition\n");
printf("Enter question: ");
fgets(ques,128,stdin);
printf("Enter answer for yes condition: ");
fgets(ans,128,stdin);
fprintf(stdout,"question received: %s\n",ques);
fprintf(stdout,"answer received: %s\n",ans);
return 0;
}
valgrind just tells me that after 1 run I leaked 40 bytes. So no help there really.