I've created this struct:
typedef struct {
char* id;
char* name;
int birthYear;
int finishedCourses;
double avarage;
int coursesNow;
int courses[MAX_COURSES_YEAR];
}Student;
and now I am trying to set an array of courses.
this is what I wrote:
s1.courses[] = {5,4,3,2};
and the error is:
student.c:15:13: error: expected expression before ‘]’ token
s1.courses[]={5,4,3,2};
int courses[]={5,4,3,2};
memcpy (s1.courses, courses, sizeof(courses));
Other way is to do so:
typedef struct {
char* id;
char* name;
int birthYear;
int finishedCourses;
double avarage;
int coursesNow;
int courses[];
}Student;
int courses[]={5,4,3,2};
Student *s = malloc(sizeof(Student)+sizeof(courses));
memcpy (s->courses, courses, sizeof(courses));
In this second case the advantage is that you alloc at runtime the very dimension for courses, you do not use padding space or statically fixed space for the field.
There are also other ways to do it.
Initialization of an array via an initializer list is only permissible upon declaration. So you can do:
int arr[] = {1,2,3,4,5};
But you cannot do:
int arr[5];
arr = {1,2,3,4,5};
You have to use a loop or memcpy:
int tmp[] = {1,2,3,4,5};
// method 1
for(int i = 0; i < sizeof(tmp) / sizeof(*tmp); i++) {
arr[i] = tmp[i];
}
// method 2
memcpy(arr, tmp, sizeof(tmp));
You can also take advantage of compound literals and dispense with tmp array:
memcpy(arr, (int []) {1,2,3,4,5}, sizeof((int []) {1,2,3,4,5}));
Related
i want assignment a string to array of char in typedef struct like this
typedef struct convert{
char *upcase;
char *lowcase;
int number;
int order;
} convert;
convert sandi[27];
sandi[].upcase = {"ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
but it cannot
A typedef declaration does not declare an object and in C you may not provide default values for members of a structure.
In such a case you need to use a loop as for example
typedef struct convert{
char *upcase;
char *lowcase;
int number;
int order;
} convert;
convert sandi[27];
char *upcase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
for ( size_t i = 0; i < 27; i++ )
{
sandi[i].upcase = upcase;
}
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.
My intention: To loop through -- without using unions -- 30 members of a structure, all of type character array, storing in each the result of a call to itoa. In the following code, I name the structure members a-z,A-D. In the calling function, I initialize a string of those characters, called 'letters', then I try to loop through the structure members by referring to them with my increment variable as the index into letters. Then, I try to dump the contents of each member of the structure. **edit: I realize that the members wouldn't contain anything, given what code you can see. The problem seems to be with referring to struct members like this.
struct listArrays {
char a[10];
char b[10];
char c[10];
char d[10];
char e[10];
char f[10];
char g[10];
char h[10];
char i[10];
char j[10];
char k[10];
char l[10];
char m[10];
char n[10];
char o[10];
char p[10];
char q[10];
char r[10];
char s[10];
char t[10];
char u[10];
char v[10];
char w[10];
char x[10];
char y[10];
char z[10];
char A[10];
char B[10];
char C[10];
char D[10];
};
struct listArrays Ternaries;
int testTernary(){
char letters[30] = "ABCDabcdefghijklmnopqrstuvwxyz";
int i;
for(i = 0; i < 30; ++i){
dumpArray((Ternaries.(letters[i])), 10);
}
return 0;
}
The error I get is "expected identifier before '(' token."
Problems I have ruled out:
-The dumpArray function works fine.
-Looping through the letters works fine, outside the context of the
referral to struct members
Identifiers (names) only exist in the program text. Once compiled and linked, they no longer exist. So you can't "index" the struct for the letter. What you can do is:
struct listArrays {
char letters[30][10];
};
Now you can access these "letters":
dumpArray((Ternaries.letters[i]), 10);
I have the following code in C:
typedef struct
{
int age;
int phoneNumber;
} Student;
typedef struct
{
int id;
int student[1];
} People;
#define NUM_OF_PEOPLE
void *p = malloc(sizeof(People) + sizeof(int) * NUM_OF_PEOPLE + sizeof(Student) * NUM_OF_PEOPLE);
How could I find the pointer to the memory point to the first element of struct Student in the memory?
I try to do it in the following way:
int i = 0;
for(i = 0; i < NUM_OF_PEOPLE; i++)
{
Student * student_p = p.student[NUM_OF_PEOPLE];
}
It does not work, so can we allocate memory in the way?
And how to find the first element of struct Student in the memory?
What you have is an ancient way of having a flexible array member, which was technically also undefined behavior.
You are looking for this.
First, you need to define your struct like this (I don't know what the ints before the Students are, so let's just call it id):
typedef struct
{
int age;
int phoneNumber;
} Student;
typedef struct
{
int id;
Student student;
} StudentAndId;
typedef struct
{
int id;
StudentAndId students[];
} People;
Note the lack of size in the array inside People. Now you do this:
People *p = malloc(sizeof(People) + sizeof(StudentAndId[NUM_OF_PEOPLE]));
Then you can access students inside p as if it was an array of NUM_OF_PEOPLE elements.
Remember to compile with C99 (or C11) support. With gcc that would be -std=c99 or -std=gnu99.
This will allocate memory for storing the date but how you access it depends on how you store date. using C pointers you can store and access data using this structure and allocation but accessing the members will not be direct. it will involve pointer arithmetic. So better to use other structure if possible. If using this way of allocation then you need to do pointer arithmetic to get the next elements.
Try this:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int age;
int phoneNumber;
} Student;
typedef struct
{
int id;
int student[1];
} People;
#define NUM_OF_PEOPLE 10
int main()
{
People *p = malloc(sizeof(People) + sizeof(int) * NUM_OF_PEOPLE + sizeof(Student) * NUM_OF_PEOPLE);
int* id = (int*)(p+1);
Student* s = (Student*)(id+NUM_OF_PEOPLE);
printf("Size of People : %d\n", sizeof(People));
printf("p points to : %p\n", p);
printf("id points to : %p\n", id);
printf("s points to : %p\n", s);
}
Here's a sample output:
Size of People : 8
p points to : 0x80010460
id points to : 0x80010468
s points to : 0x80010490
You may want to add the id field to your Student data structure, e.g.:
typedef struct {
int id;
int age;
int phoneNumber;
} Student;
Then, you can define a structure having a fixed header (in this case, this can be the number of students), followed by a variable-sized array of Students:
#define ARRAY_OF_ANY_SIZE 1
typedef struct {
int count;
Student students[ARRAY_OF_ANY_SIZE];
} People;
This blog post explains this technique of having "arrays of size 1", including a discussion of the alignment problem.
I won't repeat the original blog post code here. Just consider that you can use the portable offsetof() instead of the Windows-specific FIELD_OFFSET() macro.
As a sample code, you may want to consider the following:
#include <stdio.h> /* For printf() */
#include <stddef.h> /* For offsetof() */
#include <stdlib.h> /* For dynamic memory allocation */
typedef struct {
int id;
int age;
int phoneNumber;
} Student;
#define ARRAY_OF_ANY_SIZE 1
typedef struct {
int count;
Student students[ARRAY_OF_ANY_SIZE];
} People;
int main(int argc, char* argv[]) {
People* people;
const int numberOfStudents = 3;
int i;
/* Dynamically allocate memory to store the data structure */
people = malloc(offsetof(People, students[numberOfStudents]));
/* Check memory allocation ... */
/* Fill the data structure */
people->count = numberOfStudents;
for (i = 0; i < numberOfStudents; i++) {
people->students[i].id = i;
people->students[i].age = (i+1)*10;
people->students[i].phoneNumber = 11000 + i;
}
/* Print the data structure content */
for (i = 0; i < people->count; i++) {
printf("id: %d, age=%d, phone=%d\n",
people->students[i].id,
people->students[i].age,
people->students[i].phoneNumber);
}
/* Release the memory allocated by the data structure */
free(people);
return 0;
}
Output:
id: 0, age=10, phone=11000
id: 1, age=20, phone=11001
id: 2, age=30, phone=11002
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);
}