I am writing code to take in a weighted adjacency list in C. Each edge is stored in the form of a struct
. I created an array of pointers where each pointer leads to the list for a node. Here's what I did:
#include <stdio.h>
#include <stdlib.h>
struct edge {
int u;
int v;
int w;
};
// taking a weighted adjacency list
int main() {
int n; // number of nodes
scanf("%d ", &n);
struct edge **list[n];
int p = n;
while (p) {
struct edge *n_list = (struct edge *)malloc(n * sizeof(struct edge));
int num = 1;
for (int i = 0; i < n; i++) {
n_list[i].u = n - p;
scanf("%d ", &n_list[i].v);
if (n_list[i].v == -1) {
n_list[i].w = -1;
break;
} else {
num++;
scanf("%d ", &n_list[i].w);
}
}
n_list = (struct edge *)realloc(n_list, num * sizeof(struct edge));
list[n - p] = &n_list;
struct edge *ptr = *list[n - p];
for (int j = 0; j < num - 1; j++) {
printf("%d %d %d\n", ptr[j].u, ptr[j].v, ptr[j].w);
}
p--;
}
}
The problem is that the edges get printed correctly but after the whole iteration over p
(number of nodes), every element in the array of pointers (list
) has the same address stored. I'm guessing that everytime I use malloc
for n_list
, it is allocating memory in the same location, thereby erasing the list for the previous node when I start taking input. How can I ensure this does not happen? Also any easier methods to go about this task are welcome.
Here's your problem
list[n-p]=&n_list;
// ^ address of
That puts the address of n_list
into list[n-p]
. This will be an address on the stack - the location of n_list
and it won't change while n_list
is in scope during the loop iteration. It will almost certainly have the same address on the stack on each iteration.
The elements of list
are of type struct edge**
but you should be putting items in them of type struct edge*
. You have too much indirection. Fortunately, you also dereference the pointer to do the printing out before the end of the iteration and n_list
is malloc'd for the next time around.
struct edge* ptr=*list[n-p];
// ^ dereference
To fix this, declare list
as follows
struct edge* list[n];
And remove the "address of"/dereferencing
list[n-p] = n_list;
struct edge* ptr = list[n-p];
Edit
Just realised that the suggestion above isn't completely correct because you realloc each element of list
to be only as large as needed. This is problematic because you can't tell how many edges are in each list[i]
. You need to either
n_list
list
(don't do the realloc
) and use some "doesn't exist" value for the unused ones. It might be enough to set the weightings to 0.