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.
Related
I'm still learning how to program in C and I've stumbled across a problem.
Using a char array, I need to create a linked list, but I don't know how to do it. I've searched online, but it seems very confusing. The char array is something like this char arr[3][2]={"1A","2B","3C"};
Have a look at this code below. It uses a Node struct and you can see how we iterate through the list, creating nodes, allocating memory, and adding them to the linked list. It is based of this GeeksForGeeks article, with a few modifications. I reccommend you compare the two to help understand what is going on.
#include <stdio.h>
#include <stdlib.h>
struct Node {
char value[2];
struct Node * next;
};
int main() {
char arr[3][2] = {"1A","2B","3C"};
struct Node * linked_list = NULL;
// Iterate over array
// We calculate the size of the array by using sizeof the whole array and dividing it by the sizeof the first element of the array
for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++) {
// We create a new node
struct Node * new_node = (struct Node *)malloc(sizeof(struct Node));
// Assign the value, you can't assign arrays so we do each char individually or use strcpy
new_node->value[0] = arr[i][0];
new_node->value[1] = arr[i][1];
// Set next node to NULL
new_node->next = NULL;
if (linked_list == NULL) {
// If the linked_list is empty, this is the first node, add it to the front
linked_list = new_node;
continue;
}
// Find the last node (where next is NULL) and set the next value to the newly created node
struct Node * last = linked_list;
while (last->next != NULL) {
last = last->next;
}
last->next = new_node;
}
// Iterate through our linked list printing each value
struct Node * pointer = linked_list;
while (pointer != NULL) {
printf("%s\n", pointer->value);
pointer = pointer->next;
}
return 0;
}
There are a few things the above code is missing, like checking if each malloc is successful, and freeing the allocated memory afterwards. This is only meant to give you something to build off of!
I am creating a simple array of structures in C, but the first structure is always jibberish. How do i fix this?
I have tried to set the first element of the double pointer to struct in many ways but it always fails.
This is my graph.h file:
#ifndef GRAPH_H
#define GRAPH_H
#include "set.h"
typedef struct urlNode * URLList;
typedef struct GraphRep * Graph;
struct urlNode {
int id;
char* URL_NAME;
URLList next; // link to next node
};
struct GraphRep {
int nV;
URLList * collections;
};
Graph newGraph(Set s);
int nameToId(Graph g, char *name);
void showGraph(Graph g);
#endif
And my newGraph(Set s) function looks like this:
Graph newGraph(Set s){
int size = nElems(s);
Graph new_graph = malloc(sizeof(struct GraphRep));
if (new_graph == NULL) {
printf("ERROR: COULDNT ALLOCATE GRAPH\n");
}
new_graph->nV = size;
char *name = getNextVal(s);
// THIS IS THE NODE TO BE ADDED TO THE GRAPH
URLList list_to_add = malloc(sizeof(struct urlNode));
list_to_add->URL_NAME = strdup(name);
list_to_add->id = 0;
list_to_add->next = NULL;
// HERE I ADD THE NODE TO THE GRAPH.
new_graph->collections[0] = list_to_add;
// PRINT OUT THE VALUES OF THE NEWLY ADDED NODE TO MAKE SURE IT WORKS
// THE URL_NAME IS PRINTED OUT FINE
// BUT THE ID IS JIBBERISH.
printf("%s\n", new_graph->collections[0]->URL_NAME);
printf("%d\n", new_graph->collections[0]->id);
if(new_graph->collections[0]->next != NULL) {
printf("%s\n", new_graph->collections[0]->next->URL_NAME);
printf("%d\n", new_graph->collections[0]->next->id);
}
printf("\n");
return new_graph;
}
I expect new_graph->collections[0]->id to be 0 but it keeps on giving me random ints.
Also even if the next for the newly declared pointer to struct is NULL, it still gives me a jibberish next value too.
Any help would be appreciated, thanks!
The data member collections of the object *new_graph is not initialized.
There is initialized only this data member
new_graph->nV = size;
So this statement
new_graph->collections[0] = list_to_add;
results in undefined behavior.
If you need an array of pointers of the type URLList you have to allocate the memory and its address assign to the pointer collections.
For example
new_graph->collections = malloc( new_graph->nV * sizeof( URLList ) );
And after that this statement
new_graph->collections[0] = list_to_add;
could be valid.
(I suppose that the data member nV corresponds to the number of elements in the dynamically allocated array though it may not be truth)
Pay attention to that as the string pointed to by the pointer name is not changed in the function then it is better to declare it like
const char *name = getNextVal(s);
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.
I have two files (.txt) with phones numbers (one number per line). The files are pretty huge (282 MB), and I am writing a program to check these two files (raw data and DO NO CALL List), and filter out those numbers that does not exist in the DO NO CALL List. Something similar to grep -f raw.txt donotcall.txt -v > filtered.txt
I have implemented a very simple form of hashtable (separate addressing, using linked lists). My code currently, reads the phone numbers from the DoNotCall.txt and stores it in the hashtable. This is the function that I use to generate the hash. THE TABLE SIZE IS 100
int hashgen(char s[])
{
int hash;
hash = (s[0] + s[1] + s[2] + s[3]) * 100 / 13;
return hash;
}
The hashtable: the way I did.
#define TABLESIZE 100
struct node {
char str[30];
struct node *next;
}
struct node *hashtble[TABLESIZE];
struct node *hashtable_alloc(void) //allocates space for a node in the memory
{
struct node *tmp = calloc(1, sizeof(struct node));
strcpy(tmp->str, "~"); //just a string to mark the head of the linked list
tmp->next = NULL;
return tmp;
}
void hashinit(void)
{
struct node *t = NULL;
int i=0;
for(i=0; i<TABLE_SIZE; i++)
ht[i] = hashtable_alloc();
}
void hashtable_add(char s[])
{
struct node *t = NULL;
int arrnum = hashgen(s);
t = calloc(1, sizeof(struct node));
strcpy(t->str, s);
t->next = ht[arrnum];
ht[arrnum] = t;
}
Undoubtedly, I am a naive programmer dealing with hashtables. Please suggest me a better hash function. Though, I have read articles on hashtables, it would be great if anyone can tell me about a better approach, something better than hashtables, or do the hashtable method in a better way. Thanks in advance
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;.