1

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;
}
  • The three `struct` definitions are all the same (with one difference in the third). At least the first two could be the *same definition*. If they were all the same, the function would not need three different (but same) types to handle. – Weather Vane Jul 16 '20 at 16:30
  • You can attempt to write a function-like macro, or you can write a different function for each of these structs and then write a macro using C11's `_Generic` to select from these functions automatically based on the type passed in to it. – Christian Gibbons Jul 16 '20 at 16:36
  • @WeatherVane Yes, but than I would not be able to check the list, I would like for all the functionaly to be inside the function and now write code "outside" –  Jul 16 '20 at 16:38
  • @ChristianGibbons I have just strarted C so I am not familiar with macros, or the _Generic keyword, could you provide some example(if possible of course)? –  Jul 16 '20 at 16:39
  • I don't see why you can't have the same functionality for all three, inside the function. You can have three linked lists, one for admin, one for profs and one for students, each of identical type. I feel sure the student's one is mistaken, with its arrays of pointers and no link. – Weather Vane Jul 16 '20 at 16:40
  • 4
    include all three `struct` as members of a `union`, then add the `union` as a member of a _collector_ struct along with one more `enum` member to identify which of the three structs you are passing. – ryyker Jul 16 '20 at 16:41
  • BTW the function argument `struct ______ dati` should be `struct ______ *dati`. – Weather Vane Jul 16 '20 at 16:43
  • In C, you don't. – user253751 Jul 16 '20 at 16:44
  • See this answer for an example of using `_Generic` along with a function-like macro to select different functions based on the type of a passed-in argument: https://stackoverflow.com/a/51658694/8513665 – Christian Gibbons Jul 16 '20 at 16:47
  • @ChristianGibbons I added the following code, but the compiler says I have a syntax error. Can not seem to find it: #define confermaCredenziali(credenziali, uN, pW) _Generic((credenziali), struct amministratore*: confermaCredenzialiAmm, \ struct professore*: confermaCredProf, \ struct studente*: confermaCredenzialiStud \ )(credenziali, uN, pW) –  Jul 16 '20 at 17:32
  • Make sure that you are compiling with the C11 standard `-std=c11`. Also make sure you are using a modern C compiler like GCC or Clang. MSVC only really supports C89. – Christian Gibbons Jul 16 '20 at 19:27

3 Answers3

2

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.

Weather Vane
  • 33,872
  • 7
  • 36
  • 56
1

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

ryyker
  • 22,849
  • 3
  • 43
  • 87
0

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.

0___________
  • 60,014
  • 4
  • 34
  • 74