For the below code
struct orderSlip
{
char source[64];
char destination[64];
char item[64];
int position;
};
//global
struct orderSlip data[100];
Is there another way of printing out the data for each element other than these methods below:
printf("%s\n",data[0].source);
printf("%s\n",data[0].destination);
printf("%s\n",data[0].item);
printf("%i\n\n", data[0].position);
printf("%s\n",data[1].source);
printf("%s\n",data[1].destination);
printf("%s\n",data[1].item);
printf("%i\n", data[1].position);
etc
for(int n = 0; n< 3; n++)
{
printf("%s\n",data[n].source);
printf("%s\n",data[n].destination);
printf("%s\n",data[n].item);
printf("%i\n\n", data[n].position);
}
For deleting and adding, do I have to make a dynamic array of structs? If so, what would be the simplest syntax to do that?
Something like this c++ code
int * bobby;
bobby = new int [5];
delete bobby[5];
but in C? I'm guessing it has do with malloc and free
"For deleting and adding, do I have to make a dynamic array of structs? If so, what would be the simplest syntax to do that? Something like this c++ code"
Not if you know that you will never have more than x amount of items or at least check to make sure you aren't exceeding what you planned was the max. Then you can use your static array.
Adding only requires you to have a variable that keeps track of how many items are in the array:
void add_item(struct orderSlip *p,struct orderSlip a,int * num_items)
{
if ( *num_items < MAX_ITEMS )
{
p[*num_items] = a;
*num_items += 1;
}
}
Deleting from a static array would require a for loop that would move the items above it down one and decrementing the int keeping track of the number of items.
void delete_item(struct orderSlip *p,int *num_items, int item)
{
if (*num_items > 0 && item < *num_items && item > -1)
{
int last_index = *num_items - 1;
for (int i = item; i < last_index;i++)
{
p[i] = p[i + 1];
}
*num_items -= 1;
}
}
You could simplify printing the struct by passing it to a function that does the work.
void print(const struct orderSlip *p);
or
void print(const struct orderslip s);
optionally
void print(const struct orderslip s, FILE *fp);
or
void print(const struct orderslip *p, FILE *fp)
{
fprintf(fp,"%s\n",p->source);
...
}
and
void print_all(const struct orderSlip *p, int num_items)
//global
struct orderSlip data[MAX_ITEMS];
int num_items = 0;
int main(void)
{
...
print_all(data,num_items);
strcpy(a.source,"source 2");
strcpy(a.destination,"destination 20");
strcpy(a.item,"item xyz");
a.position = 99;
add_item(data,a,&num_items);
print_all(data,num_items);
delete_item(data,&num_items,0);
print_all(data,num_items);
One way is to allocate each element in your array and just keep an array of pointers
struct orderSlip **data;
data = calloc(100, sizeof(struct orderSlip*)); // 100 pointers to struct
(calloc will make sure memory is zero:ed from the start)
everytime you add a new struct:
data[i] = calloc(1, sizeof(struct orderSlip));
and when you don't need any longer
free(data[i]);
You can also change the size of data by using realloc, see
If you don't need to access the array using index, you could instead consider another type of data structure like a linked list to be truly dynamic.
Related
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.
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'm trying to print out all the members of each structure from a list. I was provided the print functions below to print out an element from a generic list.
Here is the structure definition of my list, which is in a generic list ADT c file:
struct list_type {
void *data;
int size;
int capacity;
int elementSize;
int (*comparePtr) (void *d1, void *d2);
};
So in a generic list ADT c file, I have this print function:
// client needs to send a pointer to a function capable of printing an element
void printl(ListType listptr, void (*printItem) (void *d)) {
int i;
for(i = 0; i < listptr->size; i++) {
// since we cannot use data[i], we need to calculate the address
// of the element to be sent to the client's print function
// since data is of type void, the formula is:
// the beginning address of the array + (offset x element size)
printItem(listptr->data + i * (listptr->elementSize) );
printf(" ");
}
printf("\n");
}
I call my printl function like so:
printl(clientList, printItem);
In my driver file, there's a function to print out an element from the list:
void printItem (int* p) {
printf("%d", *p);
//`my attempt at printing the members of an individual structure from the list
// printf("%s", ((Client *)&p)[0]);
}
Here is my Client structure definition:
struct client_tag {
char id[5];
char name[30];
char email[30];
char phoneNum[15];
};
When I run the program, I get a bunch of weird characters. How do I fix this?
Assuming you left out the line
typedef struct client_tag Client;
and assuming the strings of Client are guaranteed to be null terminated, this is the idea:
void printItem (const Client* p) {
printf("%s\n", p->id);
}
I am trying to sort an array of pointers to structs (definition below) based on the value stored in the void* of the "bucket" struct that I know are ints. It compiles and prints out my array of buckets and their values just fine with no errors or warnings but it isn't actually sorting the array. I have used asserts to try to find anywhere that could cause an error with qsort.
Struct definitions:
typedef struct _bucket{
void* val;
char *word;
}bucket;
typedef struct _root{
bucket **list;
int hashTableLength;
}root;
Sort Function to be passed to the qsort function:
int sortFunc(const void *a, const void *b){
bucket *bucketA=(bucket*)a;
bucket *bucketB=(bucket*)b;
int bucketAVal = *((int*)bucketA->val);
int bucketBVal = *((int*)bucketB->val);
assert((bucketAVal&&bucketBVal)!=0);
return bucketAVal-bucketBVal;
}
Sort the array and print:
void sort(root* inRoot, int(*sortFunc)(const void *a, const void *b)){
int length = inRoot->hashTableLength;
assert(length==11); //known length of hash array
for (int i = 0; i<length; i++)
assert(inRoot->list[i] != NULL);
qsort(inRoot->list, length, sizeof(bucket*), sortFunc);
for(int i =0; i<length; i++)
printf("%s was found %d times\n", inRoot->list[i]->word, *((int*)(inRoot->list[i]->val)));
return;
}
The compare function sortFunc() receives a pointer to each object. The array inRoot->list is an array of bucket * so sortFunc() is receiving pointers to bucket *: bucket **.
Also the int subtraction is subject to possible overflow. Use the idiomatic 2 compares to solved that.
int sortFunc(const void *a, const void *b) {
bucket **bucketA = (bucket**) a;
bucket **bucketB = (bucket**) b;
void *vA = (*bucketA)->val;
void *vB = (*bucketB)->val;
int iA = *((int*) vA);
int iB = *((int*) vB);
return (iA > iB) - (iA < iB);
}
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);
}