copying a string in an array element of a struct - c

I have the following problem: I made this node structure
typedef struct NODE{
struct NODE *sons[1024]; //this array will be used to store children pointers
char name[255];
int leaf;
}NODE;
and this function to create a new node with a given name. The problem is that the first printf shows the right name, the second one doesn't. It seems like the for loop erases the name and I can't explain myself why...
NODE *AllocateNewNode( char *inputname) {
NODE *newnode;
newnode = (NODE *)malloc(sizeof(NODE));
memset(newnode->name, '\0', sizeof(newnode->name));
strcpy(newnode->name, inputname);
printf("node %s created\n", newnode->name); //right name in the output
int i = 0;
for (i = 0; i <= 1024; i++) {
newnode->sons[i] = NULL;
}
newnode->leaf = 1;
printf("node %s created\n", newnode->name); //no name in the output
return newnode;
}

You're writing past the end of your sons array;
Should be for (i = 0; i < 1024; i++) { since there are only 1024 elements in the array 0...1023.

Related

Random i character being printed into my string hash table despite appropriate datatypes

Can anybody explain why my hash table program for strings is just printing the letter i in the first array instead of Ben? I do not specify i anywhere so am extremely puzzled as to why this result is showing:
I have correctly set my datatypes to char with the appropriate array lengths specified, so why is it that the string is not recognised?
Code:
#include<stdio.h>
#include<stdlib.h>
#define size 7
struct node
{
char data;
struct node *next;
};
struct node *chain[size];
void init()
{
int i;
for(i = 0; i < size; i++)
chain[i] = NULL;
}
void add(char name[])
{
//create a newnode with value
struct node *newNode = malloc(sizeof(struct node));
newNode->data = name[10];
newNode->next = NULL;
//calculate hash key
char key = name[10] % size;
//check if chain[key] is empty
if(chain[key] == NULL)
chain[key] = newNode;
//collision
else
{
//add the node at the end of chain[key].
struct node *temp = chain[key];
while(temp->next)
{
temp = temp->next;
}
temp->next = newNode;
}
}
/*
* return 1, search found
* return 0, Otherwise
*/
int search(int name)
{
char key = name % size;
struct node *temp = chain[key];
while(temp)
{
if(temp->data == name)
return 1;
temp = temp->next;
}
return 0;
}
void print()
{
int i;
for(i = 0; i < size; i++)
{
struct node *temp = chain[i];
printf("chain[%d]-->",i);
while(temp)
{
printf("%c -->",temp->data);
temp = temp->next;
}
printf("NULL\n");
}
}
int main()
{
//init array of list to NULL
init();
add("Ben");
print();
printf("Searching element 10\n");
if(search(10))
printf("Search Found\n");
else
printf("Search Not Found\n");
return 0;
}
Result:
chain[0]-->i -->NULL
chain[1]-->NULL
chain[2]-->NULL
chain[3]-->NULL
chain[4]-->NULL
chain[5]-->NULL
chain[6]-->NULL
Searching element 10
Search Not Found
Syntactically your code is good.
The error is, that you call add() like this:
add("Ben");
This means that the address of a 4 character array (exactly: the address of its first member) is given to add(). The 4 characters are:
'B'
'e'
'n'
'\0'
Now in add() you read from the 11th character of the address given, at the offset of 10:
newNode->data = name[10];
This is called "out of bounds" and in Java (because you seem to know that) will throw an IndexOutOfBoundsException. But C doesn't have such checks and so the code reads whatever is there. In your example it is an 'i' by accident.

Adding node to a linked list

So I'm creating a linked list in C and adding some nodes to it that contain information. I have an if else statement where I create the linked list's head and then add nodes to it. The problem is that when I add a new node I seem to lose the old one. Not sure why this is happening or how to fix this.
Edit: I have made some updates to make it a runnable program.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stdint.h>
#include<regex.h>
int main(int argc, char argv[]) {
int head=0, i=0;
char tempCourseID[10], tempCourseGrade[10], tempCourseCH[10];
static struct LinkedList {
char *CourseName;
char *CourseGrade;
char *CourseCreditHours;
struct LinkedList *next;
} LinkedList;
static struct LinkedList *first, *savefirst, *headlist;
first = malloc(sizeof ((*first)));
savefirst = first;
headlist = first;
for(i ; i<5; i++){
printf("Enter Course name");
fgets(tempCourseID, sizeof(tempCourseID), stdin);
printf("Enter Course grade");
fgets(tempCourseGrade, sizeof(tempCourseGrade), stdin);
printf("Enter Course credit hours");
fgets(tempCourseCH, sizeof(tempCourseCH), stdin);
//checks to see if linked list head exists
if (head == 0) {
printf("No head has been found.\n");
headlist->CourseName = tempCourseID;
headlist->CourseGrade = tempCourseGrade;
headlist->CourseCreditHours = tempCourseCH;
headlist->next = NULL;
printf("A head has been created\n");
printf("A node has been added\n");
head = 1;
} else {
printf("Ahead already exists\n");
first = malloc(sizeof ((*first)));
first->CourseName = tempCourseID;
first->CourseGrade = tempCourseGrade;
first->CourseCreditHours = tempCourseCH;
first->next = NULL;
savefirst->next = first;
savefirst = first;
printf("A node has been add\n");
head = 1;
}
}
while (headlist != NULL) {
printf(" %s ", headlist->CourseName);
printf(" %s ", headlist->CourseGrade);
printf("%s \n", headlist->CourseCreditHours);
headlist = headlist->next;
}
return 0;
}
You have char tempCourseID[10] and char* CourseName
It is legal to use CourseName = tempCourseID; however tempCourseID is temporary, and so the string will be lost soon. In this case we need to allocate separate memory for CourseName, and then copy the value from tempCourseID
Use instead
CourseName = malloc(strlen(tempCourseID) + 1);//add +1 for null-character
strcpy(CourseName, tempCourseID);
//or
CourseName = strdup(tempCourseID)//shortcut!
There are problem with the linked list. You have too many variables with similar names. A linked list needs only head. You can introduce a temporary variable node for adding new nodes. If you are adding nodes to the tail, then save the last node in the list, lets call it savenode
In this example I removed fgets functions and replaced it with sprintf, that's just to make it easier to run the program and debug. You can put back fgets later.
int main(int argc, char argv[])
{
struct LinkedList
{
char *CourseName;
char *CourseGrade;
char *CourseCreditHours;
struct LinkedList *next;
};
int i;
char tempCourseName[100], tempCourseGrade[100], tempCourseCH[100];
struct LinkedList *head = NULL;
struct LinkedList *node = NULL;
struct LinkedList *savenode = NULL;
for(i = 0; i < 5; i++)
{
sprintf(tempCourseName, "CourseName %d", i);
sprintf(tempCourseGrade, "tempCourseGrade %d", i);
sprintf(tempCourseCH, "tempCourseCH %d", i);
node = malloc(sizeof(*node));
node->CourseName = strdup(tempCourseName);
node->CourseGrade = strdup(tempCourseGrade);
node->CourseCreditHours = strdup(tempCourseCH);
node->next = NULL;
if(head == NULL)
head = node;
//check savenode exists
//this will be the last node (tail) in the existing list
//get it to point to our new node
if(savenode)
savenode->next = node;
//now we have a new tail
savenode = node;
}
//walk through the list
node = head;
while(node)
{
printf("%s, %s, %s\n",
node->CourseName, node->CourseGrade, node->CourseCreditHours);
node = node->next;
}
return 0;
}

Linked List insertion in Beginning

I am trying basic creation of linked list using C. I have written the following code which is working up until first node but fails eventually on second one. I think the issue is where I am trying to display the node values in list separated by arrow(->). I think my logic is right but please correct me. Thanks in advance
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct node
{
int number;
struct node *next;
};
typedef struct node NODE;
NODE *node1, *node2, *start, *save;
int main()
{
node1 = (NODE *)malloc(sizeof(NODE));
int i = 0;
start = NULL;
for(i = 0; i < 3; i++)
{
int inf;
printf("Enter node value:");
scanf("%d", &inf);
node1->number = inf;
node1->next = NULL;
if(start == NULL)
{
start = node1;
save = node1;
}
else
{
// save=start;
// start=node1;
// node1->next=save;
node1->next = start;
start = node1;
}
while(node1 != NULL)
{
printf("%d ->",node1->number);
node1 = node1->next;
}
}
return 0;
}
The issues are
How you're allocating your nodes for insertion (i.e. save for one, you're not).
How they're placed in the list once you fix the above.
Don't cast malloc in C programs (read here for why).
Fail to check the success of your scanf invoke.
Fail to check the success of your malloc invoke
Before you get discouraged, things you did correctly:
Did not mask a node pointer in a typedef
Properly included a MCVE for review
Prospected the things you may be doing wrong.
A very simple example of iterating three values into a linked list would look something like this:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int number;
struct node *next;
};
typedef struct node NODE;
int main()
{
NODE *head = NULL, *p;
int i = 0;
for(i = 0; i < 3; i++)
{
int inf;
printf("Enter node value:");
if (scanf("%d", &inf) == 1)
{
p = malloc(sizeof *p);
if (p != NULL)
{
p->number = inf;
p->next = head;
head = p;
}
else
{
perror("Failed to allocate new node");
return EXIT_FAILURE;
}
}
else
{
// failed to read data. break
break;
}
// report current linked list
printf("%d", p->number);
for (p=p->next; p; p = p->next)
printf(" -> %d", p->number);
fputc('\n', stdout);
}
// cleanup the linked list
while (head)
{
p = head;
head = head->next;
free(p);
}
head = NULL;
return 0;
}
Input
The values 1 2 3 are input upon being prompted:
Output
Enter node value:1
1
Enter node value:2
2 -> 1
Enter node value:3
3 -> 2 -> 1
Best of luck.
You should use malloc() inside for loop.
Since it is outside, same memory is being used.
As said by Vamsi, you should use malloc to put the nodes on the heap. You also generally shouldn't cast the output of malloc, it isn't needed. And then you could play around with making a doubly-linked list, where you also have a prev pointer inside your struct.

Array of pointer to the linked list

I'm working of my assignment, in C, which to store 500 string into strings of 5 char by the mean of hash table with chaining method to fix the collision.
Hashing algorithm : to add up the ASCII value and apply the modulus operator to the result.
The hash table store the hash key generated and a pointer which points to a linked list. Each linked list has more than one element if there are more than one 5-char string that gives the same hash key.
So far this is my code. I compiled it (Codeblock) and it appears that there is no error. However the program crashed.
Please give some inputs on where did i do wrong.
#include <stdio.h>
#include <string.h>
#define SLEN 500
#define WLEN 5
#define MPRIME 73
struct Node {
char s[WLEN+1]; // array to hold the 5-letter word
int sindex; // starting index of the word
struct Node * next; // a pointer to the next word in the list
};
int searchword(char *);
int hashfunc(char *);
void build_hashtbl();
struct Node * hashtable[MPRIME] = {NULL};
char string[SLEN+1] = "thenamewasfamiliartomeonseverallevelslookingbackitwasfatethatifoundhimihadcometopeppervillebeachtocloseonasmallhousethathadbeeninourfamilyforyearsonmywaybacktotheairportistoppedforcoffeetherewasafieldacrossthestreetwherekidsinpurpletshirtswerepitchingandhittingihadtimeiwanderedoverasistoodatthebackstopmyfingercurledinthechainlinkfenceanoldmanmaneuveredalawnmoweroverthegrasshewastannedandwrinkledwithahalfcigarinhismouthheshutthemowerwhenhesawmeandaskedifihadakidoutthereisaidnoheaskedwhatiwasdoing";
int main(void) {
int index;
char query[WLEN+1];
build_hashtbl(); // prepare the hash table
printf("Enter a 5-letter word to search: ");
scanf("%s", query);
index = searchword(query);
if (index != -1)
printf("The word %s starts at index %d.\n", query, index);
else
printf("The word %s is not found.\n", query);
return 0;
}
int searchword(char * word) {
int hashval;
struct Node * lhead;
hashval = hashfunc(word);
lhead = hashtable[hashval];
while (lhead) {
if (strcmp(lhead->s,word) == 0)
return lhead->sindex;
lhead = lhead->next;
}
return -1;
}
int hashfunc(char *){
int hashval = 0;
int i = 0;
for (i = 0; i < WLEN; i++){
hashval += (int) string[i];
}
return (int) (hashval % MPRIME);
}
void build_hashtbl(){
struct Node *hashtable[MPRIME]; //already declared. put here for ease
struct Node * head = NULL;
struct Node * last = NULL;
int i = 0;
int k = 0;
int key = 0;
char sElement[WLEN+1] = {0};
for (i = 0; i <SLEN; i = i+WLEN){ //for every 5 char, find they hashtable index key
key = hashfunc(*string[i]);
for (k = 0; k <WLEN; k++){ //create a new string, sElement from the 5 letter word
sElement[k] = string[i+k];
}
if (hashtable[key] != (NULL)){ //if the hashtable element at that index is empty, STORE it in a node
hashtable[key] = head;
struct Node *new_node;
new_node = (struct Node *) malloc ( sizeof (struct Node) );
strcpy(new_node->s, sElement); //put the new 5 letter word string into the node
new_node->sindex = i; //put the starting index of this word
new_node->next = NULL; //the next pointer is set to NULL
head->next = new_node; //finally set the head node to point to this new node
last = new_node; //set the new node as the last node
}
else { //if there is already a node in the array
struct Node *new_node;
new_node = (struct Node *) malloc ( sizeof (struct Node) );
strcpy(new_node->s, sElement); //put the new 5 letter word string into the node
new_node->sindex = i; //put the starting index of this word
new_node->next = NULL; //the next pointer is set to NULL
head->next = new_node; //finally set the head node to point to this new node
last->next = new_node; //set the last node to point to thew new created node
last = new_node; //set the new node as the last node
}
}
}
Your used last and head uninitialized, so head->next and friends would segfault. In fact you don't need them at all and you don't need your if branches - just replace hashtable[key] by new_node after setting new_node->next to hashtable[key]
void build_hashtbl(){
int i = 0;
int k = 0;
int key = 0;
char sElement[WLEN+1] = {0};
for (i = 0; i <SLEN; i = i+WLEN){ //for every 5 char, find they hashtable index key
key = hashfunc(string+i);
for (k = 0; k <WLEN; k++){ //create a new string, sElement from the 5 letter word
sElement[k] = string[i+k];
}
struct Node *new_node;
new_node = (struct Node *) malloc ( sizeof (struct Node) );
strcpy(new_node->s, sElement); //put the new 5 letter word string into the node
new_node->next=hashtable[key];
new_node->sindex=i;
hashtable[key]=new_node;
}
}
Works for me.
Edit: Also needs #include <stdlib.h> (at least here)

Description is only printing out for the last one entered

I'm quite new to C and I'm trying to implement a binary tree in C which will store a number and a string and then print them off e.g.
1 : Bread
2 : WashingUpLiquid
etc.
The code I have so far is:
#include <stdio.h>
#include <stdlib.h>
#define LENGTH 300
struct node {
int data;
char * definition;
struct node *left;
struct node *right;
};
struct node *node_insert(struct node *p, int value, char * word);
void print_preorder(struct node *p);
int main(void) {
int i = 0;
int d = 0;
char def[LENGTH];
struct node *root = NULL;
for(i = 0; i < 2; i++)
{
printf("Please enter a number: \n");
scanf("%d", &d);
printf("Please enter a definition for this word:\n");
scanf("%s", def);
root = node_insert(root, d, def);
printf("%s\n", def);
}
printf("preorder : ");
print_preorder(root);
printf("\n");
return 0;
}
struct node *node_insert(struct node *p, int value, char * word) {
struct node *tmp_one = NULL;
struct node *tmp_two = NULL;
if(p == NULL) {
p = (struct node *)malloc(sizeof(struct node));
p->data = value;
p->definition = word;
p->left = p->right = NULL;
}
else {
tmp_one = p;
while(tmp_one != NULL) {
tmp_two = tmp_one;
if(tmp_one->data > value)
tmp_one = tmp_one->left;
else
tmp_one = tmp_one->right;
}
if(tmp_two->data > value) {
tmp_two->left = (struct node *)malloc(sizeof(struct node));
tmp_two = tmp_two->left;
tmp_two->data = value;
tmp_two->definition = word;
tmp_two->left = tmp_two->right = NULL;
}
else {
tmp_two->right = (struct node *)malloc(sizeof(struct node));
tmp_two = tmp_two->right;
tmp_two->data = value;
tmp_two->definition = word;
tmp_two->left = tmp_two->right = NULL;
}
}
return(p);
}
void print_preorder(struct node *p) {
if(p != NULL) {
printf("%d : %s\n", p->data, p->definition);
print_preorder(p->left);
print_preorder(p->right);
}
}
At the moment it seems to work for the ints but the description part only prints out for the last one entered. I assume it has something to do with pointers on the char array but I had no luck getting it to work. Any ideas or advice?
You're always doing a scanf into def and then passing that to your insert routine which just saves the pointer to def. So, since all of your entries point to the def buffer, they all point to whatever was the last string you stored in that buffer.
You need to copy your string and place a pointer to the copy into the binary tree node.
The problem is that you're using the same buffer for the string. Notice your struct is holding a pointer to a char, and you are passing the same char array as that pointer each time.
When you call scanf on the buffer, you are changing the data it points to, not the pointer itself.
To fix this, before assigning it over to a struct, you can use strdup. So the lines of code would become
tmp_*->definition = strdup(word);
Keep in mind that the char array returned by strdup must be freed once you are done with it, otherwise you'll have a leak.

Resources