Lista di Liste in C - Progetto Universitario

di il
3 risposte

Lista di Liste in C - Progetto Universitario

Ciao a tutti, scrivo perchè ho un grossissimo problema. Uno dei miei ultimi esami per la laurea è fondamenti di informatica: il corso richiede un progetto utilizzando strutture dati. Senza perdermi troppo in discorsi, vi spiego il mio problema.

Il mio progetto è un social network e praticamente si compone di una lista in cui ho tutti gli utenti registrati con questa struct
struct utente {                
    char nome[20];                
    char cognome[20];
    char username[20];
    char password[20];
    char ddn[20];
    struct nodo_amici* amici;
    struct utente* next;      
};

typedef struct utente lista_utenti;
e non ho alcun problema con l'eliminazione dalla lista, aggiungere in testa o ordinatamente. Diciamo che con le liste me la cavo in maniera abbastanza sciolta.

Il campo puntatore amici dovrebbe idealmente puntarmi alla testa della lista personale di ogni utente e permettermi le operazioni su questa lista singola (inserisco la struct nodo_amici per facilitare la comprensione)
 struct nodo_amici{
  char username[20];
  struct nodo_amici* next;
};

typedef struct nodo_amici lista_amici;
Adesso, il mio problema è uno. Come faccio ad aggiungere campi alla mia lista amici personale? fin'ora ho cercato da solo una soluzione e (non ironicamente) sono 15 giorni che sbatto la testa con il risultato che mi ritrovo sempre una singola lista amici e quindi accedendo ad ogni utente trovo sempre la stessa lista di amici.

Non so se mi sono spiegato correttamente quindi vi faccio un esempio: io Fabio aggiungo Luca agli amici.
La soluzione a cui ero arrivato era: mi scorro tutta la lista utenti, nel momento in cui vado a trovare la persona a cui devo aggiungere l'amico (in questo caso io Fabio), mi copio su un puntatore temporaneo il puntatore della mia lista amici e poi la scorro e aggiungo Luca alla mia lista.

posto la mia soluzione (non funzionante) N.B. La funzione trovapers è un controllo per non far aggiungere persone non registrate alla mia lista amici:

int trovapers (lista_utenti *lista, char username[]){
    lista_utenti* r= lista; //precedente
    while(r!=NULL){
        if((strcmp(r->username, username))==0) {
              //  puts("L'utente è registrato al social! \n");
                return 0;
        }
        else {
            r=r->next;
        }
    }
    printf("Utente non registrato! \n");
    return 1;
}




int aggiungi_amico (struct utente **lista, char trovaptr[], char username[]) {//registrazione
    int trovato;
    struct nodo_amici** tmp = NULL;
    lista_utenti* s= *lista; //precedente
    while(s!=NULL){
        if((strcmp(s->username, trovaptr))==0)
                tmp=&(*lista)->amici;
        s=s->next;
        }
    
        trovato=trovapers(*lista, username);
        if(trovato==0){
              lista_amici* r= *tmp; //precedente
              lista_amici* q= *tmp; //successivo
              lista_amici* p=(lista_amici*)malloc(sizeof(lista_amici)); //alloco nuovo nodo
              if (p==NULL) return 1; //se non alloco il nodo allora restituisco 1
              strcpy(p->username, username);
               p->next=NULL;
        
        if(q==NULL){
              lista_amici* p;
              p =(lista_amici*)malloc(sizeof(lista_amici));
              strcpy(p->username, username);
              p->next=*tmp;
              *tmp=p;
              return 0;
          }
        
        while((q!=NULL)&&(strcmp(q->username, p->username)<0)){
              r=q;
              q=q->next;
          }

       if(q==*tmp){
            p->next=*tmp;
           *tmp=p;
            return 0;
            }
        else{
            r->next=p;
            p->next=q;
            }
        return 0; //se tutto è andato correttamente resistuisco 0
    }
    else return 1;
}
Ultima cosa, il mio progetto è fatto con due header, uno utenti e uno amici e per non intasare il post non vado a postare tutto il codice. Sono aperto a qualsiasi richiesta pur di farmi passare questo DANNATISSIMO esame che io già so, mi farà laureare fuori corso.
Grazie infinite a tutti

3 Risposte

  • Re: Lista di Liste in C - Progetto Universitario

    Secondo me l'approccio di fare una "lista amici" per ogni persona è sbagliato. Se un utente A è amico a B, allora B è amico ad A. Se pensi a un database, la tabella Utenti sarebbe in relazione molti-a-molti con sè stessa per quanto riguarda le amicizie. Questo si risolve con una terza tabella "Amicizie" dove ogni record memorizza i due utenti A e B. Nel tuo caso si tradurrebbe in una terza lista.
    Diversamente se fosse un meccanismo di follower, dove la relazione è a senso unico, avrebbe più senso farlo come hai fatto tu.
  • Re: Lista di Liste in C - Progetto Universitario

    Ciao, da un'occhiata veloce al codice secondo me ti stai complicando troppo la vita, io farei qualcosa del genere:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct amico_
    {
        char username[20];
        struct amico_ *next;
    }   amico;
    
    typedef struct utente_
    {
        char username[20];
        unsigned int eta;
        amico *lista_amici;
        struct utente_ *next;
    }   utente;
    
    void aggiungi_in_testa_amico(amico **p, const char username[20])
    {
        amico *nuovo = (amico*)malloc(sizeof(amico));
        strcpy(nuovo->username, username);
        nuovo->next = *p;
        *p = nuovo;
    }
    
    void aggiungi_in_testa_utente(utente **p, const char username[20], const unsigned int eta)
    {
        utente *nuovo = (utente*)malloc(sizeof(utente));
        strcpy(nuovo->username, username);
        nuovo->eta = eta;
        nuovo->lista_amici = NULL;
        nuovo->next = *p;
        *p = nuovo;
    }
    
    amico* trova_amico(amico *p, const char username[20])
    {
        while(p && strcmp(p->username, username))
        {
            p = p->next;
        }
        return p;
    }
    
    utente* trova_utente(utente *p, const char username[20])
    {
        while(p && strcmp(p->username, username))
        {
            p = p->next;
        }
        return p;
    }
    
    void aggiungi_amico(utente *p, const char utente[20], const char amico[20])
    {
        if(strcmp(utente, amico) && (p = trova_utente(p, utente)))
        {
            if(!trova_amico(p->lista_amici, amico))
            {
                aggiungi_in_testa_amico(&p->lista_amici, amico);
            }
        }
    }
    
    void stampa_lista_amici(amico *p)
    {
        while(p)
        {
            printf("%s ", p->username);
            p = p->next;
        }
    }
    
    void stampa_lista_utenti(utente *p)
    {
        while(p)
        {
            printf("%s\t%2u anni | amici: ", p->username, p->eta);
            stampa_lista_amici(p->lista_amici);
            printf("\n");
            p = p->next;
        }
    }
    
    int main()
    {
        utente *lista = NULL;
        aggiungi_in_testa_utente(&lista, "LUCA", 20);
        aggiungi_in_testa_utente(&lista, "ALDO", 21);
        aggiungi_in_testa_utente(&lista, "MARTA", 22);
        aggiungi_in_testa_utente(&lista, "MIRCO", 23);
        aggiungi_in_testa_utente(&lista, "GIORGIO", 24);
        aggiungi_amico(lista, "MARTA", "GIORGIO");
        aggiungi_amico(lista, "ALDO", "GIORGIO");
        aggiungi_amico(lista, "MARTA", "LUCA");
        aggiungi_amico(lista, "GIORGIO", "MARTA");
        aggiungi_amico(lista, "MIRCO", "ALDO");
        aggiungi_amico(lista, "MIRCO", "GIORGIO");
        aggiungi_amico(lista, "MARTA", "MIRCO");
        aggiungi_amico(lista, "LUCA", "ALDO");
        aggiungi_amico(lista, "ALDO", "LUCA");
        stampa_lista_utenti(lista);
        return 0;
    }
    Relativamente al codice, non ho ricontrollato quello che ho scritto, potrebbe quindi esserci qualche errore, in ogni caso il punto è l'impostazione logica del programma mediante brevi funzioni generiche.


    P.S.
    Modificare la struct
    struct nodo_amici
    {
    	char username[20];
    	struct nodo_amici* next;
    };
    in
    struct nodo_amici
    {
    	struct utente* amico;
    	struct nodo_amici* next;
    };
    potrebbe portare alcuni vantaggi, ma per il momento, assodato che l'username sia una chiave univoca, può andar bene anche così.
  • Re: Lista di Liste in C - Progetto Universitario

    Ringrazio veramente tantissimo entrambi per la risposta... proverò ad attuare queste vostre idee e mi farò risentire. Buon Ferragosto!
Devi accedere o registrarti per scrivere nel forum
3 risposte