Tokenizing elements and storing them in an n-ary tree - c

My goal is to tokenize the strings using delimiter '.' and then store them in the form of n-ary tree, with successive children containing the tokenized elements. I have problem storing the elements in an array of strings. And hence not able to store them. I also want to ask functioning of strtok() in C.
Here is my code
int main()
{ int opt,n;
printf("Option,then number of cases:\n");
scanf("%d %d",&opt,&n);
node *root=createNode("root");
char **words=arr_strings(size,n);
char *dns_word=malloc(sizeof(char)*size);
char *app=malloc(sizeof(char)*size);
app[0]='.';
char *dup=malloc(sizeof(char)*size);
char *store=malloc(sizeof(char)*size);
for(int i=0;i<n;i++)
{printf("Word %d: ",i+1);
scanf("%s",words[i]);
*dup=*app;
strcat(dup,words[i]);
strcpy(words[i],dup);
strcat(words[i],app);
*store=*words[i];
printf("Word %d:%s\n",i,words[i]);
int j=0;
dns_word=strtok(words[i],".");
node *temp=createNode(dns_word);
while(dns_word!=NULL){
if(i==0)
{//printf("Entered one child condition\n");
if(j==0)
{root->child=temp;
}
else
{
temp->child=createNode(dns_word);
temp->children++;
temp=temp->child;
}
}
else
{
//printf("Entering else of inserting loop\n");
//printf("dns_word:%s\n",dns_word);
int t=root->children;
node* copy=root->child;
for(int j=1;j<root->children;j++)
{copy=copy->next;
}
if(j==0)
{copy->next=temp;copy->children++;}
else
{
temp->child=createNode(dns_word);
temp->children++;
temp=temp->child;
}
}
dns_word=strtok(NULL,".");
j++;
}
//printf("Word %d:%s\n",i,words[i]);
root->children++;
}
//Ignore this
printf("Root,child:%s\n",root->child->word);
printf("Root,child,next:%s\n",((root->child)->next)->word);
//print(root->child);
return 0;
}
The structure of the node is provided here.
struct node{
char *word;
int children;
struct node* child;
struct node* next;
};
typedef struct node node;
The createNode function is as follows:
node* createNode(char *word)
{
node* new=malloc(sizeof(node));
new->word=word;
new->child=NULL;
new->next=NULL;
new->children=0;
return new;
}

Related

How to delete a word from tree dictionnary in C?

I've implemented a dictionnary in C using tree, this tree stores a word and its definition as followed:
As you can see, some words are sharing same letters.
But now i'd like to implement a delete function but don't know how to proceed ... I know that I should begin to delete the end of the word ...
Here is my code, thank you for your future help !
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _noeud{
char *value;
struct _noeud *child[26];
}noeud_t;
typedef struct tree{
node_t root;
}Tree;
Tree dict;
int getPos(char letter){
char alpha[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'};
int i;
for(i=0;i<strlen(alpha);i++){
if(alpha[i]==letter){
return i;
}
}
return -1;
}
void addWord(node_t *node, char *word, char *def){
int i;
for(i = 0; i < strlen(word);i++){
int letter=getPos(word[i]);
if(letter==-1){
printf("Unknown letter... \n");
}
node_t *parent = node;
node = node->child[letter];
if(!node){
node = malloc(sizeof(node_t));
parent->child[letter]=node;
}
}
node->value = malloc(strlen(def)+1);
strncpy(node->value,def,strlen(def)),
printf("Word %s added to dictionnary.\n",word);
fflush(stdin);
}
void findWord(node_t *node, char *word){
printf("Looking for word %s \n",word);
int i;
for(i=0;i<strlen(word);i++) {
int letter = getPos(word[i]);
if(NULL ==node->child[letter]){
printf("Unknown word ...\n");
return;
}
else{
node = node->child[letter];
}
}
printf("Word found, its definition is : %s\n",node->value);
}
void deleteWord(node_t *node, char *word){
int i=0;
for(i=0;i<strlen(word);i++) {
//...
}
printf("Word deleted !\n");
}
int main(){
addWord(&dico.root,"dog","it's an animal");
addWord(&dico.root,"pineapple","it's a fruit");
addWord(&dico.root,"car","something to drive");
findWord(&dico.root,"dog");
findWord(&dico.root,"car");
findWord(&dico.root,"pineapple");
deleteWord(&dico.root,"pineapple");
return 0;
}
I can give you an idea on how to solve it, but sorry I didn’t write the code.
So from your code, I can see that you have findWord function, if that works perfectly then use it inside your delete go find the word at this stage you’re pointing to it now you have to think of three possibilities.
If the word that will be deleted doesn’t have any child then delete it with no more complication.
If the word that will be deleted has a single child then make the parent of the word point to the word’s child.
If the word that will be deleted has more than one child then replace the word with one of the children and then delete it.
I hope this will help you

find function in linked list in c programming

I wanna write a program about linked list that gets a number and if the number was equal to the one of the nodes' data , gives the number of that node .
like the datas in 3 nodes are
123
56
78
and it gets a number like 56 and its equal to the second node's data so the output should be 2.
#include<stdio.h>
#include<stdlib.h>
struct node{
int data;
node *next;
};
node* cnode();
void find(node *first,int i,int d);
int main()
{
node *first,*last;
int n,i,x,d;
printf(" How many nodes ?\t");
scanf("%d",&x);
for(i=1;i<=x;i++){
last=cnode();
last->next=first;
first=last;
}
printf("\n enter a particular data:\t");
scanf("%d",&d);
printf("\n number of the particular node:\t");
find(first,i,d);
}
void find(node *first,int i,int d){
int count=0;
while (first != NULL)
{
if (first->data == d)
count++;
first = first->next;
}
if(count != 0){
printf("%d",count);
}
if(count == 0){
printf("\n NOT FOUND ! ");
}
}
According to the C Standard the function main without parameters shall be declared like
int main( void )
Secondly this declaration of the structure
struct node{
int data;
node *next;
};
is not a valid C declaration.
You should write
struct node{
int data;
struct node *next;
};
typedef struct node node;
or
typedef struct node{
int data;
struct node *next;
} node;
You have to initialize at least node first with NULL. Otherwise the program will have undefined behavior.
node *first = NULL,*last;
The parameter i is not used within the function find. So it may be removed.
void find(node *first, int d);
The function definition can look at least like
void find( node *first, int d )
{
int count = 0;
while ( first != NULL && first->data != d )
{
first = first->next;
++count;
}
if ( first != NULL )
{
printf("%d",count);
}
else
{
printf("\n NOT FOUND ! ");
}
}

Queue of Strings in C

I am trying to edit this program. Right now the users enters symbols and I want to make it work with Strings.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
char data;
struct Node *next;
};
struct queue
{
struct Node *top;
struct Node *bottom;
}*q;
void Write(char x)
{
struct Node *ptr=malloc(sizeof(struct Node));
ptr->data=x;
ptr->next=NULL;
if (q->top==NULL && q->bottom==NULL)
{
q->top=q->bottom=ptr;
}
else
{
q->top->next=ptr;
q->top=ptr;
}
}
char Read ()
{
if(q->bottom==NULL)
{
printf("Empty QUEUE!");
return 0;
}
struct Node *ptr=malloc(sizeof(struct Node));
ptr=q->bottom;
if(q->top==q->bottom)
{
q->top=NULL;
}
q->bottom=q->bottom->next;
char x=ptr->data;
free(ptr);
return x;
}
int main()
{
q= malloc(sizeof(struct queue));
q->top=q->bottom=NULL;
char ch='a';
printf("NOTE: To stop the entry, please enter 'q'!\n\n Enter a String: \n");
while(ch!='q')
{
scanf("%c",&ch);
Write(ch);
}
printf("\nThe entered String:\n\n");
while(q->bottom!=NULL)
{
ch=Read();
printf("%c",ch);
}
printf("\n\n");
system("PAUSE");
return 0;
}
So I am editing it like this (the code below) and I get error "[Error] incompatible types when assigning to type 'char[10]' from type 'char *'"
#include <stdio.h>
#include <stdlib.h>
struct Node
{
char data[10];
struct Node *next;
};
struct queue
{
struct Node *top;
struct Node *bottom;
}*q;
void Write(char x[10])
{
struct Node *ptr=malloc(sizeof(struct Node));
ptr->data=x;
ptr->next=NULL;
if (q->top==NULL && q->bottom==NULL)
{
q->top=q->bottom=ptr;
}
else
{
q->top->next=ptr;
q->top=ptr;
}
}
char Read ()
{
if(q->bottom==NULL)
{
printf("Empty QUEUE!");
return 0;
}
struct Node *ptr=malloc(sizeof(struct Node));
ptr=q->bottom;
if(q->top==q->bottom)
{
q->top=NULL;
}
q->bottom=q->bottom->next;
char x=ptr->data;
free(ptr);
return x;
}
int main()
{
q= malloc(sizeof(struct queue));
q->top=q->bottom=NULL;
char ch][10]='a';
printf("NOTE: To stop the entry, please enter 'q'!\n\n Enter a String: \n");
while(ch!='q')
{
scanf("%c",&ch);
Write(ch);
}
printf("\nThe entered String:\n\n");
while(q->bottom!=NULL)
{
ch=Read();
printf("%c",ch);
}
printf("\n\n");
system("PAUSE");
return 0;
}
I can't solve this problem, so I would love to get some help...
You can't assign to an array, but you can copy to it.
To copy a string use strcpy:
strcpy(ptr->data, x);
Or since you have a limited array, maybe use strncpy:
strncpy(ptr->data, x, sizeof(ptr->data) - 1);
ptr->data[sizeof(ptr->data) - 1] = '\0';
For strncpy it will not add the terminating '\0' character if the source is equal or longer than the specified length, so we have to make sure that the string is properly terminated.

What is wrong with my array of linked lists implementation as all elements get over-written?

I'm trying to implement a hash table as an array of linked lists. Currently I'm trying to have a simple hash table where the key is the index of the array and value is a singly linked list for implementing chaining.
This is the code that I've written so far:
#include<stdio.h>
#include<stdlib.h>
struct Node
{
int value;
struct Node *next;
};
struct Node *hashtable[7];
int empty(int index)
{
if(hashtable[index]==NULL)
return 0;
return 1;
}
void addNode(int frame,struct Node **iter)
{
if(*iter==NULL)
*iter=malloc(sizeof(struct Node));
else
{
while((*iter)->next != NULL)
(*iter)=(*iter)->next;
(*iter)->next=malloc(sizeof(struct Node));
(*iter)=(*iter)->next;
}
(*iter)->value=frame;
(*iter)->next=NULL;
}
void print()
{
int i;
struct Node **iter;
for(i=0;i<7;i++)
{
iter=&hashtable[i];
while(*iter !=NULL)
{
printf("%d%s%d\n",(*iter)->value,"--",i);
(*iter)=(*iter)->next;
}
}
}
int main()
{
int i=0,count=7;
for(i=0;i<7;i++)
hashtable[i]=NULL;
i=empty(1);
printf("%d",i);
do
{
printf("Enter no:\n");
scanf("%d",&i);
struct Node** temp;
temp=&hashtable[i-1%7];
addNode(rand(),temp);
count--;
print();
} while(count > 0);
return 0;
}
When I'm calling print, I can only see one element added to one particular index, which is the last element that was added, what am I doing wrong here?
void add_node(int frame,struct Node **iter)
{
/* find (pointer to) NULL pointer at end of chain */
for ( ; *iter; iter = &(*iter)->next ) {;}
*iter = malloc(sizeof **iter );
(*iter)->value = frame;
(*iter)->next = NULL;
}

can my code for reversing link list be further enhanced

Here is my program which creates a link list and also reverses it.
#include<stdio.h>
#include<stdlib.h>
struct node {
int data;
struct node *next;
};
struct node *list=NULL;
struct node *root=NULL;
static int count=0;
struct node *create_node(int);//function to create node
void travel_list(void);
void create_list(int);
void reverse_list(void);
int main()
{
int i, j, choice;
printf("Enter a number this will be root of tree\n");
scanf("%d", &i);
create_list(i);
printf("Enter 1 to enter more numbers \n 0 to quit\n");
scanf("%d", &choice);
while (choice!=0){
printf("Enter a no for link list\n");
scanf("%d",&i);
// printf("going to create list in while\n");
create_list(i);
travel_list();
printf("Enter 1 to enter more numbers \n 0 to quit\n");
scanf("%d", &choice);
}
printf("reversing list\n");
reverse_list();
travel_list();
}
// end of function main
void create_list (int data)
{
struct node *t1,*t2;
//printf("in function create_list\n");
t1=create_node(data);
t2=list;
if( count!=0)
{
while(t2->next!=NULL)
{
t2=t2->next;
}
t2->next=t1;
count++;
}
else
{
root=t1;
list=t1;
count++;
}
}
struct node *create_node(int data)
{
struct node *temp;
temp = (struct node *)malloc(sizeof(struct node));
temp->data=data;
temp->next=NULL;
// printf("create node temp->data=%d\n",temp->data);
// printf("the adress of node created %p\n",temp);
return temp;
}
void travel_list(void )
{
struct node *t1;
t1=list;
printf("in travel list\n");
while(t1!=NULL)
{
printf("%d-->",t1->data);
t1=t1->next;
}
printf("\n");
}
void reverse_list(void)
{
struct node *t1,*t2,*t3;
t1=list;
t2=list->next;
t3=list->next->next;
int reverse=0;
if(reverse==0)
{
t1->next=NULL;
t2->next=t1;
t1=t2;
t2=t3;
t3=t3->next;
reverse++;
}
while(t3!=NULL)
{
t2->next=t1;
t1=t2;
t2=t3;
list=t1;
travel_list();
t3=t3->next;
}
t2->next=t1;
list=t2;
}
Above is a fully working code.
I want to know if there can be further enhancement to the above code?
Make your indentation and whitespace usage consistent
Use meaningful identifiers rather than t1, t2 and t3
Make the data member a generic type, for example void * rather than int.
Don't use global variables, pass struct node * pointers to your functions.

Resources