C : Acessing a structure within a structure - c

typedef struct mensagem
{
int sender ;
int receiver ;
char *text ;
} *Item ;
typedef struct node
{
Item item ;
struct node *next ;
} *link ;
link init(char* text)
{
link x = (link) malloc(sizeof(struct node));
(x->item->text) = (char*) malloc(sizeof(char)*(strlen(text)+1));
strcpy(x->item->text, text);
x->next = NULL;
return x;
}
I meant to use the data inside item, but I get a Segmentation Fault on the line:
(x->item->text) = (char*) malloc(sizeof(char)*(strlen(text)+1));
I'm fairly new to C and pointers, but I can't find the problem here.

You haven't allocated memory for the structure pointed to by x->item. Add
x->item = malloc(sizeof (struct mensamam));
before the other malloc.

Put this after allocating memory for x:
x->item = malloc(sizeof(struct mensagem));
You have to allocate the memory for the field 'item' before you can actually access and allocate its fields.

This should do just fine:
typedef struct mensagem
{
int sender ;
int receiver ;
char *text ;
} Item ;
typedef struct node
{
Item *item ;
struct node *next ;
} Link ;
Link *init(char *text)
{
// Note: Do error checking after each of these lines in case malloc() fails!
Link *x = malloc(sizeof(Link));
x->item = malloc(sizeof(Item));
x->item->text = malloc(sizeof(char) * (strlen(text) + 1));
strcpy(x->item->text, text);
x->next = NULL;
return x;
}

Related

how to initializing a hash table in C

I have a program in C that creates a hash table.
memset is Okay but, i want to initialize with for loop.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define HSZ 127
#define HASHING(x) ((x)%HSZ)
struct node_t{
int val;
struct node_t *next;
};
struct node_t *hash_table[HSZ];
void init(void){
int i;
//memset(hash_table,0,sizeof(hash_table));
for(i=0; i<HSZ; i++){
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
}
void insert_hash(int value){
int key = HASHING(value);
struct node_t *newNode = (struct node_t*)malloc(sizeof(struct node_t));
newNode->val = value;
newNode->next = NULL;
if(hash_table[key] == NULL){
hash_table[key] = newNode;
} else {
newNode->next = hash_table[key];
hash_table[key] = newNode;
}
}
int delete_hash(int value){
int key = HASHING(value);
if (hash_table[key] == NULL)
return 0;
struct node_t *delNode = NULL;
if (hash_table[key]->val == value){
delNode = hash_table[key];
hash_table[key] = hash_table[key]->next;
} else {
struct node_t *node = &hash_table[key];
struct node_t *next = hash_table[key]->next;
while (next){
if (next->val == value){
node->next = next->next;
delNode = next;
break;
}
node = next;
next = node->next;
}
}
return 1;
free(delNode);
}
void PrintAllHashData()
{
printf("###Print All Hash Data###\n");
for (int i = 0; i < HSZ; i++){
if (hash_table[i] != NULL){
printf("idx : %d ", i);
struct node_t *node = hash_table[i];
while (node->next){
printf("%d ", node->val);
node = node->next;
}
printf("%d\n", node->val);
}
}
}
int main(void){
init();
insert_hash(1);
insert_hash(3);
insert_hash(128);
PrintAllHashData();
}
look at this code.
for(i=0; i<HSZ; i++){
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
The IDE I am using does not throw up a compilation error when I compile the code, but during the execution the code faults and is terminated/haulted. I tried debugging the code, it faults at this line and is stopped, I think BAD ACCESS points to Segmentation Error.
then, I changed this line to
for(i=0; i<HSZ; i++){
hash_table[i].val = 0;
hash_table[i]->next = NULL;
}
but, then I got the compilation error stating 'structure type require instead of 'struct node_t *'
I think that I don't understand clearly about struct in C.
How to fix this problem?
What you are dealing with is Undefined Behavior.
See, struct node_t *hash_table[HSZ];
So, hash_table is an array of HSZ (127) pointers of the data type struct node_t.
When you do,
for(i=0; i<HSZ; i++){
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
hash_table[0] to hash_table[126] pointers are not pointing to anything.
So, each of them (or all of them) should be initialized first to point to an object of the type struct node_t and then you can initialize them. For that matter, Using a memset does not cause a problem because memset is filling the contents of the pointers with all zeros. There is difference between filling the pointers with all zeros and filling all zeros to the memory pointed by pointers.
Trying this,
for(i=0; i<HSZ; i++){
hash_table[i].val = 0;
hash_table[i]->next = NULL;
}
is plain wrong.
To fix the issue you are facing, you need to allocate memory dynamically using malloc. You can do the in your for loop.
for(i = 0; i < HSZ; i++)
{
//Allocate memory of the size struct_node_t
hash_table[i] = malloc(sizeof(struct node_t)); //Do not cast!
//Check if memory is allocated
if(hash_table[i] == NULL)
{
//Memory not allocated, set some error state to handle and break
break;
}
//Initialize to zero
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}
struct node_t{
int val;
struct node_t *next;
};
struct node_t *hash_table[HSZ];
when you have *hash_table[HSZ], this varible hash_table is a pointer. so whatever your action is , use hash_table-> ,syntax for pointer, mean point to somewhere.
a suggestion that when you use pointer you should always allocate memory hash_table[i] = malloc(sizeof(struct node_t));
struct node_t hash_table;
but if you initilize your varible like this, you can use hash_table.val = 0
so the way of assign value depend on how you declare your varibles
struct node_t *hash_table[HSZ];
gives you an array of pointers that are unset (i.e. not pointing to anything)
void init(void) {
int i;
// memset(hash_table,0,sizeof(hash_table));
for (i = 0; i < HSZ; i++) {
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
tries writing to your invalid pointers which gives undefined behavior.
Either make the array an array of structs (instead of pointers):
struct node_t hash_table[HSZ];
...
/* note use of . instead of -> since we have structs not pointers */
hash_table[i].val = 0;
or allocate the necessary structs so the array points to something:
for (i = 0; i < HSZ; i++) {
hash_table[i] = malloc(sizeof(struct node_t));
hash_table[i]->val = 0;
hash_table[i]->next = NULL;
}

Enqueue/Dequeue two linked lists simultaneously in C

I have two linked lists that I track using inputFront, inputRear, outputFront & outputRear. My problem arises when I enqueue the data from input into output. Printf prints only the first item from the input. Ex: my input is "a b c", it will only return "a". I'd appreciate the help. Thanks.
struct linked_list{
char *operand;
struct linked_list *next;
};
void enqueue(struct linked_list** queueFront, struct linked_list** queueRear,
char* token);
char* dequeue(struct linked_list** queueFront, struct linked_list** queueRear);
int main(int argc, char *argv[]){
struct linked_list *inputFront = NULL, *inputRear = NULL;
struct linked_list *outputFront = NULL, *outputRear = NULL;
for (int i = 1; i < argc; i++)
enqueue(&inputFront, &inputRear, argv[i]);
for (struct linked_list *p = inputFront; p != NULL; p = p->next)
enqueue(&outputFront, &outputRear, dequeue(&inputFront, &inputRear));
for (struct linked_list *p = outputFront; p != NULL; p = p->next)
printf("%s \n", dequeue(&outputFront, &outputRear));
}
void enqueue(struct linked_list** queueFront, struct linked_list** queueRear,
char* token){
struct linked_list* newNode = (struct linked_list*) malloc(
sizeof(struct linked_list));
newNode->operand = token;
newNode->next = NULL;
if (*queueRear == NULL && *queueFront == NULL){
*queueFront = *queueRear = newNode;
return;
}
(*queueRear)->next = newNode;
*queueRear = newNode;
}
char* dequeue(struct linked_list** queueFront, struct linked_list** queueRear){
if (*queueFront != NULL){
struct linked_list *remv = *queueFront;
char *remOperand = (*queueFront)->operand;
*queueFront = remv->next;
if (remv == (*queueRear))
*queueRear = NULL;
free(remv);
return remOperand;
}
else
return NULL;
}
There are 2 issues with your code. See.
for (struct linked_list *p = inputFront; p != NULL; p = p->next)
enqueue(&outputFront, &outputRear, dequeue(&inputFront, &inputRear));
You are using a pointer p to run through the list, but this pointer is not used inside the loop. The inputFront in the statement must be replaced by this pointer p. This will allow it to run through every element of the loop.
In the dequeue function, you are moving the pointer inputFront (now p). So, if you do p = p-> next in the loop, it will be done twice. This has to be removed.
Fixed code is
for (struct linked_list *p = inputFront; p != NULL; )
enqueue(&outputFront, &outputRear, dequeue(&p, &inputRear));
for (struct linked_list *p = outputFront; p != NULL; )
printf("%s \n", dequeue(&p, &outputRear));
The problem seems to be in your print loop. You let p advance until the end of the list, and you let dequeue retrieve the next (first) item in the list. But dequeue also removes the front from the list. Following the return, the for-loop now also advances p, whose next member has jus been advanced already. Given input a b c, I would expect the output now to be a c. If you take a debugger, you can get some more clues.

Hashtable Add - C

Getting some segfault on the following algorithm to add an element to the correct bucket in a hashtable.
My structures are basic:
struct kv {
char* key;
unsigned val;
struct kv* next;
};
struct hashtable {
struct kv** table;
unsigned size;
};
And my buggy function:
struct kv* ht_find_or_put(char* word, unsigned value,
struct hashtablet* hashtable,
unsigned (*hash)(char*))
{
unsigned index = hash(word) % hashtable->size;
struct kv* ke = malloc(sizeof (struct kv));
for (ke = hashtable->table[index]; ke != NULL; ke = ke->next)
{
if (strcmp(ke->key, word) == 0)
return ke;
}
if (ke == NULL)
{
ke->key = word;
ke->val = value;
ke->next = hashtable->table[index];
hashtable->table[index] = ke;
}
return ke;
}
I know I haven't added yet all the tests (if malloc failed and such) just trying to debug this particular problem...
I'm allocating my table as such:
struct hashtable* hashtable_malloc(unsigned size)
{
struct hashtable *new_ht = malloc(sizeof(struct hashtable));
new_ht->size = size;
new_ht->table = malloc(sizeof(struct kv) * size);
for(unsigned i = 0; i < size; i++)
new_ht->table[i] = NULL;
return new_ht;
}
Any sort of help will greatly be appreciated. I'm only starting to learn.
The first issue is a memory leak, e.g. - you allocate memory using malloc, but than loses the reference to it, as you override the pointer:
// allocate memory
struct kv* ke = malloc(sizeof (struct kv));
// lose the reference
// VVVVVVVVVVV
for (ke = hashtable->table[index]; ke != NULL; ke = ke->next)
The second issue, which probably causes the segfault, is that you try to de-reference a null pointer:
if (ke == NULL)
{
// ke is NULL, you can't de-reference it
ke->key = word;
ke->val = value;
ke->next = hashtable->table[index];
hashtable->table[index] = ke;
}
The solution will be, IMHO, to allocate and put the new element, only upon failure to find it:
struct kv* ht_find_or_put(char* word, unsigned value, struct hashtablet* hashtable, unsigned (*hash)(char*))
{
unsigned index = hash(word) % hashtable->size;
struct kv* ke;
// first we try to find the node
for (ke = hashtable->table[index]; ke != NULL; ke = ke->next)
{
if (strcmp(ke->key, word) == 0)
return ke;
}
// didn't find it - lets create and put a new one.
if (ke == NULL)
{
ke = malloc(sizeof (struct kv));
// later add a check if the allocation succeded...
ke->key = word;
ke->val = value;
ke->next = hashtable->table[index];
hashtable->table[index] = ke;
}
return ke;
}
Since I didn't want to introduce entirely new code, that would just confuse you, I made the minimal changes to the original code.

create new nodes that point at each other

struct x{
...;
...;
struct x * next;
};
struct x create() {
struct x new = malloc...
new->... = .;
new->... = ..;
new->next = NULL
};
When i create a new node of struct x how does it work when using struct x create multiple times. It feels strange for me that you can use it multiple times because It allocate memory to a struct x with the same name new each time? Doesn't each node of a struct require an individual name. Or Does it only matters that each time a new memory allocation is done.
Main problem: I will create first node and then a second node. The first node should then point at the second node and so on. But when I create the first node the second doesn't exists so I can't set first->next = second.
I have looked at linked lists examples but it doesn't improve my thinking at the moment. The code isn't that important as my own understanding and thinking. Please help me think and grasp the concept.
//I tried to follow the sugestions from Degustaf(except the next pointer, basically the same as create a new node) but did the implementation wrong. So I wounder whats wrong with this code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct x{
int a;
int b;
struct x * next;
}
struct x *create(int a , int b){
struct x *new = malloc(sizeof(struct x));
new->a = a;//namn skitsamma allokering relevant
new->b = b;
new->next = NULL;
return new;
};
int main() {
struct x *x1 = struct x *create(12,13);
return 0;
}
You can simply assign the values of the pointers after you've created both.
i.e.,
struct x x1 = create();
struct x x2 = create();
x1.next = &x2;
x2.next = &x1;
Or Does it only matters that each time a new memory allocation is done.
Correct.
But, there are other issues with your code. In particular, you aren't returning anything from your create function. I see 2 ways to approach this to remedy the problem. The first is that you can return the struct directly, which means that you don't need the malloc:
struct x create()
{
struct x new;
new.member1 = .;
new.member2 = ..;
new.next = NULL;
return new;
};
Then you can populate it using
struct x x1 = create();
struct x x2 = create();
x1.next = &x2;
The other possibility is to return a pointer to a struct, in which case this becomes
struct x *create()
{
struct x *new = malloc...;
new->member1 = .;
new->member2 = ..;
new->next = NULL;
return new;
};
Then you can populate it using
struct x *x1 = create();
x1->next = create();
My opinion is that the second option is cleaner as you don't need to worry about individual elements of your linked list going out of scope, although it does require being careful when it comes to freeing memory (needing to traverse the list and free one element at a time.
I thing this is what you want but this is a example with intenger numbers in a list also yoy can change the code as you wish.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <iostream>
struct cell {
float info;
struct cell * next;
};
int more (float * k)
{
char ans[4];
printf("Continue Yes/No: ");
scanf("%s",ans);
if (ans[0]=='Y') {
printf("insert value: ");
scanf("%f",k);
return(1);
}
else
return(0);
}
struct cell * crelist()
{
struct cell * last = (struct cell *)NULL;
struct cell * ptr = (struct cell *)NULL;
struct cell * list = (struct cell *)NULL;
float k;
ptr = (struct cell *)malloc(sizeof(struct cell));
if (ptr != (struct cell *)NULL) {
printf("insert value: ");
scanf("%f",&k);
ptr->info = k;
ptr->next = (struct cell *)NULL;
list = ptr;
last = ptr;
}
else
return((struct cell *)NULL);
while (more(&k)) {
ptr = (struct cell *)malloc(sizeof(struct cell));
if (ptr != (struct cell *)NULL) {
ptr->info = k;
ptr->next = (struct cell *)NULL;
last->next = ptr;
last = ptr;
}
else
break;
}
return(list);
}
void printlist(struct cell * list)
{
struct cell * p;
p = list;
while (p != (struct cell *)NULL) {
printf("->%f\n",(*p).info);
p=(*p).next;
}
return;
}
int main()
{
struct cell * list;
int i;
list = crelist();
printlist(list);
scanf("%d",&i);
system("pause");
return 0;
}

Segmentation Fault error - Implementing Stack using Linked lists

I am currently in a University program studying Data Structures in C and I am having a lot of trouble right now. I want to make clear that what I am asking help for is not for marks, just practice challenge problems.
The goal is to implement a stack using Linked Lists. By looking through the lecture notes I think I have most of the functions down. I need to demonstrate Push() and Pop() will an append and a pretend. Using Cygwin, I compiled with no errors. but when I try to run it, I get a "Segmentation Fault". What does this mean and how do I fix it? if I remove "stack = initLListStack();", the error disappears. Here is my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct Link{
int *value;
struct Link *next;
}Link;
typedef struct LList1{
int *size;
Link *head;
}LList1;
typedef struct LListStack{
LList1 *llist;
}LListStack ;
LListStack *initLListStack(void)
{
LListStack *stack = (LListStack *) malloc(sizeof(LListStack)) ;
stack->llist->size = 0;
stack->llist->head = NULL;
return(stack);
}
void removefront(LList1 *llist)
{
if(llist->head != NULL){
llist->head = llist->head->next;
llist->size--;
}
}
Link *FindLastLink(LList1 *llist, Link *link)
{
if(link = NULL){
return(NULL);
}
else if(link->next == NULL){
return(link);
}
else{
return(FindLastLink(llist, link->next));
}
}
Link *FindSecondLastLink(LList1 *llist, Link *link)
{
if(link = NULL){
return(NULL);
}
else if(link->next->next == NULL){
return(link);
}
else{
return(FindSecondLastLink(llist, link->next));
}
}
void removelast(LList1 *llist)
{
Link *secondlastlink = (Link *) malloc(sizeof(Link));
secondlastlink = FindSecondLastLink(llist, llist->head);
secondlastlink->next = NULL;
llist->size--;
}
void prepend(int *newValue, LList1 *templist)
{
Link *node = (Link *) malloc(sizeof(Link));
node->value = newValue;
node->next = templist->head;
templist->head = node;
templist->size++;
}
void append(int *newValue, LList1 *templist)
{
Link *node = (Link *) malloc(sizeof(Link));
Link *lastlink = (Link *) malloc(sizeof(Link));
lastlink = FindLastLink(templist, templist->head);
node->value = newValue;
lastlink->next = node;
node->next = NULL;
templist->size++;
}
void prepush(int *value, LListStack *stack)
{
prepend(value, stack->llist);
}
void apppush(int *value, LListStack *stack)
{
append(value, stack->llist);
}
int prepop(LListStack *stack, int *value)
{
int result ;
if ((!isEmpty(stack)))
{
removefront(stack->llist);
result = 1 ;
}
else {
result = 0 ;
}
return(result) ;
}
int isEmpty(LListStack *stack)
{
int empty;
if (stack->llist->head == NULL)
return( 1 ) ;
else
return( 0 ) ;
}
int apppop(LListStack *stack, int *value)
{
int result ;
if ((!isEmpty(stack)))
{
removelast(stack->llist);
result = 1 ;
}
else
result = 0 ;
return(result) ;
}
//*******MAIN**********//
int main()
{
LListStack *stack = (LListStack *) malloc (sizeof(LListStack));
stack = initLListStack(); //if I take this away, I can run the program
return(0);
}
I don't have that much in Main() yet because I'm just trying to get it to run first. Initializing the Stack seems to be the problem.
Thanks for your help guys!
The problem is in your initLListStack() function:
LListStack *stack = (LListStack *) malloc(sizeof(LListStack)) ;
stack->llist->size = 0;
stack->llist->head = NULL;
return(stack);
The result of malloc is an uninitialized block of memory large enough to hold an LListStack struct.
The very first thing you do with that memory is read its llist member. Since this is uninitialized, you invoke undefined behavior which, fortunately, causes a segfault. (The compiler would be within the specification to send embarrassing e-mails to our instructor when this happens.)
You need to initialize llist before you can use that member in stack. Something like:
LListStack *stack = malloc(sizeof(*stack));
stack->llist = malloc(sizeof(*stack->llist));
stack->llist->size = 0;
stack->llist->head = NULL;
return stack;
Note that I've also removed some unnecessary casts and parentheses, and changed the sizeof operator to calculate the memory you need based on the pointer you're storing into.
A segmentation fault error is usually caused by trying to dereference an uninitialized pointer. In your case, you have allocated memory for stack in your initLListStack method but you haven't initialized it -- in particular the llist field is not initialized to any particular value. You need to allocate an LList1 and set the llist field to the newly-allocated memory.
LListStack *initLListStack(void)
{
LListStack *stack = (LListStack *) malloc(sizeof(LListStack)) ;
stack->llist->size = 0; // **this is probably where it crashes**
stack->llist->head = NULL;
return(stack);
}
You allocate stack ok, but you do not allocate stack->llist. So stack->llist is uninitialized and then you dereference it in stack->llist->size . Dereferencing an
uninitialized variable results in undefined behavior.
To fix this, allocate stack->list like this:
LListStack *initLListStack(void)
{
LListStack *stack = (LListStack *) malloc(sizeof(LListStack)) ;
stack->llist = (LListStack *) malloc(sizeof(LList1)) ; // ADD THIS LINE
stack->llist->size = 0;
stack->llist->head = NULL;
return(stack);
}

Resources