use a struct into an other struct c - c

I have a problem using a struct in the C language.
It is very strange !!!
I cant use course struct in student struct.
I have defined it before but ...
why?
struct course
{
int no;
char name[30];
int credits;
float score;
};
struct student
{
int no;
char name[50];
course c[3];
};
My language is c not c++

One of the differences between C++ and C is that you can omit type keywords such as class and struct when using C++ types.
The problem is the line course c[3];. In order to make it work, you have two choices--you can use a typedef on your struct course:
typedef struct _course // added an _ here; or we could omit _course entirely.
{
int no;
char name[30];
int credits;
float score;
} course;
or you can add the keyword struct in front of the broken line, i.e. structcourse c[3];.

You need to prefix the struct name with the struct keyword:
struct course
{
int no;
char name[30];
int credits;
float score;
};
struct student
{
int no;
char name[50];
struct course c[3];
};

struct course c[3];
should work...

struct student {
/* ... */
struct course c[3];
}
or
typedef struct _course {
/* ... */
} course;
struct student {
/* ... */
course c[3];
}

You should actually be able to define an anonymous struct and then typedef it, so:
typedef struct {
/* stuff */
} course;
and then as the others have said,
struct student {
course c[3];
}

typedefs are helpful, because they allow you to shorten declarations, so you are not always having to type the word struct.
Here is an example involving typedef-ing your structs. It also includes a course struct in the student struct.
#include <stdio.h>
#include <string.h>
typedef struct course_s
{
int no;
char name[30];
int credits;
float score;
} course;
typedef struct student_s
{
int no;
char name[50];
course c[3];
} student;
bool isNonZero(const int x);
int main(int argc, char *argv[])
{
int rc = 0;
student my_student;
my_student.c[0].no = 1;
return rc;
}

Related

what is meant by item-type be presented by ony one field/member

Information about shelf and compartment should be stored as two integer values (one for the shelf number and one for the compartment number) but should in the item-type be presented by only one field/member (you will therefore need to define a new type for the place).
struct GrocaryItem{
char productName[20];
float amount;
char unit[10];
char FileName[30];
};
struct ShoppingList{
int length;
struct GrocaryItem *itemList;
};
How can I do it? Can I just write...
struct GrocaryItem{
char productName[20];
float amount;
char unit[10];
char FileName[30];
};
struct ShoppingList{
int length;
struct GrocaryItem *itemList;
struct ExtraInfo *ShelfCompartment;
};
struct ExtraInfo {
int shelf;
int compartment;
};
You could add the new field in the struct representing the item so that if you have a GrocaryItem variable x you can do x.info.shelf or x.info.compartment.
struct ExtraInfo {
int shelf;
int compartment;
};
struct GrocaryItem{
char productName[20];
float amount;
char unit[10];
char FileName[30];
struct ExtraInfo info;
};
To add to the solution, if you wanted to pass that value as one integer and print it as two, this would be a great use of a union. Especially useful if it's going to be a primary key.
#include <stdio.h>
#include <inttypes.h>
union ExtraInfo {
struct { uint16_t shelf, compartment; } split;
uint32_t together;
};
struct GroceryItem {
union ExtraInfo info;
char productName[20];
float amount;
char unit[10];
char FileName[30];
};
int main(void) {
union ExtraInfo a = { 10, 10 }, b = { 8, 10 };
printf("They are %s.\n",
a.together == b.together ? "the same" : "different");
return 0;
}
The shopping list should generally not modify the GroceryItem. This way you break the dependency on GroceryItem, only storing a reference. If one were to serialize the shopping list, (into a file, for example,) one could store the ExtraInfo of the GroceryItem, assuming it is unique, like a synecdoche.
struct ShoppingListItem {
struct GroceryItem *item;
int amount;
};
struct ShoppingList {
size_t size;
struct ShoppingListItem *items;
};

Overloading with struct in C

I am trying to write a function with the same name, but that accepts 3 different typers of structs.I don't know how I can write the parameters to do this.So in the _______, there should be proffesore, amminustratore, studente. Sp that the function can accept all 3 types of struct but only one at the time.
Here is the code:
int confermaCredenziali(struct ______ dati, char *uN, char *pW);
struct amministratore{
char userName[MAX_LNG];
char passWord[MAX_LNG];
int stato;
struct ammin *next;
};
struct professore{
int ID;
char userName[MAX_LNG];
char passWord[MAX_LNG];
int stato;
struct prof *next;
};
struct studente{
int ID;
char *userName[MAX_LNG];
char *passWord[MAX_LNG];
int punti;
int stato;
struct studente *next;
};
int confermaCredenziali(struct ______ dati, char *uN, char *pW){
while (dati != NULL) {
if (strcmp(dati->userName, uN) == 0 && strcmp(dati->passWord, pW) == 0){
if (dati->stato == 1)
return 1;
else{
printf("Il suo stato e' passivo.\n");
return 0;
}
}
dati = dati->next;
}
printf("Credeziali errate.\n");
return 0;
}
I suggest a single struct type like this
typedef struct person {
char userName[MAX_LNG];
char passWord[MAX_LNG];
int stato;
struct person *next;
} person_t;
Then you have three linked lists
person_t *amministratore = NULL;
person_t *professore = NULL;
person_t *studente = NULL;
Also, the function needs a pointer argument, I suggest
int confermaCredenziali(person_t *dati, char *uN, char *pW)
Then you pass the head of the linked list you have selected, to the function. It works with one list at a time, and the three lists are completely separate.
As stated earlier in comments:
Create as follows:
Include all three struct as members of a union.
add the union as a member of a collector struct.
Add an additional enum member to the collector struct to identify which of the three struct you are passing.
The following illustrates:
typdef enum {
ADMIN,
PROF,
STUD,
MAX_S
}S_TYPE;
typedef struct {
...
}amministratore;
typedef struct {
...
}professore;
typedef struct {
...
}studente;
typedef union{
administratore admin;
professore prof;
studente stud;
}s_union;
typedef struct {
s_union;
S_TYPE type;
}collector;
Your prototype would be modified to:
int confermaCredenziali(collector *c, S_Type type, dati, char *uN, char *pW);
As mentioned also in comments, the argument for this struct as passed in the prototype should be as pointer, so that the members can be changed, and for efficiency, as a pointer is often times smaller than the entire struct
this example is trivial but you can do something like this:
enum type{STUD = 0, PROF, ADMIN};
int confermaCredenzialiSTUD(void *dati, char *uN, char *pW);
int confermaCredenzialiPROF(void *dati, char *uN, char *pW);
int confermaCredenzialiADMIN(void *dati, char *uN, char *pW);
const int (*credenziali[3])(void *, char *, char *) =
{confermaCredenzialiSTUD, confermaCredenzialiPROF, confermaCredenzialiADMIN};
int confermaCredenziali(enum type t, void *dati, char *uN, char *pW)
{
return redenziali[t](dati, uN, pW);
}
and in the functions do correctly what you need for the particular type.

pointers to structs inside union: how to initialize and retrieve struc values

I have the following simple code. I am trying to understand how I can use structs inside unions and how I can retrieve contents of struct variables in connection with unions.
Here is a small sample code I have written. I want to retrieve the "Maker" struct variables from this code. How should I correctly do it? My code here results in segmentation fault.
Here is the updated code :
#include <stdio.h>
#include <stdlib.h>
typedef struct{
char *name;
int *wheels;
}CarVendor;
typedef struct{
char *name;
int *wheels;
int seats;
}BusVendor;
typedef union{
CarVendor *carvendor;
BusVendor *busvendor;
}Maker;
typedef struct{
Maker *carType;
}Car;
typedef struct{
Maker *busType;
}Bus;
typedef union{
Car *car;
Bus *bus;
}Vehicle;
void fillDetails(Vehicle *vehicle, int type){
if(type == 0){
vehicle->car->carType->carvendor->name = "car";
int wheel = 4;
vehicle->car->carType->carvendor->wheels = &wheel;
}
if(type ==1){
vehicle->bus->busType->busvendor->name = "bus";
int wheel = 6;
vehicle->bus->busType->busvendor->wheels = &wheel;
vehicle->bus->busType->busvendor->seats = 60;
}
}
int main(int argc, char *argv[])
{
Vehicle myvehicle;
fillDetails(&myvehicle, 0); //get car details filled & retrieve the details as "Maker" struct
Maker *maker;
maker = (Maker *) malloc(sizeof(Maker));
maker = myvehicle.car->carType;
printf("Name of car =%s", maker->carvendor->name);
return 0;
}
Are you sure you want everything to be on the heap?
If you really want to, you need to malloc memory for ALL the structures that you've got pointers to (or at least the ones you want to access, e.g. from fillDetails), and clean up afterwards. Your union, e.g. Maker, essentially just says that this pointer can be one of two types, either a CarVendor, or a BusVendor.
If you want to do this kind of stuff it sometimes makes sense to have a "type" distinguisher in the structure, such that the code looking at it later knows which type the pointer has. Here's an example:
typedef struct a_t_ { /*...*/ } a_t;
typedef struct b_t_ { /*...*/ } b_t;
typedef enum mytype_t_ {a, b} mytype_t;
typedef struct foo_t_ {
mytype_t type_of_the_below;
union {
a_t *a;
a_t *b;
};
} foo_t;
Again, notice that you need to malloc the memory for the Maker before you access it from fillDetails, not after.
#include <stdio.h>
#include <stdlib.h>
typedef struct{
char *name;
int *wheels;
}CarVendor;
typedef struct{
char *name;
int *wheels;
int seats;
}BusVendor;
typedef union{
CarVendor *carvendor;
BusVendor *busvendor;
}Maker;
typedef struct{
Maker *carType;
}Car;
typedef struct{
Maker *busType;
}Bus;
typedef union{
Car *car;
Bus *bus;
}Vehicle;
void fillDetails(Vehicle *vehicle, int type){
if(type == 0){
vehicle->car->carType->carvendor->name = "car";
int wheel = 4;
vehicle->car->carType->carvendor->wheels = &wheel;
}
if(type ==1){
vehicle->bus->busType->busvendor->name = "bus";
int wheel = 6;
vehicle->bus->busType->busvendor->wheels = &wheel;
vehicle->bus->busType->busvendor->seats = 60;
}
}
int main(int argc, char *argv[])
{
Vehicle myvehicle;
myvehicle.car = (Car*) malloc(sizeof(Car));
myvehicle.car->carType = (Maker*)malloc(sizeof(Maker));
myvehicle.car->carType->carvendor = (CarVendor*) malloc(sizeof(CarVendor));
fillDetails(&myvehicle, 0); //get car details filled & retrieve the details as "Maker" struct
Maker *maker = NULL;
maker = myvehicle.car->carType;
printf("Name of car =%s\n", maker->carvendor->name);
free(myvehicle.car->carType->carvendor);
free(myvehicle.car->carType);
free(myvehicle.car);
return 0;
}
Here's how you can more safely do it on the stack...
#include <stdio.h>
#include <stdlib.h>
typedef struct{
char *name;
int wheels;
}CarVendor;
typedef struct{
char *name;
int wheels;
int seats;
}BusVendor;
typedef union{
CarVendor carvendor;
BusVendor busvendor;
}Maker;
typedef struct{
Maker carType;
}Car;
typedef struct{
Maker busType;
}Bus;
typedef union{
Car car;
Bus bus;
}Vehicle;
void fillDetails(Vehicle *vehicle, int type){
if(type == 0){
vehicle->car.carType.carvendor.name = "car";
int wheel = 4;
vehicle->car.carType.carvendor.wheels = wheel;
}
if(type ==1){
vehicle->bus.busType.busvendor.name = "bus";
int wheel = 6;
vehicle->bus.busType.busvendor.wheels = wheel;
vehicle->bus.busType.busvendor.seats = 60;
}
}
int main(int argc, char *argv[])
{
Vehicle myvehicle;
fillDetails(&myvehicle, 0); //get car details filled & retrieve the details as "Maker" struct
Maker *maker;
maker = &myvehicle.car.carType;
printf("Name of car =%s\n", maker->carvendor.name);
return 0;
}

Can't print structure variable

#include <stdio.h>
#include <stdlib.h>
typedef struct {
char name[20];
int age;
} employee;
int main(int argc, char** argv)
{
struct employee em1 = {"Jack", 19};
printf("%s", em1.name);
return 0;
}
This doesn't seem to work because, as the compiler says, the variable has incomplete type of 'struct employee'. What's wrong?
Remove struct from
struct employee em1 = {"Jack", 19};
You used
typedef struct
{
char name[20];
int age;
}
with the purpose of not requiring to type struct anymore.
The problem is that you made the struct a typedef, but are still qualifying it with struct.
This will work:
employee em1 = {"Jack", 19};
Or remove the typedef.
To use struct employee em1 = ... you need to declare the struct with a tag.
struct employee /* this is the struct tag */
{
char name[20];
int age;
} em1, em2; /* declare instances */
struct employee em3;
typedef creates a type alias which you use without the struct keyword.
typedef struct employee employee;
employee em4;
As you have already typedef your structure, you are not required to add struct keyword again.
typedef struct Employee{
char name[20];
int age;
} employee;
int main(int argc, char** argv)
{
employee em1 = {"Jack", 19};
printf("%s", em1.name);
return 0;
}

Error: Conversion to non-scalar type requested

I'm having a small problem trying to malloc this struct.
Here is the code for the structure:
typedef struct stats {
int strength;
int wisdom;
int agility;
} stats;
typedef struct inventory {
int n_items;
char **wepons;
char **armor;
char **potions;
char **special;
} inventory;
typedef struct rooms {
int n_monsters;
int visited;
struct rooms *nentry;
struct rooms *sentry;
struct rooms *wentry;
struct rooms *eentry;
struct monster *monsters;
} rooms;
typedef struct monster {
int difficulty;
char *name;
char *type;
int hp;
} monster;
typedef struct dungeon {
char *name;
int n_rooms;
rooms *rm;
} dungeon;
typedef struct player {
int maxhealth;
int curhealth;
int mana;
char *class;
char *condition;
stats stats;
rooms c_room;
} player;
typedef struct game_structure {
player p1;
dungeon d;
} game_structure;
And here is the code I'm having a problem with:
dungeon d1 = (dungeon) malloc(sizeof(dungeon));
It gives me the error "error: conversion to non-scalar type requested"
Can someone help me understand why this is?
You can't cast anything to a structure type. What I presume you meant to write is:
dungeon *d1 = (dungeon *)malloc(sizeof(dungeon));
But please don't cast the return value of malloc() in a C program.
dungeon *d1 = malloc(sizeof(dungeon));
Will work just fine and won't hide #include bugs from you.
malloc returns a pointer, so probably what you want is the following:
dungeon* d1 = malloc(sizeof(dungeon));
Here is what malloc looks like:
void *malloc( size_t size );
As you can see it return void*, however you shouldn't cast the return value.
The memory assigned by malloc must be stored in a pointer to an object, not in the object itself:
dungeon *d1 = malloc(sizeof(dungeon));

Resources