Accessing a bit array in linked list node - c

I have a linked list defined as such:
typdef struct _seg
{
int bits[256]; // # of bits in bits[] array = 256
struct _seg *next; // link to the next segment
} seg;
And I was wondering how I can access the bit array inside each node of this list. If it were a regular int variable and the list was called p, I could just do p->bits = 13;. But I don't know how to get to and modify the list in this case. Can someone please help me out?
P.S. (not as important) Does anyone know what the seg; does at the very end?

To access the nodes in your list, you'll have to use a loop to iterate on all your elements:
seg* p = createList();
seg* current = p; // start at first element
while( current != NULL ){
for( int i=0; i<256; i++ ) {
current->bits[i] = 13; // modify bits inside
}
current = current->next; // go to next element in the list
}

p->bits is an array of 256 integers. You can access it with p->bits[0] = 13.
Or in general p->bits[i] = 13 where 0 <= i < 256.
typdef struct _seg
{
...
}seg;
With this you can define a variable of this struct type using seg as
seg SomeName;
No need for struct _seg someName;.

Related

Pointer seg faulting although I malloc-ed right

I don't understand why my program seg faults at this line: if ((**table->table).link == NULL){ I seem to have malloc-ed memory for it, and I tried looking at it with gdb. *table->table was accessible and not NULL, but **table->table was not accessible.
Definition of hash_t:
struct table_s {
struct node_s **table;
size_t bins;
size_t size;
};
typedef struct table_s *hash_t;
void set(hash_t table, char *key, int value){
unsigned int hashnum = hash(key)%table->bins;
printf("%d \n", hashnum);
unsigned int i;
for (i = 0; i<hashnum; i++){
(table->table)++;
}
if (*(table->table) == NULL){
struct node_s n = {key, value, NULL};
struct node_s *np = &n;
*(table->table) = malloc(sizeof(struct node_s));
*(table->table) = np;
}else{
while ( *(table->table) != NULL){
if ((**table->table).link == NULL){
struct node_s n = {key, value, NULL};
struct node_s *np = &n;
(**table->table).link = malloc(sizeof(struct node_s));
(**table->table).link = np;
break;
}else if (strcmp((**table->table).key, key) == 0){
break;
}
*table->table = (**(table->table)).link;
}
if (table->size/table->bins > 1){
rehash(table);
}
}
}
I'm calling set from here:
for (int i = 0; i < trials; i++) {
int sample = rand() % max_num;
sprintf(key, "%d", sample);
set(table, key, sample);
}
Your hashtable works like this: You have bins bins and each bin is a linked list of key / value pairs. All items in a bin share the same hash code modulo the number of bins.
You have probably created the table of bins when you created or initialised the hash table, something like this:
table->table = malloc(table->bins * sizeof(*table->table);
for (size_t i = 0; i < table->bins; i++) table->table[i] = NULL;
Now why does the member table have two stars?
The "inner" star means that the table stores pointers to nodes, not the nodes themselves.
The "outer" start is a handle to allocated memory. If your hash table were of a fixed size, for example always with 256 bins, you could define it as:
struct node_s *table[256];
If you passed this array around, it would become (or "decay into") a pointer to its first element, a struct node_s **, just as the array you got from malloc.
You access the contents of the l´bins via the linked lists and the head of linked list i is table->table[i].
You code has other problems:
What did you want to achieve with (table->table)++? This will make the handle to the allocated memory point not to the first element but tho the next one. After doing that hashnum times, *table->table will now be at the right node, but you will have lost the original handle, which you must retain, because you must pass it to free later when you clean up your hash table. Don't lose the handle to allocated memory! Use another local pointer instead.
You create a local node n and then make a link in your linked list with a pointer to that node. But the node n will be gone after you leave the function and the link will be "stale": It will point to invalid memory. You must also create memory for the node with malloc.
A simple implementation of your has table might be:
void set(hash_t table, char *key, int value)
{
unsigned int hashnum = hash(key) % table->bins;
// create (uninitialised) new node
struct node_s *nnew = malloc(sizeof(*nnew));
// initialise new node, point it to old head
nnew->key = strdup(key);
nnew->value = value;
nnew->link = table->table[hashnum];
// make the new node the new head
table->table[hashnum] = nnew;
}
This makes the new node the head of the linked list. This is not ideal, because if you overwrite items, the new ones will be found (which is good), but the old ones will still be in the table (which isn't good). But that, as they say, is left as an exercise to the reader.
(The strdup function isn't standard, but widely available. It also creates new memory, which you must free later, but it ensures, that the string "lives" (is still valid) after you have ceated the hash table.)
Please not how few stars there are in the code. If there is one star too few, it is in hash_t, where you have typecasted away the pointer nature.

Inserting an element in a list without tail or head

I've got a little problem about an exercice which is supposed to explain how malloc works.
For starters, here's the header we have been given:
struct cell_m
{
unsigned int magicnumber ;
struct cell_m *next ;
void *userspacestart ;
void *userspacestop ;
};
typedef struct cell_m *liste_t ;
As you can see, I have only a next pointer so it's a simple chained list.
I am supposed to code a function to insert a cell_m inside a liste_t of cell_m.
There is one condition, the size of the cell_m that we want to insert must be smaller than the one we're currently at.
Here's my code of this function :
void insert(liste_t *list, liste_t cell)
{
liste_t *old_list = malloc(sizeof(liste_t*));
if (sizeof((*list)->userspacestop) - (sizeof((*list)->userspacestart))
>= (sizeof(cell->userspacestop)) - (sizeof(cell->userspacestart)))
/*insert at the begining*/
else
{
old_list = list;
(*list) = (*list)->next;
while ((*list)->next != NULL)
{
if (sizeof((*list)->userspacestop) - (sizeof((*list)->userspacestart))
>= (sizeof(cell->userspacestop)) - (sizeof(cell->userspacestart)))
{
(*old_list)->next = cell;
cell->next = (*list);
break;
}
old_list = list;
(*list) = (*list)->next;
}
}
}
A little explanation : I try to keep the last position of where I was in the list so I created an "old_list" variable to keep it.
At first, I tried to see if I can directly insert my cell at the beginning of the list. I'm not entirely sure what to put here so I put a comment for now.
Then, if it's not possible to insert it at the begining, I will move forward into my list and try to insert the element. (Then again, not entirely sure if the code for inserting is right)
Is this any good, or am I totally wrong with this code?
Assuming that the first pointer points to the pointer that points to the list and the second argument is a pointer to the new element to insert, there is no reason to malloc() anything. You just need to find the place in the list where you want to insert.
struct cell_m {
unsigned int magicnumber ;
struct cell_m *next ;
char *userspacestart ; // character pointers allow pointer arithmetic
char *userspacestop ;
};
// typedefs only exist to confuse you
// typedef struct cell_m *liste_t ;
void insert(struct cell_m **head, struct cell_m *this)
{
for ( ;*head != NULL; head = &(*head)->next) {
if (*head)->userspacestop - (*head)->userspacestart
< this->userspacestop - this->userspacestart) break;
}
this->next = *head;
*head = this;
}
You can of course do the same using void * pointers, but you will need a lot of casts to char* (or some other granularity) to get it working.

Initialization error misunderstanding... Need some clarification

So I have a linked list set up like this:
#define MAX 20
//structure for a single linked list
typedef struct element {
int info;
struct element *link;
} Tnode;
//structure for a grapgh
typedef struct graphAdjList {
int nodes;
Tnode *adjList[MAX];
} Tgraph;
In my code I have it set up like this:
Tgraph *graph;
graph = (Tgraph*) malloc(sizeof(Tgraph));
graph -> nodes = 0;
for(i; i < 20; i++){
graph->adjList[i]= NULL;
}
graph->adjList[2]->info = 222;
Now if I compile this I get an access violation on this last line. Is it that I have not reserved memory for the Tnode part of the struct or am I missing something. How can I initialize the array so that I can assign a value to info in any element of the array?
Thank you
Jason
You are right, the issue is that you have not allocated memory for the individual nodes in adjList.
When you do graph->adjList[2]->info = 222;, graph->adjList[2] is still NULL from the for loop right before it.
To fix this, you need to first allocate memory for it like so:
graph->adjList[2] = malloc(sizeof(TNode));
Note: You could just replace graph->adjList[i] = NULL; with graph->adjList[i] = malloc(sizeof(Tnode)); in the for loop, but allocating as you go can be useful for memory efficiency.
You need to replace
graph->adjList[i]= NULL;
to
graph->adjList[i] = (Tnode*)malloc(sizeof(Tnode));

Creating and expanding a Linked List using Structs

I have been working on a program in C99 which is based heavily around structs. I found that I could create linked lists of structs, and thought to give it a try.
The following is a miserable attempt, reworked about 50 times, that is meant to do the following:
1) Create a struct of type BASE in the main method, which contains the head of a linked list (CHAIN).
2) Pass this BASE struct to another function, which will append additional CHAIN elements to the end of the linked list.
3) Print the linked lists elements in main, as proof to myself that the changes are not just in the other method.
#include <stdlib.h>
#include <stdio.h>
typedef struct Base {
//many things
struct Chain *head;
} BASE;
typedef struct Chain {
int x;
struct Chain *next;
} CHAIN;
void extendChain(BASE *Data, int length);
int main() {
BASE Data;
CHAIN *pointer;
Data.head = 0;
int length = 10; //userInput(); // gets integer
extendChain(&Data, length);
pointer = Data.head;
while (pointer) {
printf("%d\n", pointer->x);
pointer = pointer->next;
}
}
void extendChain(BASE *Data, int length) {
CHAIN *position;
position = Data->head;
for (int i=0; i<length; ++i) {
if (!Data->head) {
// this will set the first value, the first time this is run.
Data->head = malloc(sizeof(CHAIN));
Data->head->x = -1; // set values here. Irrelevant.
position = Data->head;
} else if (position) {
while (position->next) {
position = position->next;
}
position = malloc(sizeof(CHAIN));
position->next = 0;
position->x = i; // placeholder
}
}
}
This has turned out terribly, and I realize that my example doesn't begin to work even in theory (but I gave it my best shot). I'm beginning to think that the only way to do this is if I do it all in the same method, which I successfully managed to do earlier, however this will quickly become messy, and a method would definitely be best.
Does anyone have a creative way of adding X elements to a linked list when passed only a struct containing the header of this linked list? Much appreciated, as always.
Logical errors in your code. This code worked:
void extendChain(BASE *Data, int length) {
CHAIN *position;
position = Data->head;
int i;·
for (i=0; i<length; ++i) {
if (!Data->head) {
// this will set the first value, the first time this is run.
Data->head = malloc(sizeof(CHAIN));
Data->head->x = -1; // set values here. Irrelevant.
Data->head->next = NULL; // <=========
position = Data->head;
} else if (position) {
while (position->next) {
position = position->next;
}
CHAIN * position_new_node = malloc(sizeof(CHAIN)); // <=========
position_new_node->next = 0; // <=========
position_new_node->x = i; // placeholder // <=========
position->next = position_new_node; // <=========
}
}
}
Algorithm
Create the original linked list
Send the linked list to be added, to the function
Traverse till the end of first linked list (Let the pointer be t)
repeat:
node next to t=next node of new linked list
move both nodes one unit forward
till the next node of new linked list is Null

C - Finding the max value using pointers

Im new to C. Say if
struct test{
int val;
struct test *next
};
If a list has been created using this struct, how do you find the maximum value via pointers?
Assuming list is filled with objects of the above struct, I have tried
struct test *t1 = malloc(sizeof (struct test));
struct test *t2 = malloc(sizeof (struct test));
While (list !=NULL){
int max=0;
struct test *t1, *t2;
if(t1->val < t2->val){
max = t2->val;
}
list = list->next;
}
But I guess I dont understand the logic behind it. I just need an explanation or an example on how to find the maximum value of a list of structs using pointers. Your help will be appreciated.
This may help you out understanding (I guess)
snippet:
max = t1->val; /* take first value */
/* this is one way of traveling through the simple (?) list */
for(pointer = t1->next; pointer; pointer = pointer->next)
max = pointer->val > max ? pointer->val : max;
printf("max: %d\n", max);
EDIT: assuming t1 refers to a populated list.

Resources