Cannot print out data in a binary tree - c

Actually, I am here asking you to help debug. So, if you don't have any interest in helping me debugging, you can stop here any go back. However, I believe that my code only contain a small bug because I have tested most part of it.
I have do a little test myself. The code work successfully when I commented out the function pinrtOneNode(), which mean that I only input data into that binary tree. So probably the only bug is in the printOnrNode() function.
And also, the compile time error is
c:\users\...\Local\temp\ccwCUbY.oprompt
c:\users\...\.../bst.c:45printOneNode
collect2.exe:error:ld returned 1 exit status
By the way, the bst.c is where my source code in
So here is the code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct BSTnode{
struct BSTnode* leftchild;
struct BSTnode* rightchild;
char data[20];
}BSTnode;
void prompt(); //this function always prompt the user for selection everytime
//after he input data( inputData() ) or print data( printOneNode() )
void inputData();
void printOneNode();
BSTnode firstNode;
BSTnode* MyNode=&firstNode; //I don't know if it's good to initialize it this way
int main()
{
//MyNode=malloc(sizeof(BSTnode));
MyNode->leftchild=NULL;
MyNode->rightchild=NULL;
strcpy(MyNode->data,"");
while(1)
prompt(); // I use a while loop to prompt user for selection continuously
return 0;
}
/* this function is used to prompt user for selection input*/
void prompt(){
int i=0;
printf("Please select:\n");
printf("1.input a data\n2.print only one data\n3.Exit\n");
scanf("%d",&i);
switch(i){
case 1:
inputData();
break;
case 2:
printOneNode();
break;
case 3:
exit(0);
default:
printf("Please input a valid number!(1-3)");
}
}
/* this is used to input data into the binary tree*/
void inputData(){
char data[20]={0};
printf("Input your data here(character only / less than 19 characters!): ");
scanf("%s",data);
BSTnode** ptr=&MyNode;
while(1){
if(strcmp(data,(*ptr)->data)){
if((*ptr)->rightchild!=NULL){
ptr=&((*ptr)->rightchild);
continue;
}
else{
(*ptr)->rightchild=malloc(sizeof(BSTnode));
ptr=&((*ptr)->rightchild);
(*ptr)->rightchild=NULL;
(*ptr)->leftchild=NULL;
strcpy((*ptr)->data,data);
break;
}
}
else{
if((*ptr)->leftchild!=NULL){
ptr=&((*ptr)->leftchild);
continue;
}
else{
(*ptr)->leftchild=malloc(sizeof(BSTnode));
ptr=&((*ptr)->leftchild);
(*ptr)->leftchild=NULL;
(*ptr)->rightchild=NULL;
strcpy((*ptr)->data,data);
break;
}
}
}
printf(" Your data have been input successfully!\n");
return;
}
/* this is used to print data, only one at a time*/
void PrintOneNode(){
BSTnode** ptr=&MyNode;
printf("The first node is%s\n",(*ptr)->data);
while(1){
printf("Select which side of node do you want to print now(l/r)?(q for quit) ");
//I ask user whether he wanna print out the data in node in the right side
// of the current node or left side
char a;
scanf("%c",&a);
switch(a){
case 'l':
if((*ptr)->leftchild!=NULL){
ptr=&((*ptr)->leftchild);
printf("\t%s\n",(*ptr)->data);
}
else
printf("There is no more leftchild");
break;
case 'r':
if((*ptr)->rightchild!=NULL){
ptr=&((*ptr)->rightchild);
printf("\t%s\n",(*ptr)->data);
}
else
printf("There is no more rightchild!");
break;
case 'q':
return;
default:
return;
}
}
}
Please help. And any improvement to this snippet of code beside the bug will be also appreciated vert much. Thanks.

Related

C Programming - Using Parallel Arrays to enter Names, Exercise Marks and Compute Average of Exercise Marks and Display

I'm doing self-study on C Programming, and I have been recommended the following C Program by my colleagues to study further, where you can enter the Name and Age and it displays and uses Insert, Delete, Display, and Exit menu options.
I'm trying to convert it to my current study stream logic scenario where I need to enter the Name, Exercise Mark 1 (up to 3), and then it computes the Average and gets displayed while employing the Insert, Delete, Display, Update (updating the scores only, not the names), Delete and Exit.
Any guidance please on how to learn this code and understand the logic, and apply it to the 2nd scenario will be much appreciated.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 50
//using parallel arrays as fields in the list
typedef struct list{
char name[MAX][31];
int age[MAX];
int last;
}LIST;
LIST L;//L structure is global
void save();
void retrieve();
void makenull();
void insert(char n[31],int a);
void del(char n[31]);
void display();
int locate(char n[31]);
int isfull();
int isempty();
int menu();
int main(){
char nm[31];
int ag;
makenull();
retrieve();
while(1){
switch(menu()){
case 1: system("cls");printf("Insert Mode\n");
printf("Input Name: ");scanf("%s",nm);
printf("Input Age: ");scanf("%d",&ag);insert(nm,ag);break;
case 2: system("cls");printf("Delete Mode\n");
printf("Input Name: ");scanf("%s",nm);del(nm);break;
case 3: display();break;
case 4: save();exit(0);
default: printf("\n1-4 lang!\n");system("pause");
}
}
return 0;
}
void makenull(){
L.last = -1;
}
void insert(char n[31],int a){
if (isfull()){
printf("List is full.\n");
system("pause");
}
else {
L.last++;
strcpy(L.name[L.last],n);
L.age[L.last]=a;
}
}
void del(char n[31]){
int p;
if (isempty()){
printf("List is empty.\n");
system("pause");
}
else {
p=locate(n);
if (p==-1){
printf("Not found.\n");
system("pause");
}
else{
for(int i = p;i<L.last;i++){
strcpy(L.name[i],L.name[i+1]);
L.age[i]=L.age[i+1];
}
L.last--;
printf("Successful delete operation.\n");
system("pause");
}
}
}
void display(){
int i;
system("cls");
printf(" Name Age \n");
for(i=0;i<=L.last;i++)
printf("%d.) %s %d\n",i+1,L.name[i],L.age[i]);
system("pause");
}
int locate(char n[31]){
int i;
for (i=0;i<=L.last;i++)
if(strcmp(L.name[i],n)==0)
return i;
return -1;
}
int isfull(){
if (L.last==MAX-1)
return 1;
else
return 0;
}
int isempty(){
return(L.last==-1);
}
int menu(){
int op;
system("cls");
printf("MENU\n");
printf("1. Insert\n");
printf("2. Delete\n");
printf("3. Display\n");
printf("4. Exit\n");
printf("\nSelect(1-4): ");
scanf("%d",&op);
return(op);
}
void save(){
FILE *fp;
int i;
fp=fopen("Practice4.dbf","w+");
if (fp==NULL){
printf("File Error.\n");
system("pause");
}
else{
for (i=0;i<=L.last;i++)
fprintf(fp,"%s %d\n",L.name[i],L.age[i]);
}
fclose(fp);
}
void retrieve(){
FILE *fp;
char n[31];
int i,a;
fp=fopen("Practice4.dbf","r+");
if (fp==NULL){
printf("File Error.\n");
system("pause");
}
else {
while(!feof(fp)){
fscanf(fp,"%s %d\n",n,&a);
insert(n,a);
}
}
fclose(fp);
}
Your code isn't properly formatted and there are no comments. I can't give you a direct answer with some code in it, but summing up all my comments (and of course I deleted them), this is what I've to say:
Consider this scenario-
if your .dbf has more than MAX 50 elements, then your while (!feof(fp)) inside retrieve() will keep calling insert() and insert() will keep executing its if () { } block.
You should put something like while (!feof(fp) && L.last < MAX) to prevent that situation and you'll need to further modify your code in insert(). Another thing is, this code doesn't have any update() function and scores variable. You'll need to add scores in your struct as well as there must be scores fields in your .dbf.
Now, for a moment let's say everything else is good to go in your code, then you should follow these following steps:
Declare variables
char nameInput[31];
float ex_marks[3], sum = 0, avr = 0;
in main().
Add another case 5 in your switch () block inside main() and translate and convert the following pseudocode into C code:
Read name in nameInput
locate()
if found then
3.a for i = 0 to 2
Read marks in ex_marks[i]
sum = sum + ex_marks[i]
3.b Calculate avr = sum / 3
3.c Display name and avr
else
Display name is not in the list.
exit
Also read about why is while(!feof()) always wrong?

Passing and returning a struct from a function

I have a function with a book struct array, but when i try to return it to my main it does not return the values and store them in the array. If the addBook function has to be void how would i work around that so that i can access the array elements later.
void addBook(struct Book book[], int *size) {
if (*size == MAX_BOOKS) {
printf("The inventory is full\n");
}
else {
printf("ISBN:");
scanf("%d", &book[*size]._isbn);
printf("Title:");
scanf("%s", book[*size]._title);
getchar();
printf("Year:");
scanf("%d", &book[*size]._year);
printf("Price:");
scanf("%f", &book[*size]._price);
printf("Quantity:");
scanf("%d", &book[*size]._qty);
*size++;
printf("The book is successfully added to the inventory.\n");
}
return book;
}
int main(void) {
struct Book book[MAX_BOOKS];
int size = 0;
int i;
int option;
printf("Welcome to the Book Store\n");
printf("=========================\n");
do {
menu();
printf("Select: ");
scanf("%d", &option);
switch (option) {
case 0:
printf("Goodbye!\n");
break;
case 1:
displayInventory(book, size);
break;
case 2:
addBook(book, &size);
break;
case 3:
//checkPrice();
break;
default:
printf("Invalid input, try again:\n");
}
} while (option != 0);
}
Your return statement isn't going to do what you're intending as the addBook's function signature says it returns void. I'm surprised that the code as is actually compiled without an error about this.
Anyways, the book data can be returned from the same way it was passed in - as an input and output parameter.
Essentially your code could look like the following (which is only meant to be an example of code that compiles and works to save info entered in from standard input into the book):
#include <stdio.h>
struct Book {
int value;
};
#define MAX_BOOKS 2
void addBook(struct Book book[], int *size) {
if (*size == MAX_BOOKS) {
printf("The inventory is full\n");
}
else {
printf("Value:");
scanf("%d", &book[*size].value);
(*size)++;
printf("The book is successfully added to the inventory.\n");
}
}
int main(void) {
struct Book book[MAX_BOOKS];
int size = 0;
addBook(book, &size);
printf("Book 1: Value=%d\n", book[0].value);
}
And here's how this looks when run:
$ ./main
Value:9
The book is successfully added to the inventory.
Book 1: Value=9
Hope this answers your question.
I think your problem is in the line *size++;. You should use parenthesis, otherwise you are modifying the pointer to size, not the value. It should be (*size)++.
Also, the addBook function should not return anything, since it is void, and it is changing the content of the array book already.

Why does this give junk value?

I am getting garbage / junk values as output when my program is run and the data displayed.
Why is it so?
Can someone help me to understand how to properly pass by pointers and not get junk values?
This program is about stack creation of struct books type variables.
By default shouldn't the variable bks pass by pointer and change when b is changed?
bks is still storing garbage value.
Here is my code:
#include<stdio.h>
#include<stdlib.h>
struct books
{
int yrpub;
char name[100],author[50];
};
int top=-1;
int push(struct books b[],int top,int n)
{
if(top==n-1)
return -1;
else
{
++(top);
printf("Enter books info: \n");
printf("Enter name: ");
gets(b[top].name);
printf("Enter author: ");
gets(b[top].author);
printf("Enter Year of publish: ");
scanf("%d",&b[top].yrpub);
return top;
}
}
void display(struct books b[],int top)
{
int i;
if(top==-1)
printf("No books in the stack...");
for(i=0;i<=top;i++)
{
printf("Details of book %d: \n",i+1);
printf("Name: %s\nAuthor: %s\nYear of publish: %d\n",b[i].name,b[i].author,b[i].yrpub);
}
system("pause");
}
int main()
{
struct books bks[10];
int ch;
system("cls");
printf("Select an option:\n");
printf("1. Push book\n2. Pop book\n3. Peep book\n4. Display all books info\n5. Exit\n");
printf("Enter a choice: ");
scanf("%d",&ch);
fflush(stdin);
switch(ch)
{
case 1:
system("cls");
top=push(bks,top,10);
break;
case 4:
system("cls");
display(bks,top);
break;
case 5: exit(0);
default: printf("\nWrong choice...Please retry.");
long i,j;
for(i=0;i<1000000;i++)
for(j=0;j<100;j++);
}
main();
}
Each time you recursively call main(), you create a new array bk.
The information you entered in the previous invocation of main() is hidden from the new one.
To iterate is human; to recurse, divine.
In this context, give up divinity for humanity. Use iteration — in this context it is better.
This is your primary problem; there may also be other off-by-one or other errors.
push:
if(top==n-1)
return -1;
main:
top=push(bks,top,10);
top is reset when the stack is full
Edit:
And the second problem is main being called again, struct books bks[10] is reset in the next main, it is a recursion. Declare bks as global or go with a while loop instead of recursion.
while (1) {
getChoices();
if (exit)
/* exit from here */
process();
}

Reading a text file to a doubly linked list

I'm coding a contact manager using a doubly linked list that is manipulated by functions using pointers that reads in a contactList.txt.
#include<stdio.h>
#include<conio.h>
#include<string.h>
#include<process.h>
#include<stdlib.h>
#include<dos.h>
//functions
listelement * getFirst(listelement *listpointer,string query[MAX]);
void getLast();
void getEmail();
void getCompany();
void getNumber();
void editCon();
void delCon();
void addCon();
void listAll();
void sortCon();
void Menu (int *choice);
#define MAX 20
//struct to order contactList
struct contact
{
string firstName[MAX],lastName[MAX],email[MAX],companyName[MAX];
long phoneNum[MAX];
struct listelement *link
struct contact *next;
struct contact *prev;
}list;
int main()
{
listelement listmember, *listpointer;
string query;int iChoice = 0;
listpointer = NULL;
Menu (&iChoice);
int iChoice;
fflush(stdin);
scanf_s("%d", &iChoice);
// user enters one of 9 values
// options are as follows: get first name,last name,list all contacts,search through contacts,add a new contact,edit/delete or sort contacts.
switch(iChoice)
{
case 1:
{
printf ("Enter contact first name to get details ");
scanf ("%d", &query);
listpointer = getFirst (listpointer, query);
break;
}
case 2:
{
getLast();
break;
}
case 3:
{
listAll();
break;
}
case 4:
{
getEmail();
break;
}
case 5:
{
getCompany();
break;
}
case 6:
{
getNumber();
break;
}
case 7:
{
addCon();
break;
}
case 8:
{
editCon();
break;
}
case 9:
{
delCon();
break;
}
case 10:
{
sortCon();
break;
}
case 11: // exit
{
printf("\n\nProgram exiting!...");
exit(0);//terminates program
break;
}
default:
printf ("Invalid menu choice - try again\n");
break;
}//end of switch
return(iChoice);
}//end of main
//menu function to test if invalid input was entered in a menu choice.
void Menu (int *iChoice)
{
char local;
system("cls");
printf("\n\n\t\\n\n");
printf("\n\n\t\tWelcome to my Contact Manager\n\n");
printf("\n\t\t1. First name");
printf("\n\t\t2. Last name");
printf("\n\t\t3. List all contacts");
printf("\n\t\t4. Search email");
printf("\n\t\t5. Search company name");
printf("\n\t\t6. Search number");
printf("\n\t\t7. Add contact");
printf("\n\t\t8. Edit contact");
printf("\n\t\t9. Delete contact");
printf("\n\t\t10. Sort contacts");
printf("\n\t\t11. Exit");
printf("\n\n\t\tEnter your menu choice: ");
do
{
local = getchar ();
if ( (isdigit(local) == FALSE) && (local != '\n') )
{
printf ("\nYou must enter an integer.\n");
printf ("");
}
} while (isdigit ((unsigned char) local) == FALSE);
*iChoice = (int) local - '0';
}
//function to get a contact by entering first name
listelement * getFirst (listelement *listpointer, string query)
{
//variables
char query[MAX],firstName[MAX];
FILE *fp, *ft;
int i,n,ch,l,found;
system("cls");
do
{
found=0;
l=strlen(query);
fp=fopen("ContactList.txt","r");
system("cls");
printf("\n\n..::Search result for '%s' \n===================================================\n",query);
while(fread(&list,sizeof(list),1,fp)==1)
{
for(i=0;i<=l;i++)
firstName[i]=list.firstName[i];
firstName[l]='\0';
if(stricmp(firstName,query)==0)
{
printf("\n..::First Name\t: %s\n..::Second Name\t: %ld\n..::Email\t: %s\n..::CompanyName\t: %s\n..::Number\t: %s\n",list.firstName,list.lastName,list.email,list.companyName.list.phoneNumber);
found++;
if (found%4==0)
{
printf("..::Press any key to continue...");
getch();
}
}
}
if(found==0)
printf("\n..::No match found!");
else
printf("\n..::%d match(s) found!",found);
fclose(fp);
printf("\n ..::Try again?\n\n\t[1] Yes\t\t[11] No\n\t");
scanf("%d",&ch);
}while(ch==1);
}
Anyone have any idea as to where I'm going wrong in the code?Thanks
Your errors are because:
1) you don't define listelement anywhere
2) you don't define string anywhere (and it's not a type in C)
3) You need to move the #define MAX up above before you use it.
4) You don't define FALSE anywhere (and it's not a type in C)
5) You're redefining elements too, in getFirst() you've passed in query as a "string", then you
define a new query as a char array
6) You get redefinition errors because you've got more than one define. That's somewhat #5 but there's more as well. In your main you declare iChoice here: string query;int iChoice = 0;
then you declare it again int iChoice; right after your Menu() call
7) Please don't do fflush(stdin) that's undefined behavior as per the C standard

C stack array problem

My function code for peek is not working? why is that? can anyone help me with my peek function?
#include<stdio.h>
#include<stdlib.h>
#define maxsize 10
int stack[maxsize];
int stacktop=0;
void instructions();
int process();
int push(int value);
int pop();
void display();
void peek();
int main()
{
process();
getch();
}
int process()
{
int val;
int choice;
do
{
instructions();
printf("Enter Your Choice: ");
scanf("%d",&choice);
switch( choice )
{
case 1:
printf("\nElement to be Pushed : ");
scanf("%d",&val);
push(val);
break;
case 2:
val=pop();
if(val!=-1)
{
printf("Popped Element : %d\n",val);
}
break;
case 3:
peek();
break;
case 4:
display();
break;
case 5:
break;
}
}while(choice !=5);
}
void instructions()
{
printf("Enter Your choice for the following process\n");
printf("\n[1]Push a Node on top of the list");
printf("\n[2]Pop a node off the list");
printf("\n[3]Peek The Top Node");
printf("\n[4]Display The Whole list");
printf("\n[5]Exit The Program\n");
}
int push(int val)
{
if(stacktop<maxsize)
{
stack[stacktop++]=val;
}
else
{
printf("Stack is full");
}
}
int pop()
{
int a;
if(stacktop>0)
{
a=stack[--stacktop];
return a;
}
}
void display()
{
int i;
i = 0;
if(stacktop>0)
{
printf("Elements are:");
while(i<stacktop)
{
printf("\n%d--\n",stack[i++]);
}
}
}
void peek()
{
printf("%d",stacktop);
}
Is it supposed to be:
printf("%d\n", stack[stacktop - 1]);
Print the contents, rather than the size of the stack?
Obviously you'd also need to bounds check to make sure you're not printing outside of the range of your stack (when it's empty)
I know this isn't Code Review, but I thought I would give you a few bits of advice.
When you call scanf, always check the result. For example, if the user enters something other than a decimal number, your code will end up putting an indeterminate value into the choice or val variables. The scanf function returns the number of items that were successfully read. If you asked for one item, and scanf returns 1, then you can rely on the value of that object:
int choice;
if (scanf("%d", &choice) != 1)
// handle error, can't rely on value of "choice"
else
// continue onwards, can rely on value of "choice"
Usually, the \n escapes go at the end of the string literal, not at the beginning. It is more common to do it this way, but it doesn't mean it should always go at the end.
printf("Enter Your choice for the following process\n\n");
printf("[1]Push a Node on top of the list\n");
printf("[2]Pop a node off the list\n");
printf("[3]Peek The Top Node\n");
For outputting simple strings, consider just using the puts function, which automatically appends the new-line character for you:
puts("Enter Your choice for the following process");
puts("");
puts("[1]Push a Node on top of the list");
puts("[2]Pop a node off the list");
puts("[3]Peek The Top Node");
Your display method is a perfect example of when to use a for loop instead of a while loop. Generally speaking, use a for loop when you know exactly how many items you have and you want to iterate over each of them:
void display()
{
int i;
puts("Elements are:");
for (i = 0; i < stacktop; i++)
printf("\n%d--\n", stack[i]);
}
To reverse the order of the stack, simply start at the top and go backwards:
void display()
{
int i;
puts("Elements are:");
for (i = stacktop - 1; i >= 0; i--)
printf("\n%d--\n", stack[i]);
}

Resources