How to correctly define an array of structures? - c

i have the following structure:
typedef struct Course {
int course_id;
char* course_name;
int prior_course_id;
StudentTree* students;
} Course;
and the following function i need to implement:
void createReport(FILE* courses[], int numOfCourses, FILE* studentFile, char* reportFileName
as you can see i get an array of FILE*, each cell contains different file pointer.
my intention is to create an array that each cell is Course* type, and initialize each cell with a Course struct containing the data read from the courses files.
what is the correct way to declare it inside the function?
do i need to dynamically allocate memory for it, or it can be done in compilation?
i've tried
Course* course_array[numOfCourses] = {NULL};
Course* course_array[numOfCourses] = NULL;
but it won't compile.
thanks for your help

You declare an array of structs the same way you declare an array of ints or FILE *s:
Type variableName[numberOfElements];
Before C99 (and barring compiler specific extensions), creating an array with a variable number of elements on the stack wasn't supported. So make sure that you are targeting the correct standard. In your case, assuming C99 support, the following should work:
Course *course_array[numOfCourses];
Because you intend to initialize each of the elements in the array, there is no need to zero them out.
You would then access the elements like this:
course_array[0] = malloc(sizeof(Course))
course_array[0]->course_id = 2;
/* etc. */
Now if you can't assume C99 support, things get a bit more tricky but not much:
Course *course_array = malloc(sizeof(Course *) * numOfCourses);
After that you can access course_array with the same array notation:
course_array[0] = malloc(sizeof(Course))
course_array[0]->course_id = 42;
/* etc. */
Once you're doing with the array, you'll need to make sure that you free any of the memory that you allocated:
for (i = 0; i < numOfCourses; i++) {
free(course_array[i]);
}
/* If you malloc'd course_array, then you need this too */
free(course_array);

Course* course_array[numOfCourses] = {NULL};
This is good, but it creates array of Course *. So you need to allocate memory for each pointer in course_array before accessing it.
Something like
course_array[0] = malloc(sizeof(Course));
course_array[0]->course_id = someid;

When you define the array in the first place, you shouldn't need to allocate memory. You're defining the array on the stack, and the elements of the array are just pointers.
I think what you should do is first define the array, and then initialize each element with a malloc call. For example:
Course* course_array[numOfCourses];
for(int i = 0; i < numOfCourses, i++) {
course_array[i] = (Course*)malloc(sizeof(Course));

My favorite way:
typedef struct {
int a;
char b;
float c;
}DATA;
//then use typdef'ed DATA to create array (and a pointer to same)
DATA data[10], *pData;
//then, in function, you can initialize the pointer to first element of array this way:
int main(void)
{
pData = &data[0];
return 0;
}
Your example code would look like this:
typedef struct {
int course_id;
char* course_name;
int prior_course_id;
StudentTree* students;
} COURSE;
//then in function:
COURSE course[numOfCourses]

Related

Can you create an array of Structure inside of another structure in C language?

Aim : To create a structure of element having certain properties. Then utilize that structure type by creating it's array in another structure.
struct Element
{
int i;
int j;
int x;
};
struct Sparse
{
int r;
int c;
int n;
struct Element *ele;
ele = (struct Element *)malloc(n*sizeof(struct Element));
};
What I wish to know is that which part of the code am I not allowed to write while creating a structure.
The common way to do this is:
struct Element
{
int i;
int j;
int x;
};
struct Sparse
{
int r;
int c;
int n;
struct Element ele[0]; // Make a zero length array
};
struct Sparse* MakeNewSparse(size_t num_ele)
{
struct Sparse* sparse = malloc(sizeof(*sparse) + num_ele*sizeof(struct Element));
return sparse;
}
This works because accessing off the end of a zero-length array is totally legal in C, provided you have allocated memory there.
In this example, we allocate enough space for the struct Sparse, and then enough more contiguous space for the array of struct Element.
After that, accessing element sparse->ele[5] is totally legal.
The line
ele = (struct Element *)malloc(n*sizeof(struct Element));
should not be part of the struct definition - that's something you do at runtime, along these lines:
struct Sparse s; // create new struct Sparse instance
s.n = get_some_size();
s.ele = malloc( s.n * sizeof *s.ele ); // no need for cast
struct in c is syntactically similar with types like int, char, etc. The definition of a struct is for compiler to know how to use variable declared with that struct such as struct Sparse var;. So the definition of a struct is not actually the code itself. It will be used at compile time.
However, malloc() is a function, which will be used at runtime, so it is nonsense to put malloc() in your struct definition.

How to properly declare/initialize/finalize dynamic array of structs with other dynamic arrays

So what i want to achieve is global variable which represents pointer to dynamic array of structs which has other pointers to dynamic arrays inside.
So i've declared everything in the header file like that:
/*** "GLOB.h" ***/
//Dynamic Array of fixed Arrays of 4 floats each
typedef float DArray1[][4];
//Dynamic Array of Integers
typedef int DArray2[];
//Struct
struct MyStruct
{
//pointer to DArray1
DArray1 * A1;
//pointer to DArray2
DArray2 * A2;
//Length of A1 and A2
int len = 1;
//Some other simple elements of fixed size
};
//Dynamic Array of Structs
typedef MyStruct DAStructs[];
namespace GLOB
{
//pointer to DAStructs
extern DAStructs * SS;
//Few other simple variables initialized in place
};
Because i don't rly sure if i declared everything properly - first question is: how to declare such data-structure in C/C++?
And second(+third) is: how to properly initialize and finalize it with some variable length?
I guess initialization and finalization should be something like that:
#include "GLOB.h"
namespace GLOB
{
void Init_SS(int len) {
SS = new MyStruct*[len];
for(int k=0; k<len; k++){
SS[k].A1 = new float*[1][4];
for(int j=0; j<4; j++) SS[k].A1[0][j] = 0.0;
SS[k].A2 = new int*[1];
SS[k].A2[0] = 0;
}
}
void Fin_SS() {
int len = length(SS);
for(int k=0; k<len; k++){
delete [] SS[k].A1;
delete [] SS[k].A2;
}
delete [] SS;
}
}
But obviously it's just a mess of nonsense and not the appropriate code...
P.S. i'd rather avoid using or any other solutions cuz i want to learn first of all and second i need as much control over how elements will be placed in memory as possible cuz later i'll need to pass pointer to such structure to other functions imported from DLLs...
Well nobody answered, but actually the answer was really simple, cuz i did everything almost properly =)
My first (and main) mistake was that i forgot that arrays in C are just pointers to first elements, so instead of
typedef float DArray1[][4];
typedef int DArray2[];
typedef MyStruct DAStructs[];
it should be
typedef float (*DArray1)[4];
typedef int * DArray2;
typedef MyStruct * DAStructs;
And it's not needed to make pointer to array, cuz array is already pointer lol
And my second mistake was that i forgot (well it's not like i knew it =) that length of array in C not stored anywhere, so instead of length(SS) it should be another variable where length should be stored manually upon allocation.
But the whole logic which i assumed seem to be legit, and it works fine. Even tho i didn't tested my project for memory leaks, when i use finalization procedure it seem to free allocated memory without any problems...

Changing the size of struct after declared

I have a code contains this structure
struct mystruct{
int a;
int array[1];
};
Directly, after running the code
I mean I will not declare any variable of that structure,the user will enter a number, for example 6.
What I want is to know how I can change the size of that structure.
Like I declared on this form
struct mystruct{
int a;
int array[6];
};
Then I use normally, like this:
struct mystruct var;
//I do not want to add any code here, to appropriate new form
for(int i=0;i<6;i++)
var.array[i]=0;
The typical way to do something like this in straight C (as opposed to C++) is to have just a pointer member in the struct, to point to the array, and then another member of the struct to indicate the size. This generally requires users of the struct to malloc() the array as needed, and to also set the size member to match. Something like:
struct mystruct
{
int size;
int *array;
};
and:
struct mystruct var;
var.array = malloc(6 * sizeof(int));
var.size = 6;
for (int i = 0; i < var.size; i++)
var.array[i] = 0;
Another common paradigm is a linked list.
Of course, in C++ you could just use a std::vector<int>.
You cannot change the declaration of the struct but if it is a variable length array within a struct that you want you do have an option. Declare your struct as:
struct mystruct{
int a;
int array[0];
};
And then when you want to create an instance with n elements in the array do the following:
struct mystruct *a = malloc(sizeof(struct mystruct) + n * sizeof(int));
This will create a memory region large enough to hold the struct and an array of length n. You can then use the array just as you would any other array:
a->array[1] = 5;
(this example assumes the array has at least 2 elements)
To accomplish what you have in your code example you would want to do something like this:
struct mystruct *var = malloc(sizeof(struct mystruct) + 6 * sizeof(int));
for(int i=0;i<6;i++) {
var->array[i]=0;
}
You cannot change an already declared struct, but you can make a new one as you want by modifying the program. You can't change data structures used in the program on the fly while it is running.

access array using pointer to array stored in a struct C

I have a struct defined as following:
typedef char *element_t;
typedef
struct {
element_t *array; /* start of the array */
int capacity; /* number of elements the array */
int length; /* used portion of array, 0..capacity */
} list;
I am trying to access the array that *array points to and assign it a char value and print it.
I'm a bit rusty with C but this is how i'm trying to do it:
list.array[0] = "a";
printf("%s\n", list.array[0]);
This makes my program crash. Any fixes?
EDIT: I should also mention that I have done the following initialisations too:
element_t* array[LMAX];
list.array= *differentArray;
Seems to work for me:
typedef char *element_t;
typedef
struct {
element_t *array; /* start of the array */
int capacity; /* number of elements the array */
int length; /* used portion of array, 0..capacity */
} list;
int main(int argc, char **argv)
{
element_t array[2] = {"foo", "bar"};
list list;
list.array = array;
list.capacity = sizeof(array)/sizeof(array[0]);
list.length = 1;
printf("%s\n", list.array[0]);
return 0;
}
You are most likely forgetting to assign list.array to point to a valid array.
typedef char *element_t; Don't hide pointers behind typedefs, this is bad practice as it makes the code unreadable. element_t *array will be the same as char** array. Is this actually what you want?
list.array[0] = "a"; suggests that you intended "array" to be an array of pointers? Where do you allocate the actual array? Where do you initialize the struct? list.array[0] is pointing into la-la-land rather than at allocated memory, as far as I can tell from the posted code.
Also, the array of pointers need to be of type const char*, since you are pointing at string literals.
Change your initialization to:
element_t differentArray[LMAX];
list.array = &differentArray[0];
The rest of your code should work as is after this change. You don't need any further allocations as long as you only keep putting literals like "a" into it.

Dynamically allocated array of structures in C

I just wanted to know if the following works. I have a struct
called foo that is defined as the following:
struct foo {
char name[255];
int amount;
};
During runtime, I need to create an array of the above structures whose size is dependent on a value I receive from a file's input. Let's say this size is k. Will the following code appropriately allocate a dynamically-sized array of structures?
struct foo *fooarray;
fooarray = malloc(k * sizeof(struct foo));
EDIT: If I want to access members of the structures within these arrays, will I use the format fooarray[someindex].member?
That will work (and your accessing is correct). Also, you can guard against size errors by using the idiom:
fooarray = malloc(k * sizeof *fooarray);
Consider using calloc if it would be nice for your items to start out with zero amounts and blank strings, instead of garbage.
However, this is not a VLA. It's a dynamically-allocated array. A VLA would be:
struct foo fooarray[k];
Yes it will.
On failure it will return 0.
And you have to free the memory returned by malloc when you are done with it
You can access the first member:
fooarray[0].name
fooarray[0].amount
The second as:
fooarray[1].name
fooarray[1].amount
etc..
One more different notation can be used in this approach:
struct foo {
char name[255];
int amount;
};
int main (void)
{
struct foo *fooarray;
struct foo *fooptr[5];
unsigned int i = 0;
for (i = 0; i < 5; i++)
fooptr[i] = malloc(1* sizeof(struct foo));
fooptr[2]->name[3] = 'A';
printf ("\nfooptr[2]->name[3]=%c\n",fooptr[2]->name[3]);
}

Resources