I am just learning c with the cs50 course and I just got introduced to pointers and data structures (It is very confusing please help). So I got a project where I need to make a hash table and I started first by trying to add some nodes to the zero index of the list instead of going for hash table right away and for some reason I am getting a segmentation fault while adding the node to the list. Its on line 31 (which is n->next = table[0]->next;) I am not able to understand why is this happening. Someone please help and thanks in advance
LoL I just forgot to add the code
Here It Is
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(void)
{
typedef struct node
{
char *word;
struct node *next;
} node;
const unsigned int N = 10;
node *table[N];
for (int i = 0; i < 10; i++)
{
table[i] = NULL;
}
char *words[] = {"Hell", "Sup", "Brain", "Greek", "Mother", "Flip", "Poster", "Dark", "Apple", "Kandy"};
for (int i = 0; i < 10; i++)
{
char *wordle = words[i];
node *n = malloc(sizeof(node));
n->word = wordle;
n->next = table[0]->next;
table[0]->next = n;
printf("%s\n", table[0]->next->word);
}
}
You are initializing all table elements to NULL, and later you attempt to access the first (null) element: table[0]->next. This will result in dereferencing a null pointer, hence the segmentation fault you got.
What you need to do is allocating a node for each table entry:
for (int i = 0; i < N; i++) // You didn't make N constant for no reason, did you?
{
table[i] = malloc(sizeof(node));
}
Edit:
You can improve/optimise your code by avoiding repetitive calls to malloc() (as #Lundin suggested):
node* table = calloc(N, sizeof(node));
Your code has a few issues.
After setting all values to NULL you never assign to the elements in table making table[0]->next; an invalid access.
Your code seems to initialize your array of lists.
Therefore you should assign all elements, not only table[0].
You don't terminate the lists.
Not causing your problem but if your table has N element, use N as limit for your look instead of magic number 10.
A fixed version could look like this:
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node
{
char *word;
struct node *next;
} node;
int main(void)
{
const unsigned int N = 10;
node *table[N];
for (int i = 0; i < N; i++)
{
table[i] = NULL;
}
char *words[] = {"Hell", "Sup", "Brain", "Greek", "Mother", "Flip", "Poster", "Dark", "Apple", "Kandy"};
for (int i = 0; i < N; i++)
{
char *wordle = words[i];
node *n = malloc(sizeof(node));
n->word = wordle;
n->next = NULL
table[i] = n;
printf("%s\n", table[0]->word);
}
}
Related
I was trying to make a simple Link List struct but for some reason when I tested freeing up the data in the LL it would give me an invalid pointer error. Can anyone explain why?
#include <stdio.h>
#include <stdlib.h>
void add();
typedef struct node{
char* data;
struct node* next;
} node;
node** n;
int main(int argv, char** argc){
n = (node**)malloc(sizeof(node*)*10);
int i;
for(i = 0; i < 10; i++){
n[i] = NULL;
}
add();
free(n[0]->data);
return 0;
}
void add(){
char* temp = (char*)malloc(sizeof(char)*4);
temp = "Meh\0";
n[0] = (node*)malloc(sizeof(node));
n[0]->data = temp;
}
char* temp = (char*)malloc(sizeof(char)*4);
temp = "Meh\0";
Your assignment to temp is the culprit, as that sets it to point to the static character string "Meh\0", which it not yours to free. Your malloc has no effect in this case, as you immediately replace it to point to static data instead. Use memcpy or similar if you want to copy the data into the memory allocated by malloc.
I am having an issue with copying the contents of the character array in a linked list to a regular array of characters. I have an issue with a segmentation fault that I am not sure why.
The program that I have created works when the character array in the linked list is only one character, but it does not work when it is greater than 1. The main issue occurs on line 62 ("array[index] = p -> word[count]"). I have tried using strcpy to copy each index of it into the character array but that as well produced an error that reads: "passing argument 2 of ‘strcpy’ makes pointer from integer without a cast".
However, when I use an assignment statement, I just get a segmentation fault. I am not sure why because I feel I've created enough memory that should be able to hold the contents of the linked list for the array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
char word[100];
struct node *next;
} ListNode;
int main ()
{
ListNode * head = NULL;
ListNode * tail = NULL;
for (int count = 0; count < 5; count++)
{
ListNode * temp = malloc (sizeof (*temp));
strcpy(temp -> word, "Hi");
temp -> next = NULL;
if (tail == NULL)
{
head = temp;
tail = temp;
}
else
{
tail->next = temp;
tail = temp;
}
}
char array[999]; // array that will hold the characters in the linked list
ListNode * p = head; //position of the current node
int count;
int index = 0;
// while p is still a node in the list
while(p != NULL)
{
if((int) strlen(p -> word) > 1) // checks if the string is longer than one character
{
count = 0; // initializes count as 0
while(count < (int) strlen(p -> word)) // counts how many characters are in the string
{
array[index] = p -> word[count]; // assings the words into charater array
count++; // increments the count
index++; // changes the index
}
}
else
{
array[index] = p -> word[0]; // copies p-word to array
index++; // changes the index in the array
p = p -> next;
}
}
return 0;
}
As mentioned before, the program works whenever the character array in the linked list is only 1, but a segmentation fault is produced when the number is greater than 1. Please let me know what I need to correct in this program. Thank you.
simplify your loops; for-loops allow you to keep the loop-machinery on one line
avoid special cases; there is nothing special about a one-char string
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
char word[100];
struct node *next;
} ListNode;
int main ()
{
ListNode * head = NULL;
ListNode * tail = NULL;
ListNode * p ;
int count;
int index ;
char array[999]; // array that will hold the characters in the linked list
for (count = 0; count < 5; count++)
{
ListNode * temp = malloc (sizeof *temp);
strcpy(temp->word, "Hi");
temp->next = NULL;
if (!tail) { head = temp; tail = temp; }
else { tail->next = temp; tail = temp; }
}
count=0;
for(p=head;p; p=p->next) { // walk the linked list
for(index=0; p->word[index]; index++) { // walk the string
array[count++] = p->word[index];
}
}
array[count++] = 0; // terminate
printf("%s\n", array);
return 0;
}
I'm dealing with implementing a hash table. My understanding of a hashtable is that is that to have an array like table where you're able to access the elements quickly by getting the hash value and modding it by the table size. So my initial thought was declaring
Node *hTable [100];
where
typedef struct node {
char *s;
int value;
} Node;
and going to the index of the array and malloc a new element that belongs there. But, the problem is that I need to grow my table.
So, my question is, how would I make a dynamic table, but access it like an array? (e.g table[i]).
I know that you need to call something like
Node *table = (Node*)malloc(sizeof(Node)*size);
which lets you access it like a table table[i] =... but if I did that, I can't declare a new Node in the index of the table
table[i]=(Node*)malloc(sizeof(Node));
Here's a code that I've been testing with (getting seg fault) to better give a view of the problem:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 typedef struct node {
5 int data;
6 struct node *next;
7 } Node;
8
9
10 void main() {
11 Node **list;
12 *list = (Node*)malloc(sizeof(Node)*10);
13 for (int i = 0; i < 10; i++) {
14 list[i] = (Node*)malloc(sizeof(Node)); //problem here?
15 list[i]->data = i;
16 list[i]->next = NULL;
17 }
18 printf("printing...\n");
19 for (int i = 0; i < 10; i++) {
20 printf("%d ", list[i]->data);
21 }
22 }
Your problem is how you allocate space for list. list is uninitialized and does not point to valid memory, you must allocate space for it first, and then allocate space for each element:
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
} Node;
int main() //return type of main is int
{
Node **list;
list = malloc(10 * sizeof *list); //allocate memory for list not *list, also no need to cast return value of malloc.
for (int i = 0; i < 10; i++)
{
list[i] = malloc(sizeof *list[i]); //allocate space for each element.
list[i]->data = i;
list[i]->next = NULL;
}
printf("printing...\n");
for (int i = 0; i < 10; i++)
{
printf("%d ", list[i]->data);
}
return 0;
}
It doesn't need to be an array of pointers, you can simply make an array of nodes, with:
Node *list = malloc(sizeof *list * count);
Then you can access list[i].s and list[i].value.
When you want to grow the table, you use realloc():
new_list = realloc(list, sizeof *list * new_count);
if (new_list) {
list = new_list;
} else {
// report allocation failure
}
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} Node;
int main() {
// just initialize it this way ( previous was undefined behavior, dereferencing an initialize pointer)
Node **list= malloc(sizeof(Node*)*10);
for (int i = 0; i < 10; i++) {
list[i] = malloc(sizeof(Node*)); //problem here?
list[i]->data = i;
list[i]->next = NULL;
}
printf("printing...\n");
for (int i = 0; i < 10; i++) {
printf("%d ", list[i]->data);
}
}
I am trying to create a Hash Map in C. Below is the code. When I try to
assign value to the elements of Darray ( each of which is a pointer to a Node) I am getting a segmentation fault ( i.e. at line 23 and24). Could anybody help in pointing out where am I going wrong.
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node* next;
}Node;
typedef struct Map{
struct Node** Darray;
} Map;
#define SIZE 10
int main()
{
int i=0;
Map* M = malloc(sizeof(Map));
M->Darray = (struct Node**)malloc(sizeof(Node*)*SIZE);
for (i =0;i < SIZE;i++){
M->Darray[i]->data =0;
M->Darray[i]->next =NULL;
}
}
You allocate space for SIZE pointers to Node, but don't initialize these in any way, so when you access M->Darray[i] in M->Darray[i]->data you get segmentation fault because value of M->Darray[i] has not been set.
You need to allocate space for each node before using it:
for (i = 0; i < SIZE; i++) {
M->Darray[i] = malloc(sizeof(Node));
M->Darray[i]->data = 0;
M->Darray[i]->next = NULL;
}
Depending on your needs, you could also change Darray to be an array of nodes instead of node pointers, so you can allocate space for all nodes at once:
struct Node* Darray;
...
M->Darray = malloc(sizeof(Node) * SIZE);
for (i = 0; i < SIZE; i++) {
M->Darray[i].data = 0;
M->Darray[i].next = NULL;
}
I wrote a piece of code to handle dynamic arrays. Idea was to use array of struct pointers, where the last member of array is NULL. Slight variation of code I wrote is below (using integers and not structures).
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
void list_add(int **list, int* value) {
for(int i = 0; true; i++) {
if(list[i] == NULL) {
list = realloc(list, (i+2) * sizeof(int*));
list[i] = value;
list[i+1] = NULL;
break;
}
}
}
void list_init(int **list) {
int* x;
for(int i = 0; i < 100; i++) {
x = malloc(sizeof(int));
*x = i;
list_add(list, x);
}
}
int main() {
int** l = malloc(sizeof(int*));
l[0] = NULL;
list_init(l);
}
While debugging, I discovered that only first 3 integers are added to the list. I can't seem to figure out why is this happening. Any ideas?
The problem is that the call to realloc() in list_add() potentially frees the memory block *list and allocates another. list_add updates its list pointer, but it does not return the updated pointer to the caller, list_init(); list_init()'s list pointer is potentially a pointer to the recently-freed memory block.
To fix this code, list_add() and list_init() need to be able to "return" the updated list pointer:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
void list_add(int ***p_list, int *value) {
int **list = *p_list;
int i;
for(i = 0; true; i++) {
if(list[i] == NULL) {
list = realloc(list, (i+2) * sizeof(int*));
list[i] = value;
list[i+1] = NULL;
break;
}
}
*p_list = list;
}
void list_init(int ***p_list) {
int **list = *p_list;
int *x;
int i;
for(i = 0; i < 100; i++) {
x = malloc(sizeof(int));
*x = i;
list_add(&list, x);
}
*p_list = list;
}
int main() {
int **list = malloc(sizeof(int*));
list[0] = NULL;
list_init(&list);
int **l = list;
for (; *l != NULL; ++l) {
printf("%d\n", **l);
}
}
http://codepad.org/iGcSaJOR
EDIT
In this case of dynamic arrays the way you have told will not make anything better, the code will complicate only. For each addition of integer you have used realloc trying aggressively to save memory, but this will take more time while execution. Why not allocate a block of memory reserved for the array and to reflect the dynamic character put the array inside a struct with the last index, and when you add something add it on the last location and increment the counter. When this block is filled, you can chain another block to point to another one.
typedef struct _dyna_arr
{
my_type data_arr[MAX_LEN];
int n;
struct _dyna_arr *next block;
};
Therefore you maintain a linked list of multiple arrays. The size of MAX_LEN can be fixed which is appropriate for an application which will help decrease internal fragmentation.
*old answer removed *