segmentation fault when adding array to a node n-ary tree - c

I'm trying to create an N-ary tree where I have a char array ex: {A,B,C,D} to insert to a tree.
I set the root to be "/"
if the command is mkdir /A/B/C => create node A at root, then B at A and C at B. if the command is mkdir B/C/D =>create node D inside C, etc... I simplified the code below so hopefully, there won't be any typo here. Anyway, upon debugging with gdb, it looks like the upon reaching search function will give me a segmentation fault, I made the code below, I'm really sure the insert function will have the same error as well but I haven't been able to test it out yet.
head.c
#pragma once
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define len 128
#define num 128
typedef struct tree{
char name;
char type;
struct node *child, *sibbling, *parentNode;
}node;
char *baseName[64];
node *root, *cwd;
tree.c
node *createNode(node * newNode, char ch, char ty){
node *curNode = (node*)malloc(sizeof(node));
curNode->name = ch;
curNode->type = ty;
curNode->parentNode = newNode;
curNode->sibbling = curNode->child=NULL;
return curNode;
}
node * insertNode(node *parent, char name, char type){
if(parent->child == NULL){
parent->child=parent;
createNode(parent->child,name,type);
}
else{
parent->sibbling = parent;
createNode(parent->sibbling,name,type);
}
}
node *searchNode(node *curNode, char name){
if(curNode->name ==name){ <------------error here
return curNode;
}
if(name != curNode->name && curNode->sibbling != '\0'){
searchNode(curNode->sibbling, name);
}
if(name != curNode->name && curNode->child != '\0'){
searchNode(curNode->sibbling, name);
}
return 0;
}
void mkDir(){
int index = 0;
int flag =0;
int baseFlag=0;
node *pwd = root;
///// insert
while(dirName[index] !='\0'){
if(searchNode(root,dirName[index]) != NULL){ <-- error in this searchNode function //no node exist
// insertNode(pwd,"A","D"); <---this probably error too
printf("found A");
}
else{
//node exist
cwd = searchNode(root,dirName[index]);
insertNode(cwd,dirName[index],"D");
}
index++;
}
}
memset(dirName,'\0',sizeof(dirName));
}

I suspect you are passing in a null node reference to the searchNode function, hence when you try to access the property name you are getting a segfault.
I would recommend testing for and handling for null references in your code.

function createNode return type is node*.In function insertNode you must store the address of new node in some other variable of type node*.
node *r
r=createNode(parent->child,name,type);
....
...
In the function searchNode you must check
if(curnode!=NULL) {
if(curNode->name ==name){
return curNode;
}
}
In the last line you are returning 0 but return type is node*
return either NULL or (node*)0.

Related

Insert Node into BST on a loop in C

I'm trying to insert into my BST but I'm struggling with creating a loop out of it.
The code works when I insert one by one, but when I try to put it into a loop it doesn't insert correctly.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h> // for strcmp()
#include <ctype.h> // for toupper()
typedef struct BstNode{
//char name[20];
// int data;
struct BstNode* left;
struct BstNode* right;
char* name;
}BstNode;
typedef int (*Compare)(const char*, const char*); // makes comparisons easier
/* Returns pointer address to newly created node */
BstNode* createNode(char* name){
BstNode* newNode = (BstNode*)malloc(sizeof(BstNode)); // Allocates memory for the newNode
newNode->name = name; // newNode->data is like newNode.data
newNode->left= NULL;
newNode->right = NULL;
return newNode;
}
//insert node into Tree recursively
BstNode* insertNode(BstNode* node, char* name, Compare cmp){
int i;
/* char *s1 = node->name;
char *s2 = name;
printf("s1: %s, s2: %s\n", s1,s2);
i = strcmp(s1, s2); // if =1, s1 is greater
printf("i: %d\n", i); */
if(node == NULL){// if tree is empty
// printf("inside NULL\n");
node = createNode(name);
//return node;
}
else{
i = cmp (name, node->name); // sweet
if(i == -1){
// printf("inside left\n");
node->left = insertNode(node->left, name, cmp);
//return node;
}
else if(i == 1){
// printf("inside right\n");
node->right = insertNode(node->right, name, cmp);
//return node;
}
else if(i == 0 ){ //avoid duplicates for now
// printf("inside 0\n");
printf("Name is in BST\n");
return NULL;
}
}
return node;
}
BstNode* printTree(BstNode* node){
if(node == NULL){
return NULL;
}
printTree(node->left);
printf("%s\n",node->name);
printTree(node->right);
}
int CmpStr(const char* a, const char* b){
return (strcmp (a, b)); // string comparison instead of pointer comparison
}
//void Insert(Person *root, char name[20]);
int main(){
BstNode* root = NULL; // pointer to the root of the tree
char buf[100];
char option = 'a';
while(1) {
printf("Enter employee name");
scanf("%s",buf);
printf ("Inserting %s\n", buf);
root = insertNode(root, buf, (Compare)CmpStr);
printTree(root);
}
}
I can do root = insertNode(root, name, (Compare)CmpStr)
several times in code, but if I try to loop it with user input it won't insert correctly. I'm not sure if it has to do with the fact that I'm using scanf() or root not being set correctly. I've tried using fgets() as well but I'm not too sure how to use it and keep messing that up.
Any help is appreciated.
In your loop, you always pass the same buffer to your insert function; Your createNode does not copy the content of the buffer but rather stores a reference to the (always) same buffer; Hence, changing the buffer content after insert will also change the "content" of previously inserted nodes.
I'd suggest to replace newNode->name = name in createNode with newNode->name = strdup(name). This will actually copy the passed "contents" and gives your BST control over the memory to be kept. Thereby don't forget to free this memory when deleting nodes later on.

Array of linked lists added to from directory

I've been trying to create an array of linked lists. The array being size 26 each part corresponding to a letter of the alphabet. The user inputs a directory of the PC and the name of any folders or files in that directory are then added to the a linked list in the array based on what letter they start with.
How i've been trying to do it->
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <stdlib.h>
My node and its declaration:
struct node{
char data[50];
struct node *next;
};
struct node* nodeArray[26];
My alphabet:
const char* basis[26] = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
A string comparing function to check which linkedlist in the array my word goes(compares to alphabet)
int StartsWith(const char *a, const char *b)
{
if(strncasecmp(a, b, strlen(b)) == 0) return 1;
return 0;
}
Where I add the node and also where the problem is(the printf("1") is there to stop my computer from basically crashing):
void addNode(struct node **q,const char *d){
if(((*q)->data)==NULL){
*q = malloc(sizeof(struct node));
strncpy((*q)->data,d,50);
(*q)->next = NULL;
} else {
(*q)->next = malloc(sizeof(struct node));
*q = (*q)->next;
printf("1");
addNode(q,d);
}
}
The function that calls addNode, directory is a computer directory that's already been checked to exist:
void returner(char* directory){
int i;
DIR *dp;
struct dirent *ep;
char* tempD;
dp = opendir (directory);
struct node **z;
while ((ep = readdir(dp))){
tempD = (char*)malloc(50);
if ( !strcmp(ep->d_name, ".") || !strcmp(ep->d_name, "..") ){
} else {
strncpy(tempD, ep->d_name, 50);
for(i=0; i<26 ; i++){
if(StartsWith(tempD, basis[i])){
z = &nodeArray[i];
addNode(z,tempD);
print();
}
}
}
free(tempD);
}
closedir (dp);
}
Print function:
void print(){
int i;
struct node *temp;
for(i=0 ; i < 26; i++){
temp = malloc(sizeof(struct node));
temp = nodeArray[i];
while(temp != NULL){
printf("%s\n",temp->data);
temp = temp->next;
}
}
}
The program seems fine when adding the first node to a spot on the array such as "aaa.txt" "bbb.txt" "ccc.txt" "ddd.txt", but once a second is attempted to be added like a "ccd.txt" after a "ccc.txt" exists when it keeps going forever or until the pc crashes
You're not checking the right value in your addNode for finding the list insertion point.
Pointer-to-pointer enumeration through a linked list is frequently used to walk from the head pointer to the last next pointer in the list, each time holding the address of the said-pointer. When you reach one that is NULL (which will be head in the case of an empty list), you stop, and you can use your pointer-to-pointer via dereference to assign your new node address.
If you want to insert on the tail, the way to do it would be something like this:
#define DATA_MAX_LEN 50
void addNode(struct node **q,const char *d)
{
// assumes a null-terminated linked list
while (*q)
q = &(*q)->next;
*q = malloc( sizeof **q );
// ensures truncation and termination
strncpy((*q)->data,d,DATA_MAX_LEN-1);
(*q)->data[ DATA_MAX_LEN-1] = 0;
// make sure we terminate the list at our new node
(*q)->next = NULL;
}
Invoked from your updated returner function like this:
void returner(char* directory)
{
DIR *dp = opendir (directory);
if (dp)
{
struct dirent *ep;
while ((ep = readdir(dp)))
{
// skip parent and self symbolic links
if (ep->d_name[0] == '.' && (ep->d_name[1] == 0 || (ep->d_name[1] == '.' && ep->d_name[2] == 0)))
continue;
for(int i=0; i<26 ; i++)
{
if(StartsWith(ep->d_name, basis[i]))
addNode(nodeArray+i, ep->d_name);
}
}
closedir (dp);
}
}

Using a Binary Tree

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
typedef struct node_{
int val;
struct node_ *left;
struct node_ *right;
}node;
node* insert(node* root,int val);
void inorder(node* root);
int main(void)
{
int i;
int item;
node* root = NULL;
srand(time(NULL));
for( i = 0; i < 10; i++)
{
item = rand()%15;
insert(root,item);
}
inorder(root);
return 0;
}
node* insert(node* root,int val)
{
if(root == NULL)
{
root = malloc(sizeof(node));
if(root!= NULL)
{
(root)->val = val;
(root)->left = NULL;
(root)->right = NULL;
}
else
printf("%d not inserted. No memory available.\n",val);
}
else
{
if(val < (root)->val)
{
insert((root->left),val);
}
if(val>root->val)
{
insert(((root)->right),val);
}
}
}
void inorder(node* root)
{
printf("%p",root);
if(root != NULL)
{
inorder(root->left);
printf("%3d",root->val);
inorder(root->right);
}
}
I am trying to create a binary tree and print out the values in order. However when I run this code the printf of the address prints out nil obviously meaning that my tree is empty so the printf and recursion below does not run. I cannot figure out where I went wrong, any suggestions or answers would be appreciated because I can't figure out why the root would be null after calling all of those inserts in main.
You pass root as a parameter to insert() (which says it is going to return something but doesn't). Inside insert you malloc your node and assign it to the local variable root. Nothing you ever do makes it out of the insert function.
Try returning something from insert, or using a global root.
As #JoshuaByer hints in the comments below, another approach is to make your insert method "pass by reference" so it can effectively modify what was passed to it.
void insert(node** rootp,int val)
{
if(*rootp == NULL)
{
*rootp = malloc(sizeof(node));
}
/* and so on */
If you don't understand what this is saying, google "Pass by reference in C" and I'm positive you'll get some good information.
In main() after declaring and initializing root (node* root = NULL;) you're never assigning it. In order to fix you should probably change the lin insert(root,item); to root = insert(root,item);.
Also note that although insert is defined as returning node * it does not return any value.

Inserting an Element to a Linked List

I am working for a C exam and while trying to insert an element to a linked list, I am encountering with a runtime problem. My only purpose is adding 4 elements to list and then printing the list. However, it gives an error. I already looked some insertion codes and my code seems right. Can't see the error. Any assistance would be appreciated.
#include <stdio.h>
#include <stdlib.h>
struct ders{
char kod;
struct ders *next;
}*header;
typedef struct ders Ders;
void add(Ders*,Ders*);
void print(Ders*);
int main(void)
{
header = NULL;
Ders *node = NULL;
int i = 0;
char c;
while(i<4)
{
scanf("%c",&c);
node = (Ders*)malloc(sizeof(Ders));
node->kod = c;
node->next = NULL;
add(header,node );
i++;
}
print(header);
return 0;
}
void add(Ders *header, Ders *node)
{
if(header == NULL){
header = node;
header->next = NULL; }
else{
node->next = header;
header = node;
}
}
void print(Ders *header)
{
Ders *gecici = header;
while(gecici != NULL){
printf("%c\n",gecici->kod);
gecici = gecici->next;
}
}
As nihirus stated,
"The pointer is passed by value. Thus you can change the memory it points but you can't change the actual pointer, i.e. make it point to something else."
Your modification resulted in error *header is not member of struct
because
->
has a higher precedence than
*
Try using
(*header)->next = NULL
instead.
C operator precedence:
http://www.difranco.net/compsci/C_Operator_Precedence_Table.htm

Pointer trouble creating binary trees

I am creating a binary tree from a bitstring in c. ie 1100100 creates a tree:
1
/ \
1 1
I decided to use a recursive function to build this tree however i keep getting the error
Debug assertion failed...
Expression : CrtIsValidHeapPointer(pUserData)
here is a fragment of my code
typedef
struct Node {
char key;
struct Node *left;
struct Node *right;
} Node;
char string[1000];
int i = 0;
void insertRecursivePreorder(Node **node)
{
Node* parent = *node;
if(string[i] == '0')
{
parent = NULL;
i++;
}
else
{
Node *newn = (Node*)malloc(sizeof(Node));
newn->key = string[i];
parent = newn;
i++;
insertRecursivePreorder(&newn->left); //errors occur here
insertRecursivePreorder(&newn->right); //errors occur here
free(newn);
free(parent);
}
}
int main(void)
{
void printTree(Node* node);
Node* root = NULL;
scanf("%s", string);
insertRecursivePreorder(&root);
//... do other junk
}
i was wondering why this error comes about and what i can do to fix it.
The immediate problem is likely to be calling free on a pointer twice. In insertRecursivePreorder, you set parent to newn, and then call free on both. As an example of this, the following program fails (but works if you comment out one of the free(..)s):
#include <stdlib.h>
int main() {
int *a = malloc(sizeof(int)),
*b = a;
free(a);
free(b);
return 0;
}
However, there are several problems with your logic here. You should only call free when you have completely finished with the pointer, so if you are using your tree later you can't free it as you construct it. You should create a second function, recursiveDestroyTree, that goes through and calls free on the tree (from the bottom up!).
And, you probably want *node = newn rather than parent = newn, since the latter is the only one that actually modifies node.
(You could also change your function to return a Node * pointer, and then just go:
root = insertRecursivePreorder();
and
newn->left = insertRecursivePreorder();
newn->right = insertRecursivePreorder();
instead of trying to keep track of pointers to pointers etc.)
(Furthermore, on a stylistic point, using global variables is often bad practice, so you could have your insertRecursivePreorder take int i and char * string parameters and use them instead of global variables.)
The problem was: you were never assigning to the double pointer in 'insertRecursivePreorder', so root always stayed NULL.
#include <stdio.h>
#include <stdlib.h>
typedef
struct Node {
char key;
struct Node *left;
struct Node *right;
} Node;
/* slightly changed the syntax for the str
** ; now '.' indicates a NULL pointer, values represent themselves.
*/
char *string = "12..3.." ;
/* Removed the global index 'i' */
void printTree(Node* node, int level);
unsigned insertRecursivePreorder(Node **pp, char *str);
unsigned insertRecursivePreorder(Node **pp, char *str)
{
unsigned pos =1;
if (!*str) { *pp = NULL; return 0; } /* safeguard for end of string */
if (*str == '.') { *pp = NULL; return pos; }
*pp = malloc(sizeof **pp);
(*pp)->key = *str;
pos += insertRecursivePreorder(&(*pp)->left, str+pos);
pos += insertRecursivePreorder(&(*pp)->right, str+pos);
return pos;
}
void printTree(Node* node, int level)
{
unsigned pos,len;
len = level> 0 ? level : -level;
for (pos =0; pos < len; pos++) putchar (' ');
if (!level) printf ("Root=");
else if (level<0) printf ("Left=");
else printf ("Right=");
if (!node) { printf( "Null\n" ); return; }
printf("Key=%c\n", node->key );
printTree(node->left, -(len+1) ) ;
printTree(node->right, len+1) ;
}
int main(void)
{
Node *root = NULL;
unsigned result = 0;
result = insertRecursivePreorder(&root, string);
printf( "Result=%u\n", result);
printTree(root, 0);
return 0; printTree(root, 0);
}
Output:
Result=7
Root=Key=1
Left=Key=2
Left=Null
Right=Null
Right=Key=3
Left=Null
Right=Null

Resources