Overloading with struct in C - 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.

Related

Void * that saves different structs

typedef struct s_list
{
void *content;
struct s_list *next;
} t_list;
typedef struct s_env
{
char *key;
char *val;
struct s_env *next;
} t_env;
typedef struct s_heredoc
{
char *term;
char *delimiter;
char *heredoc;
} t_heredoc;
typedef struct s_cmd
{
char *cmd;
char *path;
int istream;
int ostream;
} t_cmd;
typedef struct s_table{
char **paths;
char **reserved;
char *cmdline;
t_list *cmds;
} t_table;
I have a general struct t_table which have a pointer to t_list struct called cmds.
How can i save different structs for example t_env, t_heredoc, t_cmd in void * content; property of t_list struct. How should I cast the void * content to another type (t_env, t_cmd, t_heredoc, etc)
void lexical_analyze(char *cmdline, t_table **table)
{
cmdline = openquotes(cmdline);
cmdline = find_replace(cmdline, (*table)->env);
(*table)->cmds = malloc(sizeof(t_list));
}
After this point i can’t understand how to cast and how to allocate a memory for the other structs for example t_cmd struct
You can assign a pointer to any struct to your context member. But if you want to use that struct later, you will need to recover the original pointer type. That means you must store extra information about type of your content in your struct:
typedef enum {
CT_Env,
CT_Cmd,
CT_HereDoc
} t_context_type;
typedef struct s_list
{
void *content;
t_context_type type;
struct s_list *next;
} t_list;
t_list *add_Env(t_env *env)
{
t_list *list = malloc(sizeof *list);
... Do the list handling...
list->context = env;
list->type = CT_Env;
return list;
}
Then, when you want to access the nodes of your list you can cast to correct type:
void handle_node(t_list *list)
{
switch (list->type)
{
case CT_Env:
{
t_env *env = list->context;
// Access members of t_enf via env pointer
}
break;
case CT_Cmd: // TODO handle t_cmd type
break;
case CT_HereDoc: // TODO handle t_heredoc type
break;
default: // TODO: Error handling
break;
}
}
Of course that code is not complete. It should show how it is supposed to work.

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;
};

How to combine two different type variables?

I have two functions, the body is exactly same, only the parameter is different:
int setCustomerUser(struct userCustomer *user, struct profile *data) {
user->type = data->type;
// .... A
}
int setAdminUser(struct userAdmin *user, struct profile *data) {
user->type = data->type;
// .... B
}
A and B are same.
userCustomer and userAdmin are basically same, except some different.
struct userCustomer {
int type;
char *name;
char *mail;
int gender;
char *address;
int point;
// ....
}
struct userAdmin {
int type;
char *name;
char *mail;
int dept;
// ....
}
So I would like to combine the two functions into one, something like this:
int setUser(void *user1, struct profile *data, int userType) {
if(userType == 0) {
struct userCustomer *user = (struct userCustomer *)user1;
} else {
struct userAdmin *user = (struct userAdmin *)user1;
}
user->type = data->type;
// ...
}
But as you know C is not Python, it does not work. How can I achieve this?
Extract the common fields into a common struct.
struct userCommon {
int type;
char *name;
char *mail;
};
struct userCustomer {
struct userCommon c;
int gender;
char *address;
int point;
};
struct userAdmin {
struct userCommon c;
int dept;
};
int userCommon_setType(struct userCommon *c, struct profile *data) {
c->type = data->type;
return 62;
}
int userCustomer_setType(struct userCustomer *user, struct profile *data) {
return userCommon_setType(&user->c, data);
}
int userAdmin_setType(struct userCustomer *user, struct profile *data) {
return userCommon_setType(&user->c, data);
}
You could use a union member in the struct like this:
struct user {
int type;
char *name;
char *mail;
union {
struct {
int gender;
char *address;
int point;
// ....
} customer;
struct {
int dept;
// ....
} admin;
};
};
To distinguish values of both types, it makes sense to store the "type" right inside the struct. That's what type already does, even though I would use an enum.
You access the common parts like before:
user->type = ...;
And the special part like this (but you probably know this):
user->customer.gender = ...;
user->admin.dept = ...;
I suggest using the prototype with 2 parameters are 2 struct instead of using userType
The example:
int setUser(userCustomer *user, userAdmin *admin, struct profile *data)
{
if(user != NULL)
{
user->type = data->type;
}
if (admin != NULL)
{
admin->type = data->type;
}
// ...
}

use a struct into an other struct 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;
}

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