Struct and Pointers - c

So in my code I have two structures. The first is a node which contains an int value and a pointer to another node. The second structure is used to create an array of 10 pointers each point to a another node. And it also contains link2 which will be used to traverse the array and all the nodes that it points to. I'm trying to add 3 nodes each holds the value 3 into the third index of the array. The pointer in the third index should point to the first 3 then that should point to the second three and so on. When I put add(a,3) three times and then print i get segmentation fault. I tried tracing the code but that still didn't make any sense to me because I always end up with three nodes. Can someone point me in some direction? Thanks!:)/>
#include <stdio.h>
#include<stdlib.h>
#include<string.h>
struct node
{
int x;
struct node *link;
};
struct listofnodes
{
struct node *alist[10];
struct node *link2;
};
addFirst(struct listofnodes *a, int num)
{
struct node *nodeone = (struct node *)malloc(sizeof(struct node));
nodeone->x = num;
a->alist[num] = nodeone;
// printf("IT WENT THROUGH\n");
}
add(struct listofnodes *a, int num)
{
struct node *current;
current = a->alist[3];
struct node *nodeone = (struct node *)malloc(sizeof(struct node));
nodeone->x = num;
current->x = 5;
{
while (a->alist[3] != NULL)
{
if (a->alist[3]->link == NULL)
{
a->alist[3]->link = nodeone;
printf("IT WENT THROUGH\n");
break;
}
a->alist[3] = a->alist[3]->link;
}
}
}
main(void)
{
struct listofnodes *a =
(struct listofnodes *)malloc(sizeof(struct listofnodes));
// a->alist[3]=NULL;
addFirst(a, 3);
add(a, 3);
add(a, 3);
add(a, 5);
}

In your main() function you have:
struct listofnodes *a =
(struct listofnodes *)malloc(sizeof(struct listofnodes));
"a" is now a pointer to a listofnodes-sized block of memory containing random locations. You probably want to do something like
a->link2 = NULL;
Also, in your add() function, you have...
add(struct listofnodes *a, int num)
{
struct node *current;
current = a->alist[3];
struct node *nodeone = (struct node *)malloc(sizeof(struct node));
nodeone->x = num;
You have malloc()d random memory and put "num" into x, but you need to put a null into where 'link' goes, i.e.
nodeone->link = NULL;
When you create the memory block using malloc(), you have to manually make sure the 'link' member is set to NULL - otherwise the number left there from last use will point who knows where...

Related

no effect happening to the program when i am putting r=NULL in function ins()

While working with the pointers we are working on address, right?
So when a struct node pointer n is passed to t(struct node *t=n) and later if t is assigned NULL shouldn't n also become NULL?
ps-: it's a program of a binary tree
#include<stdio.h> //check at third line of ins() function
#include<stdlib.h>
struct node{
int data;
struct node* left,*right;
};
struct node* n(int dat){
struct node *x=(struct node*)malloc(sizeof(struct node));
x->data=dat;
x->left=NULL; x->right=NULL;
return x;
};
void ins(struct node* n,struct node* r){
struct node* t=r,*y=NULL; //ok so when i put r=NULL in this next line should this block of memory go
//r=NULL; //NULL
while(t!=NULL){
y=t;
if(t->data>n->data)
{
if(t->left==NULL)
{t->left=n;
t=NULL;
}
else
t=t->left;
}
else {
if(t->right==NULL){
t->right=n;
t=NULL;
}else
t=t->right;
}
}
}
void inorder(struct node* n){
if(n!=NULL){
inorder(n->left);
printf("%d ",n->data);
inorder(n->right);
}}
void main(){
struct node *a,*b,*c,*d,*e,*f,*g,*h;
a=n(32); b=n(20); c=n(100); d=n(16);
e=n(25); f=n(50); g=n(144); h=n(19);
a->left=b; a->right=c;
b->left=d; b->right=e;
c->left=f; c->right=g;
ins(h,a);
inorder(a);
}```
With struct node* t=r you are creating a new and independent variable t that points to the same location as r (lets call that A).
This means any changes to *r are reflected in *t as they both point to the same location A.
when assigning NULL to r, the t variable still points to location A, but r no longer does.
A small example:
int A = 0;
int *r = &A;
int *t = r;
// *r==0, *t==0, point to same location
*r = 55;
// *r==55, *t==55 (same location)
r = NULL;
// *t==55 (*r is no longer valid as r is NULL)

meaning of a struct within a struct in c [duplicate]

This question already has answers here:
What is self-referencing structure in C?
(3 answers)
Closed 3 years ago.
Can someone explain what we mean when we do, like what does struct Node* next do. does it create a pointer of type struct? any help and resources about structures in c would be helpful
struct Node {
int dest;
struct Node* next;
};
"struct" itself is not a type. "struct [tag]" is a type, for example "struct Node" in your code.
In your case you define a structure type. Every structure of that type will contain a pointer to another structure of that type as a member called "next".
This allows you to chain the structures together in a so called linked list. You store a pointer to the first structure in a variable, then you can follow the chain of links down to the structure you need.
For example, you can do
struct Node *start;
start = malloc(sizeof struct Node);
start->dest = 7;
start->next = malloc(sizeof struct Node);
start->next->dest = 13;
start->next->next = malloc(sizeof struct Node);
start->next->next->dest = 19;
printf("%d %d %d\n", start->dest, start->next->dest, start->next->next->dest);
free(start->next->next);
free(start->next);
free(start);
Please note that this code omits all error handling, in real code you have to handle the case when malloc returns NULL.
Also, in real code you would use such a structure in loops that traverse the chain, not directly as above.
As #Serge is pointing out in comments, is not a struct within a struct, is a reference (a pointer) to an object of the same type, an example:
#include <stdio.h>
struct Node {
int dest;
struct Node* next;
};
int main(void)
{
/* An array of nodes */
struct Node nodes[] = {
{1, &nodes[1]}, // next points to the next element
{2, &nodes[2]}, // next points to the next element
{3, NULL} // next points to null
};
/* A pointer to the first element of the array */
struct Node *node = nodes;
while (node) {
printf("%d\n", node->dest);
node = node->next; // node moves to the next element
}
return 0;
}
Output:
1
2
3
Of course, in my example there is no benefit in using a linked list, linked lists are useful when we don't know the number of elements before-hand.
Another example using dynamic memory:
struct Node *head, *node;
node = head = calloc(1, sizeof *node);
node->dest = 1;
while (more_elements_needed) {
node->next = calloc(1, sizeof *node);
node->next->dest = node->dest + 1;
node = node->next;
}
for (node = head; node != NULL; node = node->next) {
printf("%d\n", node->dest);
}

How to make changes in an array through a function

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 10
// A hashtable is a mixture of a linked list and array
typedef struct node NODE;
struct node{
int value;
NODE* next;
};
int hash(int);
void insert(int,NODE **);
int main(){
NODE* hashtable[SIZE];
insert(12,&hashtable[SIZE]);
printf("%d\n",hashtable[5]->value);
}
int hash(int data){
return data%7;
}
void insert(int value,NODE **table){
int loc = hash(value);
NODE* temp = malloc(sizeof(NODE));
temp->next = NULL;
temp->value = value;
*table[loc] = *temp;
printf("%d\n",table[loc]->value);
}
The above code prints :
12 and
27475674 (A random number probably the location.)
how do I get it to print 12 and 12 i.e. how to make a change in the array. I want to fill array[5] with the location of a node created to store a value.
The expression *table[loc] is equal to *(table[loc]) which might not be what you want, since then you will dereference an uninitialized pointer.
Then the assignment copies the contents of *temp into some seemingly random memory.
You then discard the memory you just allocated leading to a memory leak.
There's also no attempt to make a linked list of the hash-bucket.
Try instead to initially create the hashtable array in the main function with initialization to make all pointers to NULL:
NODE* hashtable[SIZE] = { NULL }; // Will initialize all elements to NULL
Then when inserting the node, actually link it into the bucket-list:
temp->next = table[loc];
table[loc] = temp;
This is just a simple change which I have made to your program which will tell you what you are actually doing wrong.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 10
// A hashtable is a mixture of a linked list and array
typedef struct node NODE;
struct node {
int value;
NODE* next;
};
NODE *hashtable[SIZE] = { NULL };
int hash(int);
int insert(int); //, NODE **);
int main(void)
{
int loc = insert(12); //, &hashtable[SIZE]);
if (loc < SIZE) {
if (hashtable[loc]) {
printf("%d\n", hashtable[loc]->value);
} else {
printf("err: invalid pointer received\n");
}
}
return 0;
}
int hash(int data)
{
return data%7;
}
int insert(int value) //, NODE *table[])
{
int loc = hash(value);
printf("loc = %d\n", loc);
if (loc < SIZE) {
NODE *temp = (NODE *) malloc(sizeof(NODE));
temp->value = value;
temp->next = NULL;
hashtable[loc] = temp;
printf("%d\n", hashtable[loc]->value);
}
return loc;
}
Here I have declared the hashtable globally just to make sure that, the value which you are trying to update is visible to both the functions. And that's the problem in your code. Whatever new address you are allocating for temp is having address 'x', however you are trying to access invalid address from your main function. I just wanted to give you hint. Hope this helps you. Enjoy!

Sorted Insertion in linked list

I'm trying to create a function that does sorted insertion based on two variables, level and name. Apparently I'm having some logic and syntax errors.
My linked list structure:
struct node {
struct node *next;
int level;
char name;
};
My string compare function:
int compare(struct node *one, struct node *two)
{
return strcmp(one->name, two->name);
}
My insertion function:
void insert(struct node **head, const int level, const char name, int(*cmp)(struct node *l, struct node *r))
{
struct node *new =NULL;
/* Find the insertion point */
for (; *head; head = &(*head)->next)
{
if ((*head)->level > level) { // I think this is what is causing the issue
if (compare(*head, new) > 0)
break;
}
}
new = malloc(sizeof *new);
new->level = level;
new->name = name;
new->next = *head;
*head = new;
}
and this is the call stack:
insert(node **head, const int level, const char name, int(*)(node *, node *))
Your syntax error is this line:
return strcmp(one->name, two->name);
The function strcmp expect two char* (aka char pointers) but you give it two char.
The problem is... Do you want
char name;
or
char* name;
That is important in order to get compare right.
Further you need to rearrange your insert function so that you create the new node before using it. Something like:
void insert(struct node **head, const int level, const char name, int(*cmp)(struct node *l, struct node *r))
{
struct node *new =NULL;
// Create and initialize new....
new = malloc(sizeof *new);
new->level = level;
new->name = name;
/* Find the insertion point */
for (; *head; head = &(*head)->next)
{
if ((*head)->level > level) { // I think this is what is causing the issue
if (cmp(*head, new) > 0)
// ^^^ So that you can use it here
break;
}
}
new->next = *head;
*head = new;
}
You are passing a NULL value to the cmp function (?!? probably the correct function is int compare(...). Try to initialize the value of the new variable before to pass it to the function.
You declare node.name to be of type char, but your comparison function is written as if they were null-terminated arrays of char or pointers into such arrays (i.e. C strings). You appear to want this:
struct node {
struct node *next;
int level;
char *name;
};
or maybe this:
struct node {
struct node *next;
int level;
char name[MY_MAXIMUM_NAME_LENGTH_PLUS_ONE];
};
Furthermore, your insert() function passes a NULL pointer to the comparison function as its second argument, because you never allocate any memory for pointer new, and, of course, never assign values to the non-existent members. That doesn't even make sense. What do you think you're comparing to? You seem to want something like this:
struct node *new = malloc(sizeof *new);
if (!new) {
// allocation failure -- abort ...
}
new->level = level;
new->name = /* hmmmm ... */;
Of course, the problem with the type of your names crops up here, too.

Simple linked list with random values

Okay so here's the task: Implement a list with 25 ordered random integers between 0 and 100.
My approach: get 25 numbers in an array, order the array and create the list with the array elements.
#include <conio.h>
#include <malloc.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
struct Node{
int data;
struct Node *next;
};
int main()
{
struct Node *p=NULL;
struct Node *q=NULL;
int j,i,aux,n,v[25];
for (i=0;i<25;i++)
{
v[i]=rand()%100;
}
for (i=0;i<25;i++)
{
for (j=1;j<25;j++)
{
if (v[i]>v[j])
{
aux=v[i];
v[i]=v[j];
v[j]=v[i];
}
}
}
q=(Node *)malloc(sizeof(struct Node));
q->data=v[0];
q->next=NULL;
for (i=1;i<25;i++)
{
p=(Node *)malloc(sizeof(struct Node));
q->next=p;
p->data=v[i];
p->next=NULL;
q=p;
}
while (p)
{
printf("%d ",p->data);
p=p->next;
}
}
Output: 0.
Can you guys figure out what I did wrong ?
There's a number of things wrong... but the primary one (that's causing all 0's) is here:
if (v[i]>v[j])
{
aux=v[i];
v[i]=v[j];
v[j]=v[i];
}
Your swap is incorrect, you store v[i]'s data in aux, but you never set it to v[j], so you're just overwriting everything with the smallest value (0)
You wanted:
v[j] = aux;
The other major issue is you're not keeping track of the "head" of your list:
p=(struct Node *)malloc(sizeof(struct Node));
q->next=p;
p->data=v[i];
p->next=NULL;
q=p;
You keep assigning a new value to p, then overwritting q with p... so there's no way to find your way back. You'll only have the last value in your linked list
Something like:
struct Node* head = NULL;
...
head = q=(Node *)malloc(sizeof(struct Node)); // head points to the first node now
Then later:
p = head; // reset p to the start of the list.
while (p)
{
...
You don't need to set up all this array stuff; the fragment below returns a linked list of N=cnt Nodes with random payload:
struct Node *getnrandom(unsigned cnt) {
struct Node *p=NULL, **pp;
for (pp=&p; cnt--; pp = &(*pp)->next) {
*pp = malloc (sizeof **pp);
if (!*pp) break;
(*pp)->data = rand();
}
if (*pp) (*pp)->next = NULL;
return p;
}
UPDATE: since the OP appears to need the values to be ordered, he could either perform insertion (at the right position) into the llist (N*N) , or sort it post hoc. (NlogN)

Resources