How to solve exception thrown in traversing forest - c

Question: Compute numbers of leaves in forest. Promblem: After debugging and printing a part of data, when I traverse printf("%d ", node->data);, incurred in a runtime error, that is, exception thrown: read access violation.
MainFunc.c
#include "AllFun.h"
int main(int argc, char* argv[])
{
CsNode* tree = (CsNode*)malloc(sizeof(CsNode));
if (tree) {
tree->firstchild = NULL;
tree->nextsibling = NULL;
CreateTree(&tree);
preOrder(tree);
int leaves = CountForestLeaves(tree);
printf("leaves: %d", leaves);
}
return 0;
}
AllFun.h
#include <stdio.h>
#include <stdlib.h>
typedef struct CsNode {
struct CsNode* firstchild;
struct CsNode* nextsibling;
int data;
}CsNode;
void CreateTree(CsNode** node);
void preOrder(CsNode* node);
int CountForestLeaves(CsNode* tree);
OtheFunc.c
#include "AllFun.h"
void CreateTree(CsNode** node)
{
int data;
printf("please input data: ");
scanf_s("%d", &data);
if (data != -1) {
*node = (CsNode*)malloc(sizeof(CsNode));
(*node)->data = data;
(*node)->firstchild = NULL;
(*node)->nextsibling = NULL;
CreateTree(&(*node)->firstchild);
CreateTree(&(*node)->nextsibling);
}
}
void preOrder(CsNode* node)
{
if (node != NULL) {
printf("%d ", node->data);
preOrder(node->firstchild);
preOrder(node->nextsibling);
}
}
int CountForestLeaves(CsNode* tree)
{
if (tree == NULL)
return 0;
if (tree->firstchild == NULL)
return 1 + CountForestLeaves(tree->nextsibling);
else {
return CountForestLeaves(tree->firstchild) + CountForestLeaves(tree->nextsibling);
}
}

Related

Variable value changing after returning to the loop

I've been coding for a C - Binary Search Tree, but the Program always change variable when returning to the loop. I've tried debugging it and checked every pointer but found no errors.
There is a simple run(bold for input, italic for notes)
a
Please enter name of pet:
aaa //pet name, input
Please enter pet kind:
bbb //pet kind, input
add pet success
aaa //pet name, is correct
//pet kind, return to 0
q
0b //pet name, turn to 0b
//pet kind, always 0
Bye.
The code is the next:
main.c
#include "tree.h"
#define CHECK
char menu(void);
void addpet(Tree *pt);
char *s_gets(char *st, int n);
int main(void)
{
Tree pets;
char choice;
InitializeTree(&pets);
while ((choice = menu()) != 'q')
{
switch (choice)
{
case 'a':
addpet(&pets);
#ifdef CHECK
printf("%s", pets.root->head->petname);
printf("%s", pets.root->head->petkind); // petkind back to 0
#endif
break;
default:
puts("Switching error");
}
}
#ifdef CHECK
puts(pets.root->head->petname); // trun to '\000' '372' '\333' 'b' '\376' '\177'
puts(pets.root->head->petkind); // always 0
#endif
puts("Bye.");
return 0;
}
char menu(void)
{
int ch;
ch = getchar();
while (getchar() != '\n')
continue;
return ch;
}
void addpet(Tree *pt)
{
Item temp;
if (TreeIsFull(pt))
puts("No room in the club!");
else
{
puts("Please enter name of pet:");
s_gets(temp.petname, SLEN);
puts("Please enter pet kind:");
s_gets(temp.petkind, SLEN);
temp.next = NULL;
if (AddItem(&temp, pt))
puts("add pet success");
}
}
char *s_gets(char *st, int n)
{
char *ret_val;
char *find;
ret_val = fgets(st, n, stdin);
if (ret_val)
{
find = strchr(st, '\n');
if (find)
*find = '\0';
else
while (getchar() != '\n')
continue;
}
return ret_val;
}
tree.c
#include "tree.h"
static Node *MakeNode(Item *pi);
static bool ToLeftNode(const Node *i1, const Node *i2);
static bool ToRightNode(const Node *i1, const Node *i2);
static void AddNode(Node *new_node, Node *root);
static PairNode SeekNode(const Node *pn, const Tree *ptree);
static PairItem SeekList(Node *, const Item *);
void InitializeTree(Tree *ptree)
{
ptree->root = NULL;
ptree->size = 0;
}
bool TreeIsFull(const Tree *ptree)
{
if (ptree->size == MAXITEMS)
return true;
else
return false;
}
bool AddItem(Item *pi, Tree *ptree)
{
Node *new_node;
PairNode seek_node;
PairItem seek_list;
if (TreeIsFull(ptree))
{
fprintf(stderr, "Tree is full\n");
return false;
}
new_node = MakeNode(pi);
if (new_node == NULL)
{
fprintf(stderr, "Couldn't create node\n");
return false;
}
if ((seek_node = SeekNode(new_node, ptree)).child != NULL)
{
if ((seek_list = SeekList(seek_node.child, pi)).child != NULL)
{
fprintf(stderr, "Attempted to add duplicate item\n");
return false;
}
seek_list.child = pi;
ptree->size++;
return true;
}
ptree->size++;
if (ptree->root == NULL)
ptree->root = new_node;
else
AddNode(new_node, ptree->root);
return true;
}
static void AddNode(Node *new_node, Node *root)
{
if (ToLeftNode(new_node, root))
{
if (root->left == NULL)
root->left = new_node;
else
AddNode(new_node, root->left);
}
else if (ToRightNode(new_node, root))
{
if (root->right == NULL)
root->right = new_node;
else
AddNode(new_node, root->right);
}
else
{
fprintf(stderr, "location error in AddNode()\n");
exit(1);
}
}
static bool ToLeftNode(const Node *i1, const Node *i2)
{
if (strcmp(i1->petname, i2->petname) < 0)
return true;
else
return false;
}
static bool ToRightNode(const Node *i1, const Node *i2)
{
if (strcmp(i1->petname, i2->petname) > 0)
return true;
else
return false;
}
static Node *MakeNode(Item *pi)
{
Node *new_node;
new_node = (Node *)malloc(sizeof(Node));
if (new_node != NULL)
{
strcpy(new_node->petname, pi->petname);
new_node->head = pi;
new_node->left = NULL;
new_node->right = NULL;
}
return new_node;
}
static PairNode SeekNode(const Node *pn, const Tree *ptree)
{
PairNode look;
look.parent = NULL;
look.child = ptree->root;
if (look.child == NULL)
return look;
while (look.child != NULL)
{
if (ToLeftNode(pn, look.child))
{
look.parent = look.child;
look.child = look.child->left;
}
else if (ToRightNode(pn, look.child))
{
look.parent = look.child;
look.child = look.child->right;
}
else
break;
}
return look;
}
static PairItem SeekList(Node *pn, const Item *pi)
{
PairItem seek;
seek.child = pn->head;
seek.parent = NULL;
while (seek.child != NULL)
{
if (strcmp(seek.child->petname, pi->petname) == 0 &&
strcmp(seek.child->petkind, pi->petkind) == 0)
break;
seek.parent = seek.child;
seek.child = seek.child->next;
}
return seek;
}
tree.h
#ifndef TREE_H_
#define TREE_H_
#define SLEN 20
#define MAXITEMS 10
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct item{ char petname[SLEN]; char petkind[SLEN]; struct item *next;} Item;
typedef struct node{ char petname[SLEN]; Item *head; struct node *left; struct node *right;} Node;
typedef struct tree{ Node *root; int size;} Tree;
typedef struct pairnode{ Node *parent; Node *child;} PairNode;
typedef struct pairitem{ Item *parent; Item *child;} PairItem;
void InitializeTree(Tree *ptree);
bool AddItem(Item *pi, Tree *ptree);
#endif
My question was answered elsewhere.
Modify function addpet:
void addpet(Tree* pt)
{
Item* temp = (Item*)malloc(sizeof(Item));
puts("Please enter name of pet:");
s_gets(temp->petname, SLEN);
puts("Please enter pet kind:");
s_gets(temp->petkind, SLEN);
temp->next = NULL;
if (AddItem(temp, pt))
puts("add pet success");
}

Problem searching in my Binary Search Tree

Problem is function bin_search. it works steady on function insert. However, it gets frozen on function search. I think if it's fine on insert, it should be fine on search, but it isn't. Here is my code...
"bst.h":
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node {
int key;
void *data;
struct Node *left, *right;
void (*destroy)(void *data);
} node;
typedef struct Tree {
node *head;
char name;
} tree;
#define key(node) node->key
#define data(node) node->data
#define left(node) node->left
#define right(node) node->right
#define destroy(node) node->destroy
#define tree_head(tree) tree->head
"functions.c":
#include "bst.h"
int bin_search(node *curr, int key, int cnt, node **found) {
cnt++; printf("cnt+\n");
if (curr == NULL) {
return -1;
} else if (curr->key == key) {
printf("curr_key = key\n"); return cnt;
}
if (curr->key < key) {
printf("curr_key < key\n");
if (curr->right == NULL) {
*found = curr;
return -(cnt + 1);
}
return bin_search(curr->right, key, cnt, found);
} else {
printf("curr_key > key\n");
if (curr->left == NULL) {
*found = curr;
return -(cnt + 1);
}
return bin_search(curr->left, key, cnt, found);
}
}
int insert(tree *root, int key, void *data, void (*destroy)(void *data)) {
if (root->head == NULL) {
node* new_node = (node *)malloc(sizeof(node));
left(new_node) = NULL; right(new_node) = NULL; destroy(new_node) = destroy; key(new_node) = key; data(new_node) = data;
tree_head(root) = new_node;
printf("created first node\n"); return 1;
}
int cnt; node **found;
if ((cnt = bin_search(root->head, key, 0, found)) < 0) {
node* new_node = (node *)malloc(sizeof(node));
left(new_node) = NULL; right(new_node) = NULL; destroy(new_node) = destroy; key(new_node) = key; data(new_node) = data;
if ((*found)->key < key) {
(*found)->right = new_node;
} else {
(*found)->left = new_node;
}
printf("created a node at %d\n", -cnt); return 1;
} else {
printf("already exists in tree"); return -1;
}
}
int search(tree *root, int key, void **data) {
if (root->head == NULL) {
printf("tree is empty\n"); return -1;
}
int cnt; node **found;
if ((cnt = bin_search(root->head, key, 0, found)) < 0) {
return -1;
} else {
if ((*found)->key < key) {
*data = (*found)->right->data;
} else {
*data = (*found)->left->data;
}
return cnt;
}
}
"main.c":
#include "bst.h"
#define MAX_NUM 8
#define MAX_LEGNTH 200
int main() {
// create a tree
tree root; root.head = NULL; root.name = 'a';
FILE *inpt = fopen("list.txt", "r"); char buffer[MAX_LEGNTH];
int count = 0;
while (fgets(buffer, MAX_LEGNTH, inpt) != NULL) {
printf("adding: %d\n", atoi(buffer)); insert(&root, atoi(buffer), buffer, NULL);
count++;
}
fclose(inpt);
int result; void **found;
result = search(&root, 2, found); printf("%d\n", result); // problem in here!!
return 0;
}
what is the problem with my 'search' function. I can't find it.
Besides the utterly non-standard use of sizeof(void), you are not providing a correct out-parameter to search. The point of the found argument is to receive the node pointer if the prospect key was discovered. This...
int cnt;
node **found; // <== LOOK HERE
if ((cnt = bin_search(root->head, key, 0, found)) < 0) {
is not the way to do that. It should be done like this:
int cnt;
node *found = NULL;
if ((cnt = bin_search(root->head, key, 0, &found)) < 0) {
// ^^^^^^
and all references to found thereafter should be through found->, not (*found)->
This mistake is made in three different places in your code. The last one is semi-broken, but still broken nonetheless.
void **found = (void *)malloc(sizeof(void));
int result = search(&root, 2, found);
printf("%d\n", result);
That should use this:
void *found = NULL;
int result = search(&root, 2, &found);
printf("%d\n", result);
Whether the rest of your code is broken I cannot say, and frankly we're not in the business of being an online-debugger. Use your local debugger tools; that's what they're for. But the items listed above are definitely a problem.

Why is index not changing after returning to parent after executing child process

I am trying to implement a simple shell with history which takes process batch files as input and execute them.
My header file head.h looks like:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
typedef struct Process{
int index;
char **args;
} Proc_t;
typedef struct historyNode{
Proc_t Process;
struct historyNode *next;
struct historyNode * prev;
} his_t;
//Function Prototypes
his_t * createNode(his_t *head, Proc_t *Process);
char** ParseString(char *buffer);
void execProcess(his_t *head, Proc_t *Process);
void HistoryBrief(his_t *head);
void HistoryFull(his_t *head);
void printProcess(Proc_t Process);
void printProcessCmd(Proc_t Process);
int isNumber(char *arg);
Proc_t *get_Process(his_t *head, int index);
Proc_t *existsInHistory(his_t *head, char **args);
Here is the main.c :
#include "head.h"
his_t * head = NULL;
int main(int argc, char ** argv)
{
int index = 1;
for(int i = 1 ; i<argc;i++)
{
char buffer[1000]; // to store the command read from file
FILE *f = fopen(argv[i],"r");
while(fgets(buffer,sizeof(buffer), f) != NULL)
{
char** currProcessArgs = ParseString(buffer);
Proc_t *currProcess = (Proc_t *)malloc(sizeof(Proc_t));
currProcess->index = index;
//printf("index of currProcess: %d\n",currProcess->index);
currProcess->args = currProcessArgs;
//printProcess(*currProcess);
if(head == NULL)
{
head = createNode(head, currProcess);
//printf("Process name:%s, head address:%p\n", head, head->Process.args[0]);
}
else
{
createNode(head, currProcess);
//printf("Process name:%s, head address:%p\n", head, head->Process.args[0]);
}
printf("\n%d index in loop\n", index);
index++;
execProcess(head,currProcess);
//index++;
}
// HistoryBrief(head);
//HistoryFull(head);
fclose(f);
}
//Ignore the while part for now
while(1)
{
char inputBuffer[1000];
puts("Please enter a command!: ");
scanf("%[^\n]%*c", inputBuffer);
//fflush(stdin);
printf("inputBuffer: %s\n",inputBuffer);
char **userCmdArgs = ParseString(inputBuffer);
if(strcmp(userCmdArgs[0],"EXEC")==0)
{
if(isNumber(userCmdArgs[1])==0)
{
Proc_t *userCmd = (Proc_t *)malloc(sizeof(Proc_t));
userCmd->index=index;
userCmd->args = userCmdArgs+1;
userCmd = existsInHistory(head, userCmd->args);
if(userCmd!=NULL)
{
puts("This Command Already exists in History!!");
// execProcess(userCmd);
}
else
{
puts("This Command doesn't exist in history. Adding it to the history");
createNode(head,userCmd);
//execProcess(userCmd);
}
}
else
{
Proc_t *userProcessWithIndex = get_Process(head, atoi(userCmdArgs[1]));
if(userProcessWithIndex==NULL)
{
puts("Command with the given index doesn't exist!!\n");
}
else
execProcess(head, userProcessWithIndex);
}
}
else if(strcmp(userCmdArgs[0], "HISTORY")==0)
{
if(strcmp(userCmdArgs[1],"BRIEF")==0)
{
printProcess(head->Process);
HistoryBrief(head);
}
else
{
HistoryFull(head);
}
}
else if(strcmp(userCmdArgs[0],"STOP")==0)
{
puts("Exiting Normally, Bye!!\n");
break;
}
}
return 0;
}
here is history.c
#include "head.h"
his_t *createNode(his_t *head, Proc_t *Process)
{
his_t * new_node = (his_t *) malloc(sizeof(his_t));
new_node->Process = *Process;
new_node->next = NULL;
new_node->prev = NULL;
if(head == NULL)
{
head = new_node;
return head;
}
else
{
his_t * temp = head;
while(temp->next != NULL)
{
temp=temp->next;
}
temp->next=new_node;
new_node->prev=temp;
return new_node;
}
}
Proc_t *existsInHistory(his_t *head, char **args)
{
his_t *temp = head;
int i = 0;
int exists = 1;
while(temp!=NULL)
{
while(args[i]!=NULL && temp->Process.args[i]!=NULL)
{
if(args[i]==temp->Process.args[i])
exists=1;
else
{
exists = 0;
break;
}
}
if(exists)
{
Proc_t *tempProc = (Proc_t *)malloc(sizeof(Proc_t));
tempProc = &(temp->Process);
return tempProc;
}
temp = temp->next;
return NULL;
}
}
Proc_t *get_Process(his_t *head, int index)
{
his_t * temp = head;
while(temp!=NULL)
{
if(temp->Process.index == index)
break;
temp=temp->next;
}
if(temp!=NULL)
{
Proc_t *procTemp = (Proc_t *)malloc(sizeof(Proc_t));
procTemp = &(temp->Process);
return procTemp;
}
else
return NULL;
}
void HistoryBrief(his_t *head)
{
his_t * temp = head;
while(temp->next!=NULL)
{
printf("Address of head: %p\n", temp);
if(temp->prev!=NULL)
printProcessCmd(temp->prev->Process);
printProcessCmd(temp->Process);
temp=temp->next;
}
}
void HistoryFull(his_t *head)
{
his_t *temp = head;
while(temp->next!=NULL)
{
printProcess(temp->Process);
temp = temp -> next;
}
}
}
Here is process.c
#include "head.h"
int isNumber(char *arg)
{
int i = 0;
while(arg[i]!='\0')
{
if(isdigit(arg[i])==0)
return 0;
i++;
}
return 1;
}
char** ParseString(char *buffer)
{
int buff_size = strlen(buffer);
if(buffer[buff_size-1]=='\n')
buffer[buff_size-1]='\0';
char **args =(char *)malloc(30*sizeof(char *));// array for storing arguments
int i = 0;
char *arg = strtok(buffer," ");
while(arg !='\0')
{
args[i] = arg;
arg = strtok(NULL," ");
i++;
}
args[i] = '\0';
puts("\n");
int k =0;
while(args[k]!=NULL)
{
printf("%s ",args[k]);
k++;
}
return args;
}
void printProcess(Proc_t Process)
{
printf("%d.",Process.index);
puts("args: ");
int i = 0;
while(Process.args[i]!=NULL)
{
printf("%s ",Process.args[i]);
i++;
}
puts("\n");
}
void printProcessCmd(Proc_t Process)
{
printf("%d.%s\n",Process.index,Process.args[0]);
}
void execProcess(his_t *head,Proc_t *Process)
{
int pid = fork();
if(pid==0)
{
printf("Currently Executing: index:%d||command:%s\n\n",Process->index, Process->args[0]);
execvp(Process->args[0],Process->args);
}
else if(pid)
{
wait(NULL);
(head->Process.index)++;
printf("index of head afgter returning to parent process: %d\n",head->Process.index);
printf("%s, cmd of head process after returning to parent\n",head->Process.args[0]);
}
else
return 0;
}
So basically my program will take input as text files containing linux commands. Each command is written on a different line.
Example file -
ls -al
echo Hello World
touch newfile.c
ps
I have created a doubly linked list for storing history of commands.
When I call HistoryBrief() It prints 4 ps instead of printing each command. Also, after calling fork, the index is changing inside the parent but not the child. Why is that??

How can I get a non-empty binary tree and print it?

I built three files, which includes MainFunc.c, AllFun.h, and OtheFunc.c.
The program happens runtime error, which print nothing. However, I need it output a tree as previous order.
I guess the problem may be that I built an empty tree, but I can't solve it.
MainFunc.c
#include "AllFun.h"
int main(int argc, char* argv[])
{
int nums[MaxSize] = { 0 };
printf("Enter value of root node: ");
for (int i = 0; i < MaxSize; ++i) {
scanf_s("%d", &nums[i]);
}
TreeNode* root = create(nums, MaxSize);
preorder(root);
return 0;
}
AllFun.h
#include <stddef.h> // NULL
#include <stdlib.h>
#include <stdio.h>
#define MaxSize 10
typedef struct node {
int data;
struct node* lchild, * rchild;
} TreeNode;
TreeNode *create(int nums[], int n);
void preorder(TreeNode *root);
OtheFunc.c
#include "AllFun.h"
TreeNode* newNode(int v) {
TreeNode* node = (TreeNode*)malloc(sizeof(TreeNode));
if (node) {
node->data = v;
node->lchild = node->rchild = NULL;
return node;
}
}
void insert(TreeNode* root, int x)
{
if (root == NULL) {
root = newNode(x);
return;
}
if (root->data < x) {
insert(root->lchild, x);
}
else {
insert(root->rchild, x);
}
}
TreeNode *create(int nums[], int n)
{
TreeNode* root = NULL; // Build a empty root node
for (int i = 0; i < n; i++) {
insert(root, nums[i]);
}
return root;
}
void preorder(TreeNode* root)
{
if (root == NULL) {
return;
}
printf("%d ", root->data);
preorder(root->lchild);
preorder(root->rchild);
}
You have to pass the node as a pointer to pointer, then the function can change the pointer:
void insert(TreeNode** root, int x)
{
if (*root == NULL) {
*root = newNode(x);
return;
}
if ((*root)->data < x) {
insert(&(*root)->lchild, x);
}
else {
insert(&(*root)->rchild, x);
}
}
Call with insert(&root, nums[i]);:
https://ideone.com/nV5q1g

cs50 pset5 unload problem - memory leakage

I am trying to solve the cs50 pset5. I am using a tries method.
I can insert word into the tries successfully. However, when i unload the memory, it fails. I am so stuck at the unload problem for a few days.
When I try the unload function, it stated that Erorr Message: double free or corruption (!prev): 0x000000000205d010 ***
It is probably due to my unload function, but i have drawn out the logic. It seems fine to me. Anyone has any idea where to amend?
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#define LENGTH 45
#define SIZE_OF_CHILD 27
typedef struct Node {
bool is_word;
struct Node* child[SIZE_OF_CHILD];
} Node;
Node* root;
Node* temp;
Node* create_node(Node* node);
void test();
int cal_key(char c);
Node* insert(const char* word);
void unload(Node* node);
int main() {
root = malloc(sizeof(Node));
if (root == NULL) {
exit(0);
}
root = create_node(root);
temp = malloc(sizeof(Node));
if (temp == NULL) {
exit(0);
}
test();
}
// **************** function to create a node *******************
Node* create_node(Node* node) {
node->is_word = false;
for (int i = 0; i < SIZE_OF_CHILD; i++) {
node->child[i] = NULL;
}
return node;
}
//************* calculate the key value ************
// Assume that the input is in lower case
int cal_key(char c) {
if (isalpha(c)) {
if (islower(c)) {
return c - 'a';
}
else {
return c + 32 -'a';
}
}
else {
return SIZE_OF_CHILD - 1;
}
}
//*************** function to insert an item in the the node ***********
Node* insert(const char* word) {
int str_len = strlen(word);
temp = root;
int key;
for (int i = 0; i < str_len; i++) {
key = cal_key(word[i]);
if (temp->child[key] == NULL) {
Node* node = malloc(sizeof(Node));
if (node == NULL) {
fprintf(stderr, "Error in creating node\n");
exit(0);
}
node = create_node(node);
temp->child[key] = node;
}
temp = temp->child[key];
}
temp->is_word = true;
return root;
}
//***************** function to unload a function ********************
void unload(Node* node) {
// This is to find the last node
for (int i = 0; i < SIZE_OF_CHILD; i++) {
if (node->child[i] != NULL) {
unload(node->child[i]);
}
free(node);
}
}
void test() {
root = insert("Peter");
unload(root);
}

Resources