Iterate through a List and print items - c

I have a list like this
#include <stdio.h>
#include <stdlib.h>
struct ListItem
{
int x;
int y;
struct ListItem *next;
};
int main()
{
int x1 =0;
int y1 = 0;
printf("Please enter the x coordinate: ");
scanf("%d", &x1);
printf("Please enter the y coordinate: ");
scanf("%d", &y1);
struct ListItem root;
if( root.next == NULL )
{
root.x = x1;
root.y = y1;
//I dont know what should I assign here but I want to have about 30 locations
//root.next = struct ListItem next;
}
//WHAT SHOULD I DO HERE?
{
printf("Your location is : (%d,%d)\n", root.x, root.y);
}
}
Now I want to write a loop to iterate through it so that I can print every element on the list :)
Basically what I am trying to do is, I want to get the locations from the user and then I will print them.
Please help .

Linked list. Input coordinates until you enter zero.
#include <stdio.h>
#include <stdlib.h>
struct ListItem
{
int x;
int y;
struct ListItem *next;
};
int main()
{
int x1 =0;
int y1 = 0;
int iCount = 0; // keep count of the structures allocated
int iEach = 0;
struct ListItem root = { 0, 0, NULL};// declare and initialize the first structure
struct ListItem* pFreeListItem = NULL;// declare a pointer and initialize it null. use for freeing memory later
struct ListItem* pListItem = &root;// declare a pointer and initialize it to point to the first structure
while ( 1) { // the main loop
printf("Please enter the x coordinate: ");
scanf(" %d", &x1);
printf("Please enter the y coordinate: ");
scanf(" %d", &y1);
pListItem->x = x1; // use the pointer to assign the coordinate
pListItem->y = y1;
iCount++; // keep track of the number of structures
printf("Input complete for location number %d\n", iCount);
printf("Enter 0 to exit or any other number to continue: ");
scanf(" %d", &y1);
if ( y1 == 0) { // exit the loop if zero is entered
break;
}
else { // if zero was not entered
pListItem->next = malloc ( sizeof ( struct ListItem));// allocate memory for the next structure
if ( pListItem->next == NULL) {
//allocation failed
exit (1);
}
pListItem = pListItem->next; // set the pointer to point to the new 'next' structure
pListItem->next = NULL; // set this to null as no memory has yet been allocated
}
}
pListItem = &root; // set the pointer to the original structure root
for ( iEach = 0; iEach < iCount; iEach++) // loop through each structure. icount holds the number of structures
{
printf("Location number %d is : (%d,%d)\n", iEach + 1, pListItem->x, pListItem->y);
pListItem = pListItem->next; // set the pointer to the next structure
}
pListItem = root.next; // set the pointer to the first allocated structure
for ( iEach = 1; iEach < iCount; iEach++) // loop through each structure
//start with 1 as the first structure was not allocate and does not need to be freed. icount holds the number of structures
{
pFreeListItem = pListItem->next; // set the free pointer to the next structure
free ( pListItem); // free the memory for the structure
pListItem = pFreeListItem; // point to the free pointer
}
}
EDIT: this code will show the address of the pointers and maybe that will help clarify what is going on
else { // if zero was not entered
pListItem->next = malloc ( sizeof ( struct ListItem));// allocate memory for the next structure
if ( pListItem->next == NULL) {
//allocation failed
exit (1);
}
printf ( "pListItem points to %p and pListItem->next points to %p\n", pListItem, pListItem->next);
pListItem = pListItem->next; // set the pointer to point to the new 'next' structure
pListItem->next = NULL; // set this to null as no memory has yet been allocated
printf ( "NOW pListItem points to %p and pListItem->next points to %p\n", pListItem, pListItem->next);
}

Here's a toy program that works, demonstrating a list stored in an array.
Actually compiles with no warnings - gcc -Wall -Werror -std=c99 l.c
The dynamically allocated version using calloc, works to, if you want dynamic memory, so you can add to the list later.
ladm#ash:~/src/scratch> ./a.out|head | sed 's/^/ /'
array[ 0] : (1,1)
array[ 1] : (2,2)
array[ 2] : (3,3)
Your location is : (3,3)
Your location is : (2,2)
Your location is : (1,1)
array[ 2] : (3,3)
array[ 1] : (2,2)
array[ 0] : (1,1)
ladm#ash:~/src/scratch> cat l.c | sed 's/^/ /'
#include <stdio.h>
#include <assert.h>
typedef struct ListItem
{
int x;
int y;
struct ListItem *next;
} ListItem;
void getCoord(int *x, int *y) {
static int num = 1;
*x = *y = num++;
}
int main( int argc, char **argv) {
const int N = 3;
ListItem listN[ N];
/* ListItem *listN = calloc( N, sizeof( ListItem)); */ /* Dynamic allocation method */
/* First Coordinate */
listN[ 0].next = NULL; /* Add item at front of list */
getCoord( &listN[ 0].x, &listN[ 0].y); /* Does the scanf stuff */
/* Add new coords to the list */
for (int i=1; i < N; i++) {
getCoord( &listN[ i].x, &listN[ i].y); /* Does the scanf stuff */
listN[ i].next = &listN[ i-1]; /* Add item at front of list */
}
/* List built */
{
ListItem *first = &listN[ N-1];
/* Dump all the coords in backing store */
for (int i = 0; i < N; i++) {
printf("array[ %d] : (%d,%d)\n", i, listN[ i].x, listN[ i].y);
}
/* Print list following pointers - should be reversed */
for (ListItem *l = first; l != NULL; l = l->next) {
printf("Your location is : (%d,%d)\n", l->x, l->y);
}
/* Dump all the coords in backing store reversed */
for (int i = N-1; i >= 0; --i) {
printf("array[ %d] : (%d,%d)\n", i, listN[ i].x, listN[ i].y);
}
}
}

If you know the number of locations you will have, you better use an array or matrix, like:
int x[30];
int y[30];
or
int location[60];
or
int location[2][30];
And use a for loop to iterate over the elements.
If you don't know the number of locations, then you wish to search for LinkedList (or ArrayList) implementation in C. There are plenty of material on Internet teaching how to use those data structures.

A good way to iterate through a list would be making functions like give_successor and is_after_last, then using it in a for loop, like that:
struct ListItem *l;
struct ListItem *head;
for (l = head; !(is_after_last(l)); l = give_successor(l)) {
do_stuff(l);
}
Implementation of is_after_last may vary depending on implementation of the list: you might want to check if l == NULL or if l points to artificial element at the end of the list.
Function give_successor looks like that:
struct ListItem *give_successor(l) {
if (l == NULL)
return NULL;
return l->next
}
However, I recommend using tables and libraries like those.

Related

Can anyone explain to me why each is pointing to the same thing?

I was just messing around in C when I encountered this problem:
typedef struct {
int val;
} Test;
typedef struct {
Test* p;
} P;
int main() {
int a = 0;
P list[5];
while (a <= 5) {
Test new_test = {a};
list[a].p = &new_test;
++a;
}
for (int i = 0; i < 5; ++i) {
printf("%d ", list[i].p->val);
}
}
For some reason each value in the array is pointing to the same thing.
The output I expected was something like:
1 2 3 4 5
Instead I got:
5 5 5 5 5
Anyone know the reason for this?
The variable
Test new_test = {a};
is local to the block used as the loop body and its life ends on end of execution of the block, so dereferencing pointers pointing at the after execution of the block ends is illegal.
It looks like the compiler decided to reuse some of the memory space for each iteration.
To avoid this, allocate objects in a way that persists until you finish using them.
Also list[5] is out-of-range for P list[5]; and accessing the "element" is illegal. You have to allocate more elements to avoid out-of-range access.
/* add required headers */
#include <stdio.h> /* printf() */
#include <stdlib.h> /* malloc() */
typedef struct {
int val;
} Test;
typedef struct {
Test* p;
} P;
int main() {
int a = 0;
P list[5 + 1]; /* allocate enough element */
while (a <= 5) {
/* allocate non-local object */
Test* new_test = malloc(sizeof(*new_test));
if (new_test == NULL) return 1;
new_test->val = a;
list[a].p = new_test;
++a;
}
for (int i = 0; i < 5; ++i) {
printf("%d ", list[i].p->val);
}
}

C - pointing members of array of struct into another array ( no duplicate struct data just point to it )

I have two identical arrays of struct , one in reverse order.
The problem is that i don't want duplicate the same data into the two arrays , i would a reversed array with elements pointing elements of the first array in a way that i can edit the members of struct of first array or from the reversed array taking effect in both.
you can view the source and run it online here https://onlinegdb.com/SJbepdWxS
#include <stdio.h>
typedef struct point{
int id;
float x,y,z;
} point;
void printPoints(point *pts,int len){
int i = 0;
while (pts !=NULL && i < len){
printf("id %d x %f y%f z %f\n",pts->id,pts->x,pts->y,pts->z);
pts++;
i++;
}
}
void translatePoints(point *pts,int len,float t){
int i = 0;
while (pts !=NULL && i < len){
pts->x = pts->x + t;
pts->y = pts->y + t;
pts->z = pts->z + t;
pts++;
i++;
}
}
void reversePoints(point *pts, int len, point *rev){
int i = 0;
int j = len;
while (i < len){
j=len-i-1;
rev[j]=pts[i];
i++;
}
}
int main()
{
int i;
int t1=200;
int t2=300;
int len=3;
point points[len];
point rev_points[len];
for(i=0; i<len ; i++){
points[i].id=i;
points[i].x=10+i;
points[i].y=20+i;
points[i].z=30+i;
}
//point * pts = points;
printf("\nprint points \n\n");
printPoints(points,len);
printf("\ntranslate points %d...\n\n",t1);
translatePoints(points,len,t1);
printf("\nprint points\n\n");
printf("\nreverse points to rev_points\n");
reversePoints(points,len,rev_points);
printf("\nprint rev_points \n\n");
printPoints(rev_points,len);
printf("\ntranslate rev_points %d...\n\n",t2);
translatePoints(rev_points,len,t2);
printf("\nprint rev_points\n\n");
printPoints(rev_points,len);
printf("\nprint points\n\n");
printPoints(points,len);
return 0;
}
I expect that struct values of both arrays change when i change value in one of the two array.
But changing values of struct in the first array , the second array not changes and the other way around.
One way to look at this is a set of points and two permutations on the set. This sets up a points array, which is used as a set, and forward_points and reverse_points as arrays of pointers to the point array that we are going to use as permutations.
#include <stdio.h>
struct Point {
int id;
float x,y,z;
};
/* Print a point. */
static void printPoint(struct Point *point) {
printf("id %d x %f y%f z %f\n",point->id,point->x,point->y,point->z);
}
/* These print out an array of pointers to point. */
static void printPointsRef(struct Point **ref, int len) {
struct Point **end = ref + len;
while(ref < end) printPoint(*(ref++));
}
/* This translates all the `pts` up to `len` by `(1,1,1)*t`. */
static void translatePoints(struct Point *pts, int len, float t) {
struct Point *end = pts + len;
while(pts < end) {
pts->x = pts->x + t;
pts->y = pts->y + t;
pts->z = pts->z + t;
pts++;
}
}
/* Helper function to `main`. */
static void printPoints(struct Point **forward_points,
struct Point **reverse_points, int len) {
printf("print points\nprint points forward:\n");
printPointsRef(forward_points,len);
printf("print points reverse:\n");
printPointsRef(reverse_points,len);
printf("\n");
}
int main(void)
{
const int len = 3;
/* This is the actual points structure. */
struct Point points[len];
/* These are arrays of pointers to points; they are
permutations of `points`. */
struct Point *forward_points[len], *reverse_points[len];
int i;
const int t1=200;
for(i=0; i<len; i++) {
/* Initialise element `i` of `points`. */
points[i].id=i;
points[i].x=10+i;
points[i].y=20+i;
points[i].z=30+i;
/* Initialise element `i` of `forward_points`
to point to `points[i]`, and `backward_points`
to point the other way (it doesn't matter that
the backwards points are uninitialised, they
will be.) */
forward_points[i] = &points[i];
reverse_points[i] = &points[len - 1 - i];
}
printPoints(forward_points, reverse_points, len);
/* Translation is a vector space operation and doesn't
care about order; we just do it on the original points. */
printf("translate points %d...\n\n",t1);
translatePoints(points,len,t1);
printPoints(forward_points, reverse_points, len);
return 0;
}
Of course, there is no integrity constraints on the pointers; nothing stopping one from pointing at anything, null, the same elements, or anything else.
I added an other struct with one element that is a pointer
typedef struct ptr_point{
point * p;
} ptr_point;
I edited the function reversePoints
void reversePoints(point *pts, int len, ptr_point *rev){
// This function is used only to test pointers
int i = 0;
int j = len;
while (i < len){
j=len-i-1;
rev[j].p = &pts[i];
i++;
}
}
and added another function to print ptr_points
void printPtrPoints(ptr_point *pts,int len){
int i = 0;
while (i < len){
printf("id %d x %f y%f z %f\n",pts->p->id,pts->p->x,pts->p->y,pts->p->z);
pts++;
i++;
}
}
and declaring the second array as ptr_point array
ptr_point rev_points[len];
In conclusion : now data in the second array are not replicated but pointing to element structure of the first array.
The need to not replicate data arise in presence of millions of coordinate points that if replicate more than one time , sorting it for example by x, y, z and so on , occupe much memory with the difficulty of managing .
This fix however forces me to use structures->type in order to change the access mode to read or set values.
I don't know if this is the best solution but it has solved the problem for not duplicate the data.
you can run the source with fixes here: https://onlinegdb.com/SknP_i-eS
Thank you all for the advice.

How to properly free() my mallocs in c

I need to have a dynamic array so I have used malloc in my code...However I don't know how to successfully free the memory afterwards. Somewhere in my code I believe I have a pointer re-assignment which leads to dangling pointer error (when i do child2=child1). Does anyone know how to free my mallocs properly? Thanks in advance.
My actual code is below:
typedef struct Edge//per solution
{
int label;//label
float weight;//energy of each edge
} edge;
// creating the chrom structure
typedef struct Chrom
{
edge **gene;
float fitness_score;
}
In one of my functions i have the following, where pop_size and num_nodes was previously calculated as 100 and 10 respectively.
Chrom* child1;
Chrom* child2;
//allocate memory of child
child1 = malloc(num_nodes * sizeof(child1));
child2 = malloc(num_nodes * sizeof(child2));
if(child1 == NULL||child2 == NULL)
printf("ERROR1: Memory allocation failed!");
for(x = 1; x <= num_nodes; x++)
{
child1[x].gene = malloc(num_nodes * sizeof(edge*));
child2[x].gene = malloc(num_nodes * sizeof(edge*));
if(child1[x].gene == NULL||child2[x].gene == NULL)
printf("ERROR2: Memory allocation failed!");
for(y = 0; y < num_nodes; y++)
{
child1[x].gene[y] = malloc(num_nodes * sizeof(edge));
child2[x].gene[y] = malloc(num_nodes * sizeof(edge));
if(child1[x].gene[y] == NULL||child2[x].gene[y] == NULL)
printf("ERROR3: Memory allocation failed!");
}
}
//do something...
for(i=0; i<pop_size; i++)
for(x=0; x<num_nodes; x++)
for(y=0;y<num_nodes;y++)
child2[i].gene[x][y].label=child1[i].gene[x][y].label;
free(child1);//can i free the memory like this?
free (child2);// will it automatically do all 'arrays'?
Also, must I first check if memory was allocated properly before freeing it?
child1 = malloc(num_nodes * sizeof(child1));
this is incorrect. You are allocating space for num_nodes pointers (child1 is a pointer to Chrom). You want to allocate space for num_nodes Chrom instances.
Change it to
child1 = malloc(num_nodes * sizeof(*child1));
First of all, you allocate space for Chrom pointers, not the space for Chrom structures so I am surprised that child1[x].gene works without crashing but to only answer the questions posed as comments in your code,
free(child1);//can i free the memory like this?
free (child2);// will it automatically do all 'arrays'?
child1 is an array of pointers and each of those pointers points to allocated memory which will be lost when you free(child1). I would free each pointer child1[x].gene first and then free child1. Same thing for child2.
This is probably close to what you want:
typedef struct Edge//per solution
{
int label;//label
float weight;//energy of each edge
} edge;
// creating the chrom structure
typedef struct Chrom
{
edge *gene; // changed from edge**
float fitness_score;
};
int main(void)
{
int num_nodes = 3;
int x;
struct Chrom* child1;
// if you want num_nodes Chrom entries
child1 = malloc(num_nodes * sizeof(struct Chrom));
// Allocating individual edges (I don't know why you declare edge** gene
// so I will assume that what you intended was edge* gene
for(x = 1; x <= num_nodes; x++)
{
child1[x].gene = (edge*)malloc(sizeof(struct Edge));
}
// deallocate your memory
for(x = 1; x <= num_nodes; x++)
{
free(child1[x].gene);
}
// free your array of Chroms
free(child1);
return 0;
}
Here is what the code could be if you want a 2D array of edegs within each Chrom; Also, there is a bug in my previous answer; x should be initialized to zero in the for loop rather than to 1 because this will cause an array index out of bounds and use lower-than instead of lower-than-or-equal. (WARNING: I only tested it slightly):
typedef struct Edge//per solution
{
int label;//label
float weight;//energy of each edge
} edge;
// creating the chrom structure
typedef struct Chrom
{
edge **gene;
float fitness_score;
};
int main(void)
{
int num_nodes = 3;
int num_edges_x = 2;
int num_edges_y = 3;
int x, j;
struct Chrom* child1;
// if you want num_nodes Chrom entries
child1 = malloc(num_nodes * sizeof(struct Chrom));
// Allocating 2D array of edges for each Chrom
// USE zero-based indexing.
for(x=0; x < num_nodes; x++)
{
child1[x].gene = (edge**)malloc(num_edges_x * sizeof(edge*));
// initialise you array of edges
for (j=0; j<num_edges_x; j++)
{
child1[x].gene[j] = (edge*)malloc(num_edges_y * sizeof(edge));
}
}
// Use a child1[x].gene[x][y]
child1[0].gene[0][0].label = 3;
child1[0].gene[0][0].weight = 7.2F;
printf("\nlabel: %d - weight: %f", child1[0].gene[0][0].label, child1[0].gene[0][0].weight);
child1[1].gene[0][0].label = 1;
child1[1].gene[0][0].weight = 12.4F;
printf("\nlabel: %d - weight: %f", child1[1].gene[0][0].label, child1[1].gene[0][0].weight);
child1[1].gene[1][0].label = 5;
child1[1].gene[1][0].weight = 112.6F;
printf("\nlabel: %d - weight: %f", child1[1].gene[1][0].label, child1[1].gene[1][0].weight);
// deallocate your memory
for(x =0; x < num_nodes; x++)
{
for (j=0; j<num_edges_x; j++)
{
free(child1[x].gene[j]);
}
free(child1[x].gene);
}
free(child1);
return 0;
}

Return two values with pop function from priority queue

I have priority queue which returns with pop function just int y, but I need return int x and int y. So I found, that I can use struct (struct point) to return two values from function, but I can't figure, how it implement (rewrite int out to struct and use it in main).
Structs:
typedef struct { int x; int y; int pri; } q_elem_t;
typedef struct { q_elem_t *buf; int n, alloc; } pri_queue_t, *pri_queue;
struct point{int PointX; int PointY;};
Pop function:
int priq_pop(pri_queue q, int *pri)
{
int out;
if (q->n == 1) return 0;
q_elem_t *b = q->buf;
out = b[1].y;
if (pri) *pri = b[1].pri;
/* pull last item to top, then down heap. */
--q->n;
int n = 1, m;
while ((m = n * 2) < q->n) {
if (m + 1 < q->n && b[m].pri > b[m + 1].pri) m++;
if (b[q->n].pri <= b[m].pri) break;
b[n] = b[m];
n = m;
}
b[n] = b[q->n];
if (q->n < q->alloc / 2 && q->n >= 16)
q->buf = realloc(q->buf, (q->alloc /= 2) * sizeof(b[0]));
return out;
}
Use in main():
/* pop them and print one by one */
int c;
while ((c = priq_pop(q, &p)))
printf("%d: %d\n", p, c);
I'm starting with C, so I will be gratefull for any help.
You can declare your structures like so:
typedef struct queue_element_struct { // It's good practice to name your structs
int x,y;
int pri;
} queue_element_t;
typedef struct priority_queue_struct {
queue_element_t *buf;
int n, alloc;
} pri_queue_t, *pri_queue; // Don't know what `*pri_queue` is for
Then change your function to return a pointer to a queue_element_t structure
queue_element_t * priq_pop(pri_queue q, int *pri)
Change
int out;
if (q->n == 1) return 0;
q_elem_t *b = q->buf;
out = b[1].y;
To
// Create new pointer to queue_element_t structure
// that will be returned by this function
queue_element_t *out;
out = (queue_element_t *) malloc(sizeof(queue_element_t));
if (! out) {
// Could not allocate
}
if (q->n == 1) return 0;
// Set data from queue
out->x = q->buf[1].x;
out->y = q->buf[1].y;
I don't know exactly what your function does, but that is how you return a structure in C.
You said you're just starting with C, so I recommend:
“Code Complete” book by Steve McConnell. It is very useful to comment your code (no matter how small)
properly name your variables: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Variable_Names
learn about pointers. All you can read about them, read it.
You could make your queue data of type struct point
Structs:
typedef struct point{int PointX; int PointY;} q_data;
typedef struct { q_data d; int pri; } q_elem_t;
typedef struct { q_elem_t *buf; int n, alloc; } pri_queue_t, *pri_queue;
Pop function:
q_data priq_pop(pri_queue q, int *pri)
{
q_data out = {0,0};
if (q->n == 1) return out;
q_elem_t *b = q->buf;
out = b[1].d;
if (pri) *pri = b[1].pri;
/* pull last item to top, then down heap. */
--q->n;
int n = 1, m;
while ((m = n * 2) < q->n) {
if (m + 1 < q->n && b[m].pri > b[m + 1].pri) m++;
if (b[q->n].pri <= b[m].pri) break;
b[n] = b[m];
n = m;
}
b[n] = b[q->n];
if (q->n < q->alloc / 2 && q->n >= 16)
q->buf = realloc(q->buf, (q->alloc /= 2) * sizeof(b[0]));
return out;
}
Use in main():
/* pop them and print one by one */
q_data c;
while ((c = priq_pop(q, &p)))
printf("%d: %d, %d\n", p, c.PointX, x.PointY);
Something like this should do the trick. I didn't test it though, so there might be errors.
good luck!
In C++ you would use a vector or something similar to store an array of Unfortunately you can't fall back on this.
Why not use an array though, you could have your queue be an array of q_elem_t?
q_elem_t *my_array = q_elem_t array[100]; //pseudo code
For more about making an array of structs see here: How do you make an array of structs in C?
The only thing with an array is that you need to either malloc an arbitrary size (i.e. array[100]) or you need to dynamically control the memory of the array. If you are starting out it might just be best to declare an array of size 100.
To me it looks like the confusion is in the lack of datastructure. Array is a good starting point but if you want to learn more check out linked lists and things like that.

Memory allocation to struct in pure C

I have a structure , which present my element of data
struct myElement
{
int field1;
int field2;
int field3;
};
another structure, which contain array of this elements and some another data
struct myArray
{
struct myElement *elements;
int someData;
};
and I need to have array of this arrays like that
struct myArray *myMatrix;
But I have a problem with memory allocation. Count of elements in myArray's can be different, in myMatrix too, so I need to allocate memory dynamicaly. What is the corret way to allocate and deallocate memory in this situation?
Here's a small example of how you would allocate (malloc) and deallocate (free) a dynamic struct myElement array in a struct myArray. Note also that you will need to keep track of the size of the array, so I added size_t elements_len; to struct myArray (excuse the combination of camelCase and underscores - I use underscores in C, but didn't want to modify your identifiers):
#include <stdlib.h>
struct myElement
{
int field1;
int field2;
int field3;
};
struct myArray
{
struct myElement *elements;
size_t elements_len;
int someData;
};
void allocate_elements(struct myArray *m, size_t length)
{
m->elements = malloc(length * sizeof( *m->elements) );
m->elements_len = length;
}
void free_elements(struct myArray *m)
{
free(m->elements);
m->elements = NULL; /* point to NULL to signify no array allocated */
m->elements_len = 0; /* length of 0 also signifies no elements/no array */
}
int main(void)
{
struct myArray ma;
allocate_elements(&ma, 5);
free_elements(&ma);
return 0;
}
Apply similar logic in order to have a dynamic array of struct myArray. You would malloc enough memory for X amount of struct myArrays, then for each struct myArray element in that array, you would call allocate_elements. Then iterate through each element in the array once you're done with it and call free_elements.
Use malloc to allocate the memory:
myMatrix = malloc(sizeof(myArray)*dim1);
for (int i = 0; i < dim1; i++)
myMatrix[i].elements = malloc(sizeof(myElement)*dim2);
Use free in similar fashion to release the memory once you're done with it.
struct myArray *myMatrix = malloc(Nentries * sizeof(*myMatrix));
if (myMatrix != 0)
{
for (int i = 0; i < Nentries; i++)
{
myMatrix[i].elements = malloc(Nelements[i] * sizeof(myElement));
if (myMatrix[i].elements != 0)
{
for (int j = 0; j < Nelements[i]; j++)
{
myElement *e = &myMatrix[i].elements[j];
e->field1 = 0;
e->field2 = 1;
e->field3 = 2;
}
myMatrix[i].someData = 37;
}
}
}
I'm assuming that Nentries says how many elements there are in the matrix, and that each element of the array Nelements indicates how many elements are in the corresponding element of the matrix. The code tests for successful memory allocation, but does not react to allocation failure.
int num_elements = 1234; // whatever
struct myArray *myMatrix;
myMatrix = malloc (num_elements * sizeof (*myMatrix));
if (!myMatrix)
// error
// subsequent use of myMatrix is just like it had been statically dimensioned:
myMatrix [0].someData = 343;
myMatrix [1].someData = 323;
You need to use malloc and free functions to dynamically allocate and free the memory. Please use the following as a reference.
#include <stdio.h>
#include <stdlib.h>
int main()
{
struct myElement {
int field1;
int field2;
int field3;
};
struct myArray {
struct myElement *elements;
int someData;
};
struct myArray *myMatrix = NULL;
int n_myarray = 0;
int n_elements = 0;
int i, j;
printf("How many myArray's do you want? ");
scanf("%d", &n_myarray);
printf("How many elements do you want in each array? ");
scanf("%d", &n_elements);
/* memory allocation starts here */
if ((myMatrix = (struct myArray *) malloc((int)sizeof(struct myArray) * n_myarray)) == NULL) {
printf("ERROR: unable to allocate array\n");
return 1;
}
for (i=0 ; i<n_myarray ; i++) {
if ((myMatrix[i].elements = (struct myElement *) malloc((int)sizeof(struct myElement) * n_elements)) == NULL) {
printf("ERROR: unable to allocate array elements\n");
free(myMatrix);
return 1;
}
/* initialization of other members of struct myArray goes here */
myMatrix[i].someData = 123;
/* initialization of members of struct myElement goes here */
for (j=0 ; j<n_elements ; j++) {
myMatrix[i].elements[j].field1 = 123;
myMatrix[i].elements[j].field2 = 123;
myMatrix[i].elements[j].field3 = 123;
}
}
/* do your calculations here */
/* I'm printing the values */
for (i=0 ; i<n_myarray ; i++) {
printf("myMatrix[%d].someData : %d \n", i, myMatrix[i].someData);
for (j=0 ; j<n_elements ; j++) {
printf("myMatrix[%d].elements[%d].field1 : %d \n", i, j, myMatrix[i].elements[j].field1);
printf("myMatrix[%d].elements[%d].field2 : %d \n", i, j, myMatrix[i].elements[j].field2);
printf("myMatrix[%d].elements[%d].field3 : %d \n", i, j, myMatrix[i].elements[j].field3);
}
}
/* memory deallocation (free) starts here */
for (i=0 ; i<n_myarray ; i++) {
free(myMatrix[i].elements);
}
free(myMatrix);
return 0;
}
> ./a.out
How many myArray's do you want? 2
How many elements do you want in each array? 5
myMatrix[0].someData : 123
myMatrix[0].elements[0].field1 : 123
myMatrix[0].elements[0].field2 : 123
myMatrix[0].elements[0].field3 : 123
myMatrix[0].elements[1].field1 : 123
myMatrix[0].elements[1].field2 : 123
myMatrix[0].elements[1].field3 : 123
myMatrix[0].elements[2].field1 : 123
myMatrix[0].elements[2].field2 : 123
myMatrix[0].elements[2].field3 : 123
myMatrix[0].elements[3].field1 : 123
myMatrix[0].elements[3].field2 : 123
myMatrix[0].elements[3].field3 : 123
myMatrix[0].elements[4].field1 : 123
myMatrix[0].elements[4].field2 : 123
myMatrix[0].elements[4].field3 : 123
myMatrix[1].someData : 123
myMatrix[1].elements[0].field1 : 123
myMatrix[1].elements[0].field2 : 123
myMatrix[1].elements[0].field3 : 123
myMatrix[1].elements[1].field1 : 123
myMatrix[1].elements[1].field2 : 123
myMatrix[1].elements[1].field3 : 123
myMatrix[1].elements[2].field1 : 123
myMatrix[1].elements[2].field2 : 123
myMatrix[1].elements[2].field3 : 123
myMatrix[1].elements[3].field1 : 123
myMatrix[1].elements[3].field2 : 123
myMatrix[1].elements[3].field3 : 123
myMatrix[1].elements[4].field1 : 123
myMatrix[1].elements[4].field2 : 123
myMatrix[1].elements[4].field3 : 123
>
Please ensure the following:
for every malloc there should be a free
before using the memory that was allocated using malloc you must check whether malloc successfully allocated the memory block you've requested.
Something like this should work though it is not a great solution with so many seperate allocations, further down is a better solution. I have tried to make variable names descriptive of what they hold.
int arrayOfSubArrayLengths={9,5,10,50,...};
int lengthOfMyMatrix=something;
myMatrix= (myArray*) malloc( sizeof(myArray) * lengthOfMyMatrix);
for(int i=0; i<lengthOfMyMatrix; ++i)
{
myMatrix[i].elements=new myElement[arrayOfSubArrayLengths];
myMatrix[i].someData=whatever;
}
to delete:
for(int i=0; i<lengthOfMyMatrix; ++i)
{
free( myMatrix[i].elements );
}
free( myMatrix );
However as I said that is not a great solution with so many allocations. It could cause some severe memory fragmentation depending on how large lengthOfMyMatrix is. Also so many calls to the allocator could slow things down depending once again on the size of lengthOfMyMatrix.
Here is a better solution:
int arrayOfSubArrayLengths={9,5,10,50,...};
int lengthOfMyMatrix=something;
int sumOfSubArrayLengths=someNumber;
myArray* fullArray=(myElement*) malloc( sizeof(myElement) * sumOfSubArrayLengths);
myMatrix= (myArray*) malloc( sizeof(myArray) * lengthOfMyMatrix);
int runningSum=0;
for(int i=0; i<lengthOfMyMatrix; ++i)
{
myMatrix[i].elements = &fullArray[runningSum];
runningSum += arrayOfSubArrayLengths[i];
myMatrix[i].someData = whatever;
}
to delete:
free( fullArray );
free( myMatrix );
In this fashion there are only two calls to the allocator no matter the various lengths. So there is far more memory fragmentation and less allocation overhead time.
The one downside to the second method is that if you are not careful with bounds checking it is very easy to corrupt data in the array without knowing since the memory 'belongs' to you and thus the OS will not kick you for an access violation.

Resources