PROBLEMA Lista di Liste in C - Progetto Universitario

shine98

Nuovo Utente
55
0
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

Codice:
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)

Codice:
 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:

Codice:
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
 

bigendian

Utente Attivo
749
432
OS
Linux
Un idea semplice, come "nodo amici" terrei una lista semplice (array reallocato, vedi realloc(), reallocarray) di puntatori alle strutture utenti degli amici (quindi un array di "struct utente *"), e un "int" come counter amici, per riallocare con facilita' e traversare, anche se per traversare puoi terminare a 0 l'ultimo pointer.
 

Andretti60

Utente Èlite
6,440
5,091
la tua soluzione e' fondamentalmente sbagliata, proprio a livello di strutture di dati.

In questo caso hai una lista globale di utenti che metti in una lista concatenata, quella parte e' corretta.

Il problema e' l'associazione degli amici, che sono una coppia, ossia A e' amico di B e viceversa, quindi con il tuo approccio dovresti aggiungere B all'utente A ed A all'utente B. Mantenere una cosa del genere e' fattibile, ma crea solo problemi, quindi NON si fa. La soluzione e' quella di creare un'altra struttura Amici (due campi, ossia due amici) e metterla in un altra lista concatenata (esattamente come si fa con un database, si crea una nuova tabella che associa due record di tabelle diverse). Quando due utenti diventano amici, basta creare una nuova struttura Amici (con utenti A e B) e aggiungerla alla nuova lista. Quando uno dei due cancella l'amicizia, si elimina tale struttura dalla lista.

Visto che questo e' un progetto per un esame evito di scriverti codice, pensaci su e se hai problemi chiedi pure.
 

shine98

Nuovo Utente
55
0
Intanto ringrazio entrambi per la risposta. Grazie davvero.

Un idea semplice, come "nodo amici" terrei una lista semplice (array reallocato, vedi realloc(), reallocarray) di puntatori alle strutture utenti degli amici (quindi un array di "struct utente *"), e un "int" come counter amici, per riallocare con facilita' e traversare, anche se per traversare puoi terminare a 0 l'ultimo pointer.

Purtroppo il professore non permette l'utilizzo di array nel programma, quindi non posso utilizzare questa idea.

la tua soluzione e' fondamentalmente sbagliata, proprio a livello di strutture di dati.

In questo caso hai una lista globale di utenti che metti in una lista concatenata, quella parte e' corretta.

Il problema e' l'associazione degli amici, che sono una coppia, ossia A e' amico di B e viceversa, quindi con il tuo approccio dovresti aggiungere B all'utente A ed A all'utente B. Mantenere una cosa del genere e' fattibile, ma crea solo problemi, quindi NON si fa. La soluzione e' quella di creare un'altra struttura Amici (due campi, ossia due amici) e metterla in un altra lista concatenata (esattamente come si fa con un database, si crea una nuova tabella che associa due record di tabelle diverse). Quando due utenti diventano amici, basta creare una nuova struttura Amici (con utenti A e B) e aggiungerla alla nuova lista. Quando uno dei due cancella l'amicizia, si elimina tale struttura dalla lista.

Visto che questo e' un progetto per un esame evito di scriverti codice, pensaci su e se hai problemi chiedi pure.

Ti ringrazio e veramente la tua idea è semplicemente fantastica, grande idea. Però per farlo più semplice il mio social l'ho pensato alla mo' di instagram, ovvero se io ti aggiungo alla mia lista di amici, non automaticamente vengo aggiunto alla tua lista.. devo fare un po il paraculo perchè esame si ma se posso semplificarmi il lavoro che ben venga ??
 

BAT

Moderatore
Staff Forum
Utente Èlite
22,944
11,580
CPU
1-Neurone
Dissipatore
Ventaglio
RAM
Scarsa
Net
Segnali di fumo
OS
Windows 10000 BUG
ovvero se io ti aggiungo alla mia lista di amici, non automaticamente vengo aggiunto alla tua lista
l'idea di @Andretti60 funziona ugualmente, basta che definisci le coppie di amici come se fossero ordinate (A, B) per capirsi, nel senso la coppia (A,B) significa che B è nella lista di amici di A, ma il viceversa non è vero, a meno che non compaia la coppia (B,A)
questo creerà ridondanze ma è sopportabile
 

Andretti60

Utente Èlite
6,440
5,091
.. se io ti aggiungo alla mia lista di amici, non automaticamente vengo aggiunto alla tua lista..
veramente non funziona cosi' nei social (hai citato Instagram, che uso anche io). Puoi "seguire" una altro utente, senza esserci uno scambio, l'altro utente viene notificato di essere seguito e basta. Per l'amicizia e' diverso, si chiede l'amicizia e se questa viene accettata si e' entrambi amici, ognuno e' nella lista dell'altro.

Sinceramente non capisco, dici di essere versato nelle liste concatenate, questo e' un problema banale, il fatto che la testa della lista sia in un campo di un'altra lista non cambia nulla, il procedimento di aggiungere una struttura rimane lo stesso.
Non ho guardato tutto il tuo codice per vari motivi, e' indentato male e le variabili hanno nomi senza senso, e' un codice estremamente difficile da leggere.

prendi per esempio questa parte (di cui ho corretto l'indentazione)

C:
    lista_utenti* s= lista;
    while(s!=NULL)
    {
        if((strcmp(s->username, trovaptr))==0)
             tmp=&(*lista)->amici;
         s=s->next;
     }
che ha due errori, il primo e' che non esci dal ciclo appena trovi la persona giusta, il secondo e che memorizzi in tmp (che brutta scelta di nome per una variabile...) il puntatore del campo amici del primo elemento della lista, invece di quello corrente.
 

Ci sono discussioni simili a riguardo, dai un'occhiata!

Entra

oppure Accedi utilizzando
Discord Ufficiale Entra ora!

Discussioni Simili