Allocating an array of structures within an array of structures - c

How can I allocate with malloc and array of structures within and array of structures?
for expample:
struct car_t{
int price;
float kmsDriven;
};
struct garage_t{
int locationX;
int locationY;
struct car_t * car;
}
There's an array of garages, which every one of them has an array of cars.

You will have to use a loop:
#define N 42
#define M 17
struct garage_t *a = malloc(sizeof *a * N);
for (int i = 0; i < N; i++) {
a[i].car = malloc(sizeof (*a[i].car) * M);
}

Just allocate as usual, one by one.
int garage_num = 3, car_num = 5;
int i;
struct garage_t *garage;
garage = malloc(sizeof(struct garage_t) * garage_num);
for (i = 0; i < garage_num; i++) {
garage[i].car = malloc(sizeof(struct car_t) * car_num);
}
You should check if malloc()s are successful for actual use.

Related

passing back values from array in struct by ref

struct myStruct
{
int* arr;
int size;
};
void get_back(struct myStruct* my ,int* arr, int* size)
{
arr = my->arr;
*size = my->size;
}
int main()
{
struct myStruct my;
my.arr = (int*) malloc(3 * sizeof(int));
my.arr[0] = 20;
my.arr[1] = 200;
my.arr[2] = 2000;
my.size = 3;
int* ret_arr = NULL;
int size;
get_back(&my, ret_arr, &size);
free(my.arr);
return 1;
}
The goal of my simple program is to get back the values from my.arr into ret_arr, since ret_arr=nullptr, do I need to allocate the memory and than copy it into the array inside get_back function?
or I can just point to the existing array inside "my" struct?
This is my current solution, I copy the values.
struct myStruct
{
int* arr;
int size;
};
int* get_back(struct myStruct* my , int* size)
{
int *arr = (int*)malloc(3 * sizeof(int));
for (int i = 0; i < my->size; i++)
{
arr[i] = my->arr[i];
}
*size = my->size;
return arr;
}
int main()
{
myStruct my;
my.arr = (int*) malloc(3 * sizeof(int));
my.arr[0] = 20;
my.arr[1] = 200;
my.arr[2] = 2000;
my.size = 3;
int* ret_arr = NULL;
int size;
ret_arr = get_back(&my, &size);
free(my.arr);
free(ret_arr);
return 1;
}
Seeing as you're freeing the array, you probably want to copy the contents over with memcpy (from string.h).
You will also need to include stdlib.h for malloc.
#include <string.h>
#include <stdlib.h>
// Struct definition goes here
void get_back(struct myStruct* my, int** arr, int* size)
{
*arr=malloc(my->size*sizeof(int)); //Allocate space for integers
memcpy(*arr, my->arr, my->size*sizeof(int)); //Copy integers to new array
*size=my->size;
}
The function needs to take a pointer to the pointer in order to be able to modify it.
Additionally, your main function will need to be modified too.
int main()
{
struct myStruct my; // Structs are not types.
my.arr = (int*) malloc(3 * sizeof(int));
my.arr[0] = 20;
my.arr[1] = 200;
my.arr[2] = 2000;
my.size = 3;
int* ret_arr = NULL;
int size;
get_back(&my, &ret_arr, &size); //Need to pass ret_arr by reference
free(my.arr);
return 1;
}
Use std::vector, it's very comfortable and has many useful algorithms, there is std::copy function to copy from one vector to another, take a look at your task with a help of vectors:
#include <vector>
#include <iostream>
struct myStruct
{
std::vector<int> arr;
};
int main()
{
myStruct my;
my.arr.push_back(20);
my.arr.push_back(200);
my.arr.push_back(2000);
std::vector<int> ret_arr;
std::copy(my.arr.begin(), my.arr.end(), std::back_inserter(ret_arr));
return 1;
}
And the result is on screen:
If you want to use C language then you should pass pointer on pointer(int** arr) to get right pointing after leaving scope. I will show two methods, first just to point on already allocated memory:
void get_back_pointers(myStruct* my ,int** arr, int* size)
{
*arr = my->arr;
*size = my->size;
}
Other is for deep copy, to allocate new array and copy data to it:
void get_back_copy(myStruct* my ,int** arr, int& size)
{
*arr = (int*) malloc(3 * sizeof(int));
memcpy( *arr, my->arr, my->size * sizeof(int) );
size = my->size;
}
After get_back_copy passed arr will be needed to free its memory. In debugger you can see results that my.arr and ret_arr have one address but ret_arr2 has another because it's allocated in new memory:

What is the correct way to allocate this nested structures?

I'm having some trouble trying to figure out how to allocate and free the memory for this structures.
I need to use this to create FiniteTable's to use in Newton Interpolation.
typedef struct{
unsigned int empty;
float value;
}FiniteTableValue;
The fist one is kind of a Node that has the real value.
typedef struct{
FiniteTableValue *column;
unsigned int length;
}FiniteTableRow;
FiniteTableRow keeps an array of FiniteTableValues.
typedef struct{
FiniteTableRow *row;
unsigned int length;
}FiniteTable;
FiniteTable then keeps an array of FiniteTableRows.
typedef struct{
FiniteTable *tables;
unsigned int length;
}FiniteTableList;
FiniteTableList is the list of FiniteTable's
I tried to debugg it with valgrind and it seems I always access some address that I didn't allocate.
Also, is this the right way to deallocate all ?
FiniteTableList *ftl ...
...
for(int i = 0; i < ftl->length; i++){
FiniteTable table = ftl->tables[i];
for(int j = 0; j < table.length; j++){
FiniteTableRow row = table.row[j];
free(row.column);
}
free(table.row);
}
free(ftl->tables);
free(ftl);
In your deallocation example the Ftl object is a FiniteTableList rather than a pointer (FiniteTableList *). I think you meant to write:
FiniteTableList ftl ...
To allocate memory for a FiniteTableList structure you'd do something like this:
/* Assuming every table in the list will have num_rows rows and num_columns columns. */
FiniteTableList *
allocate_table_list (int num_rows, num_columns, int num_tables)
{
FiniteTableList * res = malloc (sizeof *res);
res->tables = malloc (num_tables * sizeof (*res->tables));
res->length = num_tables;
for (int t = 0; t < num_tables; t++)
{
FiniteTable table = res->tables[t];
table.row = malloc (num_rows * sizeof (*table.row));
table.length = num_rows;
for (int r = 0; r < num_rows; r++)
{
FiniteTableRow row = table.row[r];
row.column = malloc (num_columns * sizeof (*row.column));
row.length = num_columns;
}
}
return res;
}
If you want to zero-initialise the memory you allocate you can substitute the calls to malloc by calloc

2d dynamic array in structure

I'm learning for school and I found exam task:
"Create struct with fields:
2 integers,
two-dimensional flexible array (double or float) "
I did something like that:
struct my_struct{
int firstField;
int secondField;
int columns;
int rows;
double tab[columns][rows];
}
struct my_struct sample = {2, 2, 5, 4, {0.0}}
But it does not work.How should I create struct like that?
A struct cannot have a 2D VLA variable logic array nor a 2D FAM, flexible array member like with member double tab[columns][rows];. A struct can have a final of 1 dimensional FAM.
Code can get close to OP's goal of "Create struct with fields: 2 integers, two-dimensional flexible array (double or float) " by using a flexible array member that is an array of double *.
struct my_struct {
int columns;
int rows;
double *tab[/* row */];
};
This makes tab, not a 2D array but a 1D array of double *. This is usable like a 2D array with the [][] syntax.
First allocate not only memory for my_struct, but also for the appended array of double * pointers. Then allocate memory for the double array for each pointer.
As with all allocations, good to test if the allocation succeeded. Following simple uses assert(p);
I replaced working code with some TBD to allow for OP's learning experience.
struct my_struct *my_struct_alloc(int columns, int rows) {
struct my_struct *p = malloc(sizeof *p + sizeof *(p->tab) * TBD);
assert(p);
p->columns = TBD;
p->rows = TBD;
for (int r = 0; r < p->rows; r++) {
p->tab[r] = malloc(sizeof *(p->tab[r]) * TBD);
assert(p->tab[r]);
for (int c = 0; c < p->columns; c++) { // sample, fill array w/illustrative data
static int count = 0;
p->tab[r][c] = count++; // Access like a 2D array
}
}
return p;
}
void my_struct_print(struct my_struct *p) {
for (int r = 0; r < p->rows; r++) {
for (int c = 0; c < p->columns; c++) {
printf("%.0f ", p->tab[r][c]); // Access like a 2D array
}
puts("");
}
}
void my_struct_free(struct my_struct *p) {
if (p) {
for (int r = 0; r < p->rows; r++) {
free(p->tab[r]);
}
}
free(p);
}
int main() {
struct my_struct *p = my_struct_alloc(2, 3);
my_struct_print(p);
my_struct_free(p);
}
Output
0 1
2 3
4 5

How do I correctly assign a struct containing an array of int to an array of struct?

I want to know how to assign a struct containing an array of int to an array of structs. I keep getting the incorrect result no matter what new solution I think of.
I believe the problem lies in this piece of code:
struct Codes *create(int as) {
struct Codes *c = malloc(sizeof (struct Codes)+as * sizeof (int));
c->as = as;
for (int i = 0; i < as; i++) {
c->a[i] = i;
}
return c;
}
The whole code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
struct Codes {
int as;
int a[];
};
struct Code {
int as;
struct Codes *ci[];
};
struct Codes *create(int as) {
struct Codes *c = malloc(sizeof (struct Codes)+as * sizeof (int));
c->as = as;
for (int i = 0; i < as; i++) {
c->a[i] = i;
}
return c;
}
struct Code *and(int as, struct Codes *cd) {
struct Code *c = malloc(sizeof (struct Code)+as * sizeof (struct Codes));
for (int i = 0; i < as; i++) {
c->ci[i] = cd;
}
c->as = as;
return c;
}
int main(int argc, char **argv) {
struct Codes *cd;
cd = create(4);
struct Code *c;
c = and(2, cd);
for (int i = 0; i < c->as; i += 1) {
for (int j=0; j < c->ci[i]->as; j++) {
printf("%d \n", c->ci[i]->a[j]);
}
}
free(cd);
free(c);
}//main
Actual Result:
0
1
2
3
Expected Result:
0
1
2
3
0
1
2
3
struct Code *c = malloc(sizeof (struct Code)+as * sizeof (struct Codes)); is incorrect. The struct Code 's ci is an array of pointers , but you allocated space for an array of structs.
To fix this, either change to sizeof(struct Codes *), or preferably use the pattern of dereferencing the pointer to the type you're allocating space for:
struct Code *c = malloc( sizeof *c + as * sizeof c->ci[0] );
Also, for (int j; should be for (int j = 0; . Your code causes undefined behaviour by using uninitialized value of j, it's just chance that you happened to get the output you did. Using the gcc flag -Wextra would have diagnosed this error.

Accessing and setting array values within structs

I have a struct like this:
typedef struct {
int sizes[3];
float **vals[3]; // an array of size 3 of float ** pointers
} mystruct;
What I'm trying to do is set these array values in a function that takes a pointer to a mystruct.
void populateStruct(mystruct *s) {
int i, j, n;
for (n = 0; n < 3; n++) {
scanf("%d", &s->sizes[n]);
// Malloc the float pointers (**vals) based on the scanned sizes
s->vals[n] = (float **)malloc(s->sizes[n] * sizeof(float *));
for (i = 0; i < s->sizes[n]; i++)
s->vals[n][i] = (float *)malloc(s->sizes[n] * sizeof(float));
// Populate the float "arrays"
for (i = 0; i < s->sizes[n]; i++) {
for (j = 0; j < s->sizes[n]; j++) {
scanf("%f", &s->vals[n][i][j]);
}
}
}
}
Here is how I'm using the function in main:
int main() {
mystruct *s1;
populateStructure(s1);
return 0;
}
This code compiles fine, but I get a seg fault when I run it. C is not a strong point of mine, so I'm not too sure what I'm doing wrong.
How are you declaring your s structure and how are you passing it?
In your function where you call populateStruct you should probably declare s:
as mystruct s and call populateStruct(&s)
or
mystruct *s;
s = malloc(sizeof(mystruct));
populateStruct(s);
mystruct *s1;
s1 is only a pointer with unpredictable value. You didn't allocate memory for the struct you need.
Dereferencing a wild (uninitialized) pointer would cause segv.
You can modify your code to either:
mystruct s1;
populateStructure(&s1);
or
mystruct *s1 = (mystruct *)malloc(sizeof(mystruct));
populateStructure(s1);
( don't forget to free s1 in the second one)

Resources