How do I initialize a struct containing another struct? - c

I'm new and i try to create a struct of stuct on C code. I don't understand how i can inizialize a struct of struct. Someneone help me?
I have:
#define SIZEHOSP 200
#define DIM 200
#define SIZESICK 2000
typedef struct SICKREGION {
char firstName[20];
char lastName[20];
char fiscalCode[16];
enum stateSick;
diagnosisDate data;
healingDate dataH;
};
typedef struct HOSPITAL {
char nameHospital[30];
int codeHospital;
char addressHospital[40];
char departmentManager[30];
int beds;
int bedsIntensiveCare;
};
HOSPITAL hospital[SIZEHOSP];
typedef struct REGION {
char nameRegion[20];
int codeRegion;
char MainTownRegion[15];
char namePresidentRegion[20];
int numberHospital;
int numberSickRegion;
HOSPITAL hospital[SIZEHOSP];
SICKREGION sickregion[SIZESICK];
};
REGION region[DIM] = {
{"Sicilia", 0004, "Palermo", "Musumeci", 40, 150},
{"sardegna", 4444, "cagliari", "pippo", 200, 50},
{"calabria", 0000, "reggio", "Josh", 12, 18}
};
for example i inizialized 3 type of REGION. but they are incomplete because i don't know how insert the value of structure HOSPITAL and SICKREGION inside the region[DIM]. What is the syntax? I hope he explained the problem well.

How do I initialize a struct containing another struct?
There are several ways to initialize a struct. To simplify, the following example uses smaller structs than those you provided...
The following will illustrate initialization with initialization with values ( = {,,,{,,}}; ), then with zeros = {0} :
typedef struct {
int count;
float cash;
char item[50];
}Purchase;
typedef struct {
int accnt;
char acct_name[50];
Purchase purch;
} Acct;
Acct acct = {100123, "Robert Baily", {15, 12.50, "Tires"}};
//Or, using member names to self document the initialization statement as suggested in comments:
Acct acct1 = Acct acct = {.accnt=100123, .acct_name="Robert Baily", {.count=15, .cash=12.50, .item="Tires"}};
Acct acct2 = {0};
int main(void)
{
printf("acct = %d\nAcct_name = %s\nitem = %s\ncount = %d\ncash = %3.2f\n", acct.accnt, acct.acct_name, acct.purch.item, acct.purch.count, acct.purch.cash);
printf("acct2 = %d\nAcct_name = %s\nitem = %s\ncount = %d\ncash = %3.2f\n", acct2.accnt, acct2.acct_name, acct2.purch.item, acct2.purch.count, acct2.purch.cash);
return 0;
}
Although these are small, they illustrate what you are doing with your larger, more complicated structs. I suggest that for your structs it will be extremely tedious, and probably not necessary to use the first method. struct declaration in an actual program is often initialized by zeroing. i.e. {0}

Related

In a typedef struct with a union, do I need to instantiate all variables?

I am learning C and apologies if this the question isn't even asked right
But my question is, if I have a typedef struct that contains a union of two other typedef structs, do I need to instantiate all the variables?
For example, if I have the following code:
typedef struct dog {
char *breed;
long weight;
} dog;
typedef struct cat {
bool isBlackCat;
int numberOfLives;
} cat;
typedef struct animal {
int id;
int ownerID;
char *name;
bool isDog;
union {
struct dog aDog;
struct cat aCat;
} animals;
} animal;
If I were to use the above structure in a function like so:
Adoption adoptAnimal(char *nameParam, bool type, int ownerId) {
Adoption pet = (Adoption) malloc(sizeof(struct animal));
pet -> name = (char*) malloc((1 + strlen(nameParam)) * sizeof(char));
strcpy(pet->name, nameParam);
pet -> id = getId(); //function that generates an id
pet -> ownerId = ownerId;
pet -> isDog = type;
// if type = 1, it's a dog
if (type) {
pet -> animals.aDog.breed = some breed;
pet -> animals.aDog.weight = some weight;
} else {
pet -> animals.aCat.lives = 9;
pet -> animals.aCat.isBlackCat = 1;
}
return pet;
}
Is this proper/legal use of a typedef struct that contains a union?
The way the function is set up, the variables from the dog or cat struct will be assigned, but not both, is that allowed? Or do I need to assign all of the variables from both structs
Thank you
This is tricky because of how loosely typed C is. The animals union in the animal struct will be treated as either a dog or a cat, depending on how you are accessing it.
Remember that a union is a single memory location, and it is the size of the largest struct member. This means that calling the struct member animals is misleading, because it is only 1 animal (either a cat or a dog, but never both).
So when you execute pet->animals.aCat.lives = 9, the animals union is treated as a cat struct, and the lives member of that struct is set to 9. However, you could then try and read the animals union as a dog, and C would consider this valid. You would just get data that makes no sense.
I modified your code a little so that it would compile and created a main function to offer some insight about what is going on. The adoptAnimal() function recognizes that the animal being adopted is of type dog, so pet->animals is treated as a dog struct and the members are set accordingly. However, back in the main function, I can go ahead and read the animals union as either a dog or a cat, and C doesn't care.
typedef struct dog {
char *breed;
long weight;
} dog;
typedef struct cat {
bool isBlackCat;
int numberOfLives;
} cat;
typedef struct animal {
int id;
int ownerID;
char *name;
bool isDog;
union {
struct dog aDog;
struct cat aCat;
} animals;
} animal;
animal* adoptAnimal(char *nameParam, bool type, int ownerId) {
animal *pet = (animal*) malloc(sizeof(struct animal));
pet->name = (char*) malloc((1 + strlen(nameParam)) * sizeof(char));
strcpy(pet->name, nameParam);
pet->id = 1234; //function that generates an id
pet->ownerID = ownerId;
pet->isDog = type;
// if type = 1, it's a dog
if (type) {
pet->animals.aDog.breed = malloc(10);
strcpy(pet->animals.aDog.breed, "Pit bull");
pet->animals.aDog.weight = 1000;
} else {
pet->animals.aCat.numberOfLives = 9;
pet->animals.aCat.isBlackCat = 1;
}
return pet;
}
int main() {
animal *pet = adoptAnimal("George", 1, 1234);
printf("Dog: breed=\"%s\", weight=\"%ld\"\n", pet->animals.aDog.breed, pet->animals.aDog.weight);
printf("Cat: lives=\"%d\", isBlack=\"%d\"\n", pet->animals.aCat.numberOfLives, pet->animals.aCat.isBlackCat);
/* Output:
* Dog: breed="Pit bull", weight="1000"
* Cat: lives="32735", isBlack="0"
*/
}
So in conclusion, your use of a union with struct members is valid, and you only need to set the values for a dog struct or a cat struct, but not both. Also make sure you use appropriate naming and associated variables to understand what data your union holds.
I like the explanation that tutorialspoint gives on C unions, you might want to check it out if you haven't already.
Hope this clears things up, let me know if there's something I missed.

Malloc and realloc for union of structs linked to array of structs

What's the best way to dinamically allocate memory to an array of structs with union included? I should malloc and then realloc to record_user or to data_user? Below I explain more of it, this is the sample code:
core.h
#define MAX_USER sizeof(record_user) / sizeof(record_user[0])
#define MAX_ARTIST sizeof(record_artist) / sizeof(record_artist[0])
/* all my other defines here */
typedef enum {
admin = 1,
basic = 0
} type;
typedef struct {
int hour;
int minute;
int second;
} tm;
typedef struct {
int day;
int month;
int year;
} date;
typedef struct {
short id;
char name[MAX_USER_NAME];
char surname[MAX_USER_SURNAME];
char email[MAX_USER_EMAIL];
char password[MAX_PASSWORD_LENGTH];
date birthday;
date subscription_date;
tm subscription_time;
type role;
} user;
typedef struct {
short id;
char name[MAX_ARTIST_NAME];
char genre[MAX_GENRE][MAX_GENRE_NAME];
char producer[MAX_PRODUCER_NAME];
char nationality[MAX_NATIONALITY_NAME];
int starting_year;
} artist;
/* and other structs */
typedef struct {
enum { USER, ARTIST } type;
union {
user *u_user;
artist *u_artist;
};
int size;
} data;
data.h
#ifndef DATA_H
#define DATA_H
#include "core.h"
extern user record_user[];
extern artist record_artist[];
extern data data_user;
extern data data_artist;
/* etc */
#endif
data.c
#include "data.h"
// SOME PRESET DATA
user record_user[] = {
{ 1, "Name 1", "Surname 1", "name1.surname1#email.com", ",+o[oS", { 29, 9, 1996 }, { 7, 3, 2011 }, { 18, 25, 58 }, 0 },
/** The list goes on **/
}
artist record_artist[] = {
{ 1, "Coldplay", { "Pop", "Britpop", "Alternative Rock" }, "Parlophone", "United Kingdom", 1997 },
/** The list goes on **/
}
data data_user = { .type = USER,.u_user = record_user,.size = MAX_USER };
data data_artist = { .type = ARTIST,.u_artist = record_artist,.size = MAX_ARTIST };
As you can see, there is a union struct for artist and user. I decided to create a union struct in order to pass multiple array of structs to a generic function. In the full code, I have more unions, but that's not the point to list them all. I just really need to understand what's I'm going to further explain below.
record_user like record_artist has some preset data that I link to data_user and data_artist respectively in data.c. Now this data needs to be increased during the runtime. I mean if record_user has 100 preset data rows (same thing for record_artist) in it, I'd like to add more rows or even remove them. For that I know there's malloc and realloc. I tried to play with it, making some tests and I don't know what's the best way of doing that.
I tried to declare in my main.c file the following:
int main() {
data_user.u_user = (user *)malloc(size * sizeof(user));
/***/
}
but I also tried with this
int main() {
record_user = (user *)malloc(size * sizeof(user));
/***/
}
but as I already imagined I lose all the preset data delcared in data.c file.
MY GOAL
What I'd like to achieve is to malloc a temp size for my data (for starting 100) and then to link the array of structs (or the union struct), with the starting temp size, to my preset data in order for using them. Naturally, during runtime, I will add more rows, and for that I'll use realloc (or even remove them).
This is the sample code of my add function:
data *add_data(data *record_data) {
date record_date;
tm record_time;
switch (record_data->type) {
case USER:
{
/* SOMEWHERE HERE I should use realloc to my record_data */
int ID = record_data->size;
record_data->u_user[ID].id = ID;
printf("\n\n\tNEW USER");
printf("\n\tEnter name: ");
strcpy(record_data->u_user[ID].name, inputString(MIN_USER_NAME, MAX_USER_NAME));
printf("\tEnter surname: ");
strcpy(record_data->u_user[ID].surname, inputString(MIN_USER_SURNAME, MAX_USER_SURNAME));
printf("\tEnter email: ");
strcpy(record_data->u_user[ID].email, inputString(MIN_USER_EMAIL, MAX_USER_EMAIL));
printf("\tEnter password: ");
strcpy(record_data->u_user[ID].password, inputString(MIN_PASSWORD_LENGTH, MAX_PASSWORD_LENGTH));
/* etc for birthday, subscription date */
record_data->size += 1;
printf("\n\tUser added!");
return record_data;
}
case ARTIST:
/* asking for input data */
return record_data;
}
}
this is how I call the function instead in the main.c file
int main() {
/***/
data_user = *add_data(&data_user);
/***/
}
I don't know how to move here, if I should work with the struct record_user or the union struct data_user. If it's the same or not... if I work with the original struct (allocating memory), is the union capable of reading the new memory size or not? Or is it best to work with the union struct leaving the original struct untouched?
I hope someone clear my mind!

can't seem to locate the struct

I am trying to fetch values from a struct once its been updated however the problem am facing is an undeclared error as it cannot seem to see it.
sonicNav.h file
#include<stdio.h>
#include<stdlib.h>
#include"sonicThread.h"
extern void calcSonicS();
sonicThread.c file.
int funcLock = 0;
void calcSonicS() {
struct results *rData = results;
rData = malloc(sizeof(struct results));
int newVal1 = rData->sens1;
int newVal2 = rData->sens2;
int newVal3 = rData->sens3;
int newVal4 = rData->sens4;
if(funcLock == 0){
funcLock = threadFunc();//returns INT value of 1.
}
printf("value 1: %d value 2: %d value 3: %d value 4 %d\n", newVal1, newVal2, newVal3, newVal4);
}
sonicThread.h file
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<signal.h>
#include<string.h>
#include<errno.h>
#include<pthread.h>
#include<sys/time.h>
#include<wiringPi.h>
//GPIO PINS stored within structs, for each sonic range finder.
typedef struct sonicPins{
//pins and id.
int trig;
int echo;
int id;
}args;
typedef struct results{
//all pins
int sens1;
int sens2;
int sens3;
int sens4;
}rData;
sonicThread.c file
void* setup(void *pinsPtr);
extern int threadFunc();
pthread_t pt[4];
int threadFunc()
{
struct sonicPins pinsArray[4] = { { 21, 20, 1 }, { 16, 12, 2 }, { 26, 19, 3 }, { 13, 6, 4 } };
for(int i =0; i <4; i++){
pthread_create(&pt[i], NULL, setup, &pinsArray[i] );
}
return 1;
}
void* setup(void *pinsPtr)
{
struct sonicPins *ptr = pinsPtr;
int trig = 0, Echo = 0, id;
trig = ptr->trig;
Echo = ptr->echo;
id = ptr->id;
struct results *storePtr;
}
The snippet above does update the struct "results", all threads does work concurrently each sensor giving out is own result.
Main.c
int main(){
//void(*foo1)(int, int, int);
//foo1 = &calcSonicS;
printf("In operation\n");
int operational = 1;
while(operational ==1)
{
//sonic range finders.
calcSonicS();
//gyroscope and acceometer.
}
return 0;
}
Error output:
sonicNav.c: In function ‘calcSonicS’:
sonicNav.c:5:28: error: ‘results’ undeclared (first use in this function)
sonicNav.c:5:28: note: each undeclared identifier is reported only once for each function it appears in
struct results *rData = results;
error: ‘results’ undeclared (first use in this function)
The above line tries to declare and define a local variable named rData, which has type struct results *, and initialise it with the value of the variable (local or global) results. The error message is telling you that there is no such variable.
What you're probably mixing up is C++ (old, bad) style initialisation:
MyClass variable = MyClass();
Since the next thing you do with rData is assigning it ...
rData = malloc(sizeof(struct results));
... the solution to your issue is to just remove that "wrong initialisation" from the preceeding line altogether. You could also pack it into a single line:
struct results *rData = malloc(sizeof(struct results));
Looking at ...
typedef struct results{
// ...
} rData;
... I'd guess that you have a serious misunderstanding of the relationship of structure (type) names, type names and variable names. The above definition gives you:
The name results as structure (type) name, so it can be used after struct to name the defined structure type.
The name rData as type name, referring to the same (structure) type as struct results.
When you then declare a variable struct results *rData you have additionally rData as name for a variable. This is possible, but far from good style.
If you remove the typedef, then things would change drastically: You'd then have a global variable named rData of type struct results.

structures and pointers error: dereferencing pointer to incomplete type

ok I have three structs:
struct rss_s {
Radio_types device_type; // Its device_type which is defined by the typedef above Radio_Types
char * device_info; // some thing about the radio NAV/COM/etc.
char * device_model; // the Manufactures part/model number.
char * device_serial; // the device's serial number..
int power_48v; // power to the unit..
int power_400hz;
int panel_lamps; // turn off or on the Panel Lamps only
void * radio_info;
struct radio_s_C614L8
{
loopsw_614L8 loop_sw_614L8; this is an emum
modesw_614L8 mode_sw_614L8; this is an emum
int sw_band;
int sw_bfo;
int meter;
tuner *Tuner;
int tuners;
};
typedef struct tuner_s
{
char *device_name; // OS NAME
int frequency[tuned];
int power;
int dial_lamp;
void * back_radio; // back-link to radios[n]
void * back_info; // back-link to radio_xxxx
int fd[];
} tuner;
I initialize them in main.c
// Radio 614L8
static tuner tuner_C614L8[] = {{ .device_name = "/dev/TBD", }};
static struct radio_s_C614L8 radio_C614L8 = { .Tuner = &tuner_C614L8, .tuners = DIM(tuner_C614L8) };
static struct rss_s radios[] = {
{ .device_type = C614L8,
.device_info = "ADF",
.device_model = "614L8",
.device_serial = "8384",
.radio_info = &radio_C614L8,},};
the above works with out errors....
but when I try to initialize the the above radio... in my init_C614L8.c
with the following code I get an error...
error: dereferencing pointer to incomplete type in lines 4 & 6
int init_C614L8( struct rss_s * radios ){
int rw, i;
struct radio_s_614L8 * rad_info = radios -> radio_info;
tuner * this_tuner = rad_info -> Tuner;
// Now we will loop over the sub_devices....
for ( i = 0; i < rad_info -> tuners; i++ ) {
I think I have to cast something but not shure
Thanks
In rss.h you declare
struct radio_s_C614L8
but in init_C614L8.c you use
struct radio_s_614L8
which is declared nowhere.
Update:
To fix this error
error: dereferencing pointer to incomplete type
In init_C614L8.c (and any other place, but rss.h) replace
struct radio_s_614L8
by
struct radio_s_C614L8
The lesson learned here is either go for some glasses or some sleep! ;-) And also: "The compiler never lies!"
This means that the definition of struct radio_s_614L8 is not visible to the code where the errors are seen. You have either forgotten to include the definition or there are #if... directives removing the definitions or includes you think are there.

Passing array of struct with typedef to a function

I need help with C programming. I have the following situation:
struct Product {
int code;
char *name;
char *spec;
int quantity;
float price;
};
typedef struct Product products[8];
products product = {
{100, "Mouse", "Ottico", 10, 8.30},
{101, "Tastiera", "Wireless", 6, 15.50},
{102, "Monitor", "LCD", 3, 150.25},
{103, "Webcam", "USB", 12, 12.00},
{104, "Stampante", "A Inchiostro", 6, 100.00},
{105, "Scanner", "Alta Risoluzione", 9, 70.50},
{106, "Router", "300 Mbps", 10, 80.30},
{107, "Lettore Mp3", "10 GB", 16, 100.00}
};
Please disregard the use of Italian language above.
I would like to pass the array of structs named "product" to a function. For example, if I wanted to do something like
product[1].name = "Computer"
But inside of a function, how am I supposed to do it? I would like to know how to call that function from the main() and how to write the prototype in my header file.
Thanks in advance for any help.
EDIT
I'm giving you this test program. This one ain't working and there is not even call to function in the main. It just doesn't compile.
#include <stdio.h>
#include <stdlib.h>
void test(Card *card);
int main()
{
struct Card {
char *type;
char *name;
};
typedef struct Card cards[2];
cards card = {{"Hi", "Hi"}, {"Foo", "Foo"}};
return 0;
}
void test(Card *card) {
printf("%s", card[1].type);
}
Here:
void foo(struct Product *bla)
{
bla[1].name = "Computer";
}
or using your type alias
void foo(products bla)
{
bla[1].name = "Computer";
}
then call the function like this:
foo(product);
Since you have the typedef (which is missing a struct keyword in your example, by the way), you can just use that type in the function prototype:
void func(products p);
A function performing the specific operation you asked about might be:
void func(products p)
{
p[1].name = "Computer";
}
You can call it like:
func(product);
From anywhere where product is in scope.
typedef struct tag_Product {
int code;
char *name;
char *spec;
int quantity;
float price;
} PRODUCT;
PRODUCT products[8] = {
{100, "Mouse", "Ottico", 10, 8.30},
{101, "Tastiera", "Wireless", 6, 15.50},
{102, "Monitor", "LCD", 3, 150.25},
{103, "Webcam", "USB", 12, 12.00},
{104, "Stampante", "A Inchiostro", 6, 100.00},
{105, "Scanner", "Alta Risoluzione", 9, 70.50},
{106, "Router", "300 Mbps", 10, 80.30},
{107, "Lettore Mp3", "10 GB", 16, 100.00}
};
void MyFunction(PRODUCT *pProduct)
{
pProduct->code = 0; // sample
}
void main()
{
MyFunction(&products[2]); // sample
}

Resources