Well I am wanting to change the way my structures are written, currently I use array and I need to limit its use, but I wanted a way to create a dynamic array that is the size of the reading done, without always having to edit the array value.
Current Code:
struct sr_flag {
int value_flag;
};
struct er_time {
int value_time;
};
struct se_option {
struct sr_flag flag[50];
struct er_time time[50];
};
struct read_funcs
struct se_option *option;
void (*option_func) (void);
...
}
struct read_funcs func_;
struct read_funcs *func;
int sr_flags(int i, int fg, int val) {
if(i < 0)
return 0;
return func->option[i].flag[fg].value_flag = val;
}
void option_func(void) {
struct se_option fnc;
fnc.option = malloc(500 * sizeof(*(fnc.option)));
}
void read_fnc() {
func = &func_;
func->option = NULL;
func->option_func = option_func;
}
I look for a way to remove the array amount [50] instead each time the sr_flags function is executed the limit is raised
Example: sr_flags function executed 1x array would be [1] if executed 2x would be [2]
I also think about doing the same with the option_func function
I tried using the following more unsuccessfully
struct se_option {
struct sr_flag *flag;
struct er_time time[50];
};
int sr_flags(int i, int fg, int val) {
if(i < 0)
return 0;
func->option[i].flag = malloc(1 * sizeof(*(func->option[i].flag)));
return func->option[i].flag[fg].value_flag = val;
}
int main () {
for(int i < 0; i < 10; i++)
sr_flags(i, 1, 30);
return 0;
}
I'm not 100% certain on what it is you want but I think you just want to call realloc and increase the size by the amount you provide. And that's very easy to do, as for the values you want with the arrays I'm not sure so I just used a placeholder value.
#include <stdio.h>
#include <stdlib.h>
struct sr_flag {
int value_flag;
};
struct er_time {
int value_time;
};
struct se_option {
struct sr_flag* flag;
struct er_time* time;
};
void allocateflags(struct se_option* options, int size, int val){
options->flag = realloc(options->flag, size*sizeof(struct sr_flag));
struct sr_flag* flag = options->flag+size-1;
flag->value_flag = val;
}
void allocatetime(struct se_option* options,int size, int val){
options->time = realloc(options->time, size*sizeof(struct er_time));
struct er_time* time = options->time+size-1;
time->value_time = val;
}
void displayflagvalues(struct se_option* options,int size){
for(int index = 0; index < size ; ++index){
printf("flag: %i\n",options->flag[index].value_flag);
}
}
void displaytimevalues(struct se_option* options, int size){
for(int index = 0; index < size ; ++index){
printf("time: %i\n",options->time[index].value_time);
}
}
int main(){
struct se_option options = {0};
for(int index = 0; index < 10; ++index){
allocateflags(&options, index,index);
allocatetime(&options, index,index);
}
displayflagvalues(&options, 10);
displaytimevalues(&options,10);
return 0;
}
The code creates an se_option structure wheren sr_flag and er_time pointers are null. Then there's two functions one allocateflags and the other allocatetime, both of which call realloc with the size you provide. When you call realloc, all previous memory is copied over to the new array. Also free is called automatically by realloc.
This step
struct sr_flag* flag = options->flag+size-1;
flag->value_flag = val;
struct er_time* time = options->time+size-1;
time->value_time = val;
Is slightly redundant but it was just to show the newest array can hold the value. If you understand pointer arithmetic, all its doing is incrementing the pointer to the last position then subtracting 1 struct size and setting that value. Basically setting the value of the final array in the pointer.
Related
I'm doing dining-philosopher problem in C for assignment. And got stuck very begining of my code.
I decided each philosopher to be structure, and forks to be int array.
But I can't use global variable in this assignment.
So, I have to include shared variable in philosopher structure to pass them for arguments of thread routine.
Here is my problem - how to include int array in structure if I can't know proper size of them when initializing?
My plan is just include pointer variable in structure then allocate array's address using &.
But It doesn't work :
#include <stdlib.h>
/* inside structure*/
typedef struct s_share {
int **forks;
} t_share;
/* outside structure */
typedef struct s_philo {
t_share *share;
} t_philo;
int main(void)
{
t_philo *philo;
int *forks;
int i;
i = 0;
/* malloc structure arrary philo, size = 10 */
philo = (t_philo *)malloc(sizeof(t_philo) * 10);
/* malloc int arrary forks, size = 100 */
forks = (int *)malloc(sizeof(int) * 100);
while (i < 10)
{
philo[i].share->forks = &forks; //error
i++;
}
}
Output : segmentation fault
I tested share->forks size like this :
printf("size of forks : %ld\n", sizeof(philo->share->forks));
Output was 8.
It's enough size to store int * pointer.
Through this I know It's not the memory allocation problem.
Then what is problem? Can someone check this for me?
Edit :
When I try to malloc directly philo->share->forks, I got same error.
typedef struct s_share {
int *forks;
} t_share;
typedef struct s_philo {
t_share *share;
} t_philo;
int main(void)
{
t_philo *philo;
int *forks;
int i;
i = 0;
philo = (t_philo *)malloc(sizeof(t_philo) * 10);
while (i < 10)
{
philo[i].share->forks = (int *)malloc(sizeof(int) * 100); //error
i++;
}
}
I thought it's because when philo initialized, sizeof operator calculated forks's memroy to be 8 - which required for pointer.
Is there something wrong?
Edit 2 :
To clear my question,
It's easy to solve this problem, if I write size of array in structure definition.
typedef struct s_share {
int forks[100];
} t_share;
typedef struct s_philo {
t_share *share;
} t_philo;
but according to my assignmet I have to get philosopher's number from cmd. So I can't do that.
Above is simple version of my origin code
Sorry, Edit 2 is wrong :
typedef struct s_share {
int forks[100];
} t_share;
typedef struct s_philo {
t_share *share;
} t_philo;
int main(void)
{
t_philo *philo;
t_share *share;
int *forks;
int i;
i = 0;
philo = (t_philo *)malloc(sizeof(t_philo) * 10);
while (i < 10)
{
philo[i].share->forks[i] = 1;
i++;
}
}
Output
zsh: segmentation fault ./a.out
I still got segfault when I write array size in struct definition.
I used calloc to initialize all member in my struct but same error occurs :
typedef struct s_share {
int **forks;
} t_share;
typedef struct s_philo {
t_share *share;
} t_philo;
int main(void)
{
t_philo *philo;
t_share *share;
int *forks;
int i;
i = 0;
philo = (t_philo *)calloc(10, sizeof(t_philo));
forks = (int *)calloc(100, sizeof(int));
while (i < 10)
{
philo[i].share->forks = &forks; //error
i++;
}
}
Edit 4:
I finally found error. It's because I didn't malloc 'share' struct in philo struct
typedef struct s_share {
int **forks;
} t_share;
typedef struct s_philo {
t_share *share;
} t_philo;
int main(void)
{
t_philo *philo;
int *forks;
int i;
i = 0;
philo = (t_philo *)malloc(sizeof(t_philo) * 10);
forks = (int *)malloc(sizeof(int) * 100);
while (i < 10)
{
philo[i].share = (t_share *)malloc(sizeof(t_share)); //here
philo[i].share.forks = &forks;
i++;
}
}
That one line -allocating struct share- solved problem.
Or, I can modify philo struct definition like this :
typedef struct s_philo {
t_share share; //not pointer, just struct
} t_philo;
In this way, I can automatically malloc struct share.
I got confused in this point. Thanks for helping!
this line
philo[i].share->forks
Is dereferencing the pointer 'share' which is not set. You called malloc and did not set any values, so the data inside your allocated buffer is 'garbage' data.
// add begin
t_share* new_share = (t_share*)malloc(sizeof(t_share));
philo[i].share = new_share;
// add end
// don't use &forks
philo[i].share->forks = forks; //error
i++;
// need forks++
forks++;
I'm trying to make a small library for particle management that allows to "expand" struct with user's data (texture, animation frames, etc). The library would know only the size of the expanded struct.
How do I iterate through the array of unknown struct types but known size of a struct?
typedef struct{
int type;
}Base;
typedef struct{
Base base;
int value;
}inherited;
int main(){
size_t size = sizeof(inherited);
int count = 10;
void *b = malloc(size * count);
for (int i = 0; i < count; i++){
// iterate based on known size & send to callback
callback( &( (size)b )[i] );
}
free(b);
return 0;
}
I assume the code that does the malloc and calls callback doesn't know anything about the type of the object, only its size.
#include <stdlib.h>
void *alloc_and_init(size_t nmemb, size_t size, void (*callback)(void *))
{
void *b = calloc(nmemb, size);
if (b)
{
char *p = b;
for (size_t i = 0; i < nmemb; i++)
{
callback(p);
p += size;
}
}
return b;
}
typedef struct{
int type;
}Base;
typedef struct{
Base base;
int value;
}inherited;
void init_inherited(void *p)
{
inherited *obj = p;
/* do initialization of obj->* here */
}
int main(void)
{
int objcount = 10;
inherited *objarr;
objarr = alloc_and_init(objcount, sizeof(*objarr),
init_inherited);
/* ... */
free(objarr);
}
for( inherited *p = b, *e = p + count; p < e; p++ ){
callback(p);
}
char *b = malloc(size * count);
for (int i = 0; i < count; i++){
// iterate based on known size & send to callback
callback( b + i * size );
}
Polymorphism in C is always rather clunky. Basically you have to construct a "vtable" manually. The naive, simplified version below lets each object have its own function pointer. You'll end up with something rather contrived like this:
#include <stdio.h>
#include <stdlib.h>
typedef struct base_t base_t;
typedef void callback_t (const base_t* arg);
struct base_t
{
int type;
callback_t* callback;
};
typedef struct
{
base_t base;
int value;
} inherited_t;
void callback_base (const base_t* arg)
{
puts(__func__);
}
void callback_inherited (const base_t* arg)
{
const inherited_t* iarg = (const inherited_t*)arg;
printf("%s value: %d\n", __func__, iarg->value);
}
int main (void)
{
// allocate memory
base_t* array [3] =
{
[0] = malloc(sizeof(inherited_t)),
[1] = malloc(sizeof(base_t)),
[2] = malloc(sizeof(inherited_t)),
};
// initialize objects
*(inherited_t*)array[0] = (inherited_t){ .base.callback=callback_inherited, .value = 123 };
*(array[1]) = (base_t){ .callback=callback_base };
*(inherited_t*)array[2] = (inherited_t){ .base.callback=callback_inherited, .value = 456 };
for (int i = 0; i < 3; i++)
{
array[i]->callback(array[i]); // now we get polymorphism here
}
}
A more professional version involves writing a translation unit (.h + .c) per "class" and then combine allocation with initialization in the "constructor". It would be implemented with opaque type, see How to do private encapsulation in C? Inside the constructor, set the vtable corresponding to the type of object allocated.
I'd also boldly claim that any OO solution using void* arguments has some design flaw. The interface should be using the base class pointer. Void pointers are dangerous.
I have searched through many of the answers on here and have implemented a few changes based on that, but am getting a EXC_BAD_ACCESS error when calling the qsort function. My IDE is pointing to the return in my qsort compare function as the problem. I know I am allocating memory properly for all the elements as I can print the strings with no problem if I omit the call to qsort. Could someone point me in the right direction?
My structs, to see how deep I am navigating:
typedef struct {
unsigned int siteId;
unsigned int tableTypeId;
unsigned int surMatId;
unsigned int strucMatId;
char *streetAve;
unsigned int neighbourhoodId;
char *neighbourhoodName;
unsigned int ward;
char *latitude;
char *longitude;
} Entries;
typedef struct {
int size;
Entries **entry;
} PicnicTable;
typedef struct {
Table *tableTypeTable;
Table *surfaceMaterialTable;
Table *structuralMaterialTable;
NeighbourHoodTable *neighborhoodTable;
PicnicTable *picnicTableTable;
} DataBase;
extern DataBase *DB;
Entries **ent = DB->picnicTableTable->entry;
qsort(ent,DB->picnicTableTable->size-1, sizeof(Entries*), cmpfunc); typedef struct {
unsigned int siteId;
unsigned int tableTypeId;
unsigned int surMatId;
unsigned int strucMatId;
char *streetAve;
unsigned int neighbourhoodId;
char *neighbourhoodName;
unsigned int ward;
char *latitude;
char *longitude;
} Entries;
typedef struct {
int size;
Entries **entry;
} PicnicTable;
typedef struct {
Table *tableTypeTable;
Table *surfaceMaterialTable;
Table *structuralMaterialTable;
NeighbourHoodTable *neighborhoodTable;
PicnicTable *picnicTableTable;
} DataBase;
extern DataBase *DB;
This is what the call looks like:
Entries **ent = DB->picnicTableTable->entry;
qsort(ent,DB->picnicTableTable->size-1, sizeof(Entries*), cmpfunc);
And the compare function is:
int cmpfunc(const void *a, const void *b) {
Entries *left = *(Entries**)a;
Entries *right = *(Entries**)b;
return strcmp(left->neighbourhoodName, right->neighbourhoodName);
}
The picnicTableTable, and Entry are initialized after this malloc:
DB->picnicTableTable = malloc(sizeof(PicnicTable));
DB->picnicTableTable->entry = malloc(numEntries*sizeof(Entries)+1);
DB->picnicTableTable->size = numEntries;
while ((c=fgetc(IN)) != EOF) {
if (c == ',' && row > 0) {
switch (column) {
case 0: neighbourhoodName = copyToChar(buff, begin, i);
...
}
copyToChar take a slice of the buffer and allocates memory then returns a pointer to a value that I assign:
char * copyToChar(const char * buff, int begin, int end) {
char *temp = malloc(end - begin + 1);
int j = 0;
for (int i = begin; i < end; i++, j++)
temp[j] = buff[i];
temp[j] = '\0';
return temp;
}
And the array is populated after I iterate through each row in a file (this is just one entry):
DB->picnicTableTable->entry[row]->neighbourhoodName = malloc(strlen(neighbourhoodName)*sizeof(char)+1);
The values of a->neighbourhoodName are NULL, which confuses me. Doesn't qsort pass two values from the array to the compare function?
Thanks for your time!
Beware. You declare entry to be a pointer to pointers (pointing to first element of an array of pointers)
typedef struct {
int size;
Entries **entry;
} PicnicTable;
but initialize it as a mere dynamic array, that is a pointer to first element of an array of Entrys in:
DB->picnicTableTable->entry = malloc(numEntries*sizeof(Entries)+1);
If you want an array of pointers to speed up qsort, you should build it separately:
typedef struct {
int size;
Entries *entry;
Entries **pentry;
} PicnicTable;
DB->picnicTableTable->entry = malloc(numEntries*sizeof(Entries)+1);
DB->picnicTableTable->pentry = malloc(numEntries*sizeof(&Entries)+1);
for (int i=0; i<=numEntries; i++) { // initialize the array of pointers
pentry[i] = entry + i;
}
Currently the definition of cmpfunc is not coherent with your initialization of DB->picnicTableTable->entry.
I have a small trouble initializing (dynamic) parts of my structures that are in an array. This is what i have so far I am using a sub-routine to create the struct
t_grille_animaux creer_grille(int dim_ligne, int dim_col)
{
t_grille_animaux grille;
grille.la_grille = (t_case_animal **) malloc(sizeof(t_case_animal)*dim_ligne*dim_col);
grille.dim_colonne = dim_col;
grille.dim_ligne = dim_ligne;
grille.nb_predateurs = NULL;
grille.nb_proies = NULL;
return grille;
}
This is my structure:
typedef struct
{
t_case_animal ** la_grille; //2D array
int dim_ligne;
int dim_colonne;
int nb_proies;
int nb_predateurs;
} t_grille_animaux;
typedef struct
{
t_contenu etat;
t_animal animal;
} t_case_animal;
typedef enum {VIDE, PROIE, PREDATEUR} t_contenu;
typedef struct
{
int age;
int jrs_gestation;
int energie;
int disponible;
} t_animal;
(Sorry for the language)
What I get right now is that everything that isn't the struct in the array is fine. But everything in the array is undeclared.
This should do the trick:
#define NUM_ROWS (10)
#define NUM_COLS (15)
grille.la_grille = malloc(NUM_ROWS * sizeof(*grille.la_grille));
for(int row = 0; row < NUM_ROWS; row++)
grille.la_grille[row] = malloc(NUM_COLS * sizeof(**grille.la_grille));
The malloc() function does not (necessarily) initialise the allocated bytes to any value in particular. So after calling malloc(), you should explicitly initialise the allocated data.
Having said that, you have a couple of choices about how you can store your two-dimensional array. It depends on how you want to access the data. Since C does not have true multidimensional arrays, you can either:
declare a single dimension array of size dim_ligne*dim_col of t_case_animal values
declare an array of row pointers of size dim_ligne that each point to another single dimensional array of dim_col values
For the first case, change your declaration of la_grille to:
t_case_animal * la_grille;
and access your values as something like la_grille[j*dim_colonne+i].
For the second case, be sure to initialise your subarrays:
grille.la_grille = (t_case_animal **) malloc(sizeof(t_case_animal*)*dim_ligne);
for (int i = 0; i < dim_ligne; i++) {
grille.la_grille[i] = (t_case_animal *) malloc(sizeof(t_case_animal)*dim_col);
}
In the second case, you would access your values as something like la_grille[j][i].
You can use malloc() to allocate memory for each row. The following code should work:
#include<stdlib.h>
typedef struct
{
int age;
int jrs_gestation;
int energie;
int disponible;
}t_animal;
typedef enum {VIDE, PROIE, PREDATEUR} t_contenu;
typedef struct
{
t_contenu etat;
t_animal animal;
} t_case_animal;
typedef struct
{
t_case_animal ** la_grille; //2D array
int dim_ligne;
int dim_colonne;
int nb_proies;
int nb_predateurs;
} t_grille_animaux;
t_grille_animaux creer_grille(int dim_ligne,int dim_col)
{
t_grille_animaux grille;
grille.la_grille = (t_case_animal**) malloc(sizeof(t_case_animal*)*dim_ligne);
for(int i=0; i<dim_ligne; i++) {
grille.la_grille[i] = (t_case_animal*) malloc(sizeof(t_case_animal)*dim_col);
}
grille.dim_colonne = dim_col;
grille.dim_ligne = dim_ligne;
grille.nb_predateurs = 0;
grille.nb_proies = 0;
return grille;
}
int main(int argc, char* argv[])
{
t_grille_animaux test;
test = creer_grille(3, 4);
}
Lets say I have the following code (the array* function are what we use for resizable arrays and they operate on pointers-to-arrays that are null initialized):
typedef struct MyStruct
{
int i;
} MyStruct;
MyStruct* GetNewMyStruct(int i)
{
MyStruct* s = malloc(sizeof(MyStruct));
s->i = i;
return s;
}
int SomeFunction(int number, MyStruct *elem)
{
MyStruct **structs = NULL;
int i;
for (i = 0; i < number; i++)
arrayPush(&structs, GetNewMyStruct(i));
arrayPush(&structs, elem);
return arraySize(&structs);
}
I decide that SomeFunction is too large and I want refactor it. Currently where I work we use VisualAssist X, which has some refactoring capabilities, but when I use it on this it does not work correctly. If I attempt to use it to refactor out the loop, this is what I get:
void MyMethod( int number, MyStruct ** structs )
{
int i;
for (i = 0; i < number; i++)
arrayPush(&structs, GetNewMyStruct(i));
}
int SomeFunction(int number, MyStruct *elem)
{
MyStruct **structs = NULL;
MyMethod(number, structs);
arrrayPush(&structs, elem);
return arraySize(&structs);
}
This is not correct. MyMethod should take a MyStruct ***, not a MyStruct **. This is because the code I'm refactoring takes the address of structs. The result is that the refactored version will always return 1 (since only one object has been pushed into my array) rather than number+1. Are there other tools out there that do this type of refactoring correctly?
Eclipse CDT does this correctly (at least the current version Juno). Selecting the declaration of i and the loop and doing Refactor > Extract Function, and setting structs to be an output parameter, produces:
void MyMethod(int number, MyStruct*** structs) {
int i;
for (i = 0; i < number; i++)
arrayPush(&*structs, GetNewMyStruct(i));
}
int SomeFunction(int number, MyStruct *elem)
{
MyStruct **structs = NULL;
MyMethod(number, &structs);
arrayPush(&structs, elem);
return arraySize(&structs);
}