[RISOLTO] Inserimento in lista ordinata alfabeticamente [C]

di il
41 risposte

[RISOLTO] Inserimento in lista ordinata alfabeticamente [C]

Buongiorno, sto imparando a lavorare con le liste e sto facendo un esercizio in cui devo
- Creare Lista
- Stampare
- Inserire in ordine alfabetitco
- Cancellare

Nella fase di inserimento in ordine alfabetico ho dei problemi perchè non riesco ad effettuare correttamente il confronto con il nome una volta effettuata quella del cognome
//FUNZIONE INSERIMENTO ORDINATO IN LISTA
t_lista inserimento_lista(t_lista lista,t_persona persona)
{
  t_lista prec,corr,nuovo;
  prec=NULL; //Inizio dalla testa
  corr=lista;

  //--FASE 1-- -> Ricerca della posizione nella quale inserire l'elemento nella lista
  printf("\nFASE 1\n");
  while(corr != NULL && strcmp(persona.cognome,corr->persona.cognome)>=0)// && strcmp(persona.nome,corr->persona.nome)>=0)
  {
    printf("\nCerco posizione cognome\n");
    prec=corr;
    corr=corr->next;
  }

  if(strcmp(persona.cognome,corr->persona.cognome)==0)
  {
    while(corr!=NULL && strcmp(persona.nome,corr->persona.cognome)>=0)
    {
      prec=corr;
      corr=corr->next;
    }
  }
  printf("\nPosizione trovata...\n");
  //-> Posizione trovata ->
  //--FASE 2-- -> Inserimento della 'Persona' in lista tramite 'Allocazione Dinamica della Memoria'
  printf("\nFASE 2\n");
  nuovo=(t_nodo *)malloc(sizeof(t_nodo));
  if(nuovo==NULL)
    printf("!ERRORE!");
  else
    nuovo->persona=persona;
  //-> Persona inserita nella lista ->

  //--FASE 3-- Aggiornamento delle posizioni
  printf("\nFASE 3\n");
  if(prec==NULL)//Se siamo in 'Testa'
  {
    nuovo->next=lista;
    lista=nuovo;
    return lista;
  }
  else
  {
    prec->next=nuovo;
    nuovo->next=corr;
    return lista;
  }
  
  /*//COMMENTATA
  if(strcmp(persona.cognome,corr->persona.cognome)==0)
  {
    printf("\nVerifico cognome uguale...\n");
    while(corr!=NULL && strcmp(persona.nome,corr->persona.nome)>=0)
    {
      printf("\nCerco posizione nome...\n");
      prec=corr;
      corr=corr->next;
    }
  }
  prec->next=nuovo;
  nuovo->next=corr;
  *///COMMENTATA
}

Inizialmente avevo scritto la parte alla fine del codice (quella commentata per intenderci) ma poi mi ero reso conto che non effettuava il contollo sull'ordinamento per nome.
Allora ho utilizzato questo tipo di approccio:
 while(corr != NULL && strcmp(persona.cognome,corr->persona.cognome)>=0)// && strcmp(persona.nome,corr->persona.nome)>=0)
  {
    printf("\nCerco posizione cognome\n");
    prec=corr;
    corr=corr->next;
  }

  if(strcmp(persona.cognome,corr->persona.cognome)==0)
  {
    while(corr!=NULL && strcmp(persona.nome,corr->persona.cognome)>=0)
    {
      prec=corr;
      corr=corr->next;
    }
  }
Una volta che inserisco Cognome e Nome dopo un pò il programma esce.
Dove sbaglio?
Posso effettuare un controllo contemporaneo sia di nome e cognome? (come potete vedere nel primo while c'è una parte di riga di codice commentata)
Spero di essere stato chiaro.

Grazie in anticipo

41 Risposte

  • Re: [RISOLTO] Inserimento in lista ordinata alfabeticamente [C]

    Xavier25 ha scritto:


    Inizialmente avevo scritto la parte alla fine del codice (quella commentata per intenderci) ma poi mi ero reso conto che non effettuava il contollo sull'ordinamento per nome.
    Allora ho utilizzato questo tipo di approccio:
     while(corr != NULL && strcmp(persona.cognome,corr->persona.cognome)>=0)// && strcmp(persona.nome,corr->persona.nome)>=0)
      {
        printf("\nCerco posizione cognome\n");
        prec=corr;
        corr=corr->next;
      }
    
      if(strcmp(persona.cognome,corr->persona.cognome)==0)
      {
        while(corr!=NULL && strcmp(persona.nome,corr->persona.cognome)>=0)
        {
          prec=corr;
          corr=corr->next;
        }
      }
    Una volta che inserisco Cognome e Nome dopo un pò il programma esce.
    Dove sbaglio?
    Posso effettuare un controllo contemporaneo sia di nome e cognome? (come potete vedere nel primo while c'è una parte di riga di codice commentata)
    Spero di essere stato chiaro.

    Grazie in anticipo
    Perché confronti
    persona.nome,corr->persona.cognome
    ?
  • Re: [RISOLTO] Inserimento in lista ordinata alfabeticamente [C]

    Non mi ero accorto di quell'errore. Corretto, ma continua a darmi i problemi sopra descritti.
  • Re: [RISOLTO] Inserimento in lista ordinata alfabeticamente [C]

    Ora non ho tempo di controllare tutto, in ogni caso ti consiglio di implementare una funzione del tipo:

    int successivo(t_persona persona_1, t_persona persona_2)

    che ritorna 1 se cognome_1_nome_1 viene dopo cognome_2 nome_2 e 0 altrimenti. A questo punto l'inserimento di persone in ordine alfabetico sarà equivalente all'inserimento di numeri in ordine crescente.
  • Re: [RISOLTO] Inserimento in lista ordinata alfabeticamente [C]

    Devo implementare il tutto in un unica funzione. Ma non riesco a capire dove sbaglio.
    Ho visto questo esempio:
    
    void inserisciContatto(contatto_t**head,contatto_t *p){
      contatto_t *succ=*head,*prec=*head;
      while((succ!=NULL) && strcmp(p->cognome,succ->cognome)>=0){
        prec=succ;
        succ=succ->next;
      }
      if(succ==*head) {
          *head=p;
          p->next=succ;
          return;
      }
      if(succ==NULL){
        prec->next=p;
        p->next=NULL;
        return;
      }
      if(strcmp(p->cognome,succ->cognome)==0){
        while((succ!=NULL) && strcmp(p->nome,succ->nome)>=0){
          prec=succ;
          succ=succ->next;
        }
      }
      prec->next=p;
      p->next=succ;
    }
    Rigiarda un inserimento ordinato in una rubrica.
    Praticamente prima ordina per cognome, poi aggiorna i puntori e successivamente ordina per nome?
  • Re: [RISOLTO] Inserimento in lista ordinata alfabeticamente [C]

    Ma che legame c'è tra questo codice e quello precedente?

    In ogni caso visto che hai completamente ignorato il mio precedente post, cercherò di essere più chiaro... il problema è stabilire fra due dati anagrafici (cognome e nome) quale viene prima e quale dopo, oppure il problema è l'inserimento ordinato in lista?
    Se invece che persone avessimo dei semplici interi, saresti in grado di implementare una funzione che effettui l'inserimento ordinato?
  • Re: [RISOLTO] Inserimento in lista ordinata alfabeticamente [C]

    Nippolo ha scritto:


    Ma che legame c'è tra questo codice e quello precedente?

    In ogni caso visto che hai completamente ignorato il mio precedente post, cercherò di essere più chiaro... il problema è stabilire fra due dati anagrafici (cognome e nome) quale viene prima e quale dopo, oppure il problema è l'inserimento ordinato in lista?
    Se invece che persone avessimo dei semplici interi, saresti in grado di implementare una funzione che effettui l'inserimento ordinato?
    Non ho ignorato il tuo consiglio per partito preso, ma perchè ho la necessità di implementarlo in una sola funzione e non in più funzioni, almeno mi è parso di capire questo dal tuo consiglio.

    Per quanto riguarda gli interi ho implementato questo codice seguendo un tutorial su youtube:
    
    TList inserisci_elemento(TList lista,TInfo info)  //
    {
      /*INSERIMENTO ORDINATO NELLA LISTA
      Fase 1: Ricerca della posizone
      Fase 2: Allocazione dinamica
      Fase 3: Aggiornamento dei collegamenti
      */
      TList prec,temp,nuovo_nodo;
      prec=NULL;  //Inizializzo Lista vuota
      temp=lista;
      //Verificare che la lista non sia finita e che l'elemento che sto inserendo all'interno della lista
      //è maggiore del numero nel nodo che stiamo visitando allora deve scorrere al nodo successivo
    
      //---FASE 1--- Ricerca Posizione
      while(temp!=NULL && info.valore > temp->info.valore)
      {
        prec=temp;
        temp=temp->next;
      }
    
      //---Fase 2--- Allocazione dinamica della memoria
      nuovo_nodo=(TNode *)malloc(sizeof(TNode));
      assert(nuovo_nodo!=NULL);
      nuovo_nodo->info=info;
    
      //---Fase 3---Aggiornamento dei collegamenti
      if(prec==NULL)
      {
        nuovo_nodo->next=lista;
        lista=nuovo_nodo;
        return lista;
      }
      else
      {
        prec->next=nuovo_nodo;
        nuovo_nodo->next=temp;
        return lista;
      }
    
    Fatto ciò volevo fare un esercizio dove invece di interi avessi dei char con cognome e nome ed ordinarli. Ho implementato il codice così:
    t_lista inserimento_lista(t_lista lista,t_persona persona)
    {
      int ins=1;
      t_lista prec,corr,nuovo;
      prec=NULL;
      corr=lista;
      //---FASE 1--- Ricerca della Posizione
      while(corr!=NULL && (ins=strcmp(persona.cognome,corr->persona.cognome))>0)
      {
        prec=corr;
        corr=corr->next;
      }
      if(ins==0)
      {
        while(corr!=NULL && (strcmp(persona.nome,corr->persona.nome))>0)
        {
          prec=corr;
          corr=corr->next;
        }
      }
      //---FASE 2--- ->  Allocazione Dinamica della Memoria
      nuovo=(t_nodo *)malloc(sizeof(t_nodo));
      assert(nuovo!=NULL);
      nuovo->persona=persona;
      //---FASE 3--- -> Aggiornamento dei Collegamenti
      if(prec==NULL)
      {
        nuovo->next=lista;
        lista=nuovo;
        return lista;
      }
      else
      {
        prec->next=nuovo;
        nuovo->next=corr;
        return lista;
      }
    }
    Ho utilizzato una variabile "ins" per effettuare il confronto perchè non so per qual motivo non mi effettuava mai il controllo del "nome".
    Sorge solo un problema, ti faccio un esempio di output:


    Fi..o Cr...n
    Int... Gia..o
    Penn Mar...a
    ...
    ...
    Fi..o Ugo

    Ho utilizzato i puntini per privacy visto che ho usato nomi e cognomi di persone che conosco

    Come vedi capita che con qualche nome sbagli e li metta in posizione sbagliata. Come mai?
  • Re: [RISOLTO] Inserimento in lista ordinata alfabeticamente [C]

    Per quanto riguarda gli interi ho implementato questo codice seguendo un tutorial su youtube:
    ...
    Premesso che non so cosa rappresenti TInfo, info e valore, il codice mi sembra corretto.
    Come vedi capita che con qualche nome sbagli e li metta in posizione sbagliata. Come mai?
    Consideriamo di voler aggiungere Bianchi Mario alla seguente lista:

    Abete Luca
    Bianchi Aldo
    Rossi Andrea
    Rossi Giovanna
    Verdi Luisa
    Verdi Paolo

    Dopo il primo while corr punterà a Bianchi Aldo, mentre dopo il secondo while corr punterà a Verdi Paolo. Quindi Bianchi Mario sarà aggiunto tra Verdi Luisa e Verdi Paolo.
    Il problema è che in caso di stesso cognome poi vai a confrontare solo i nomi ignorando i cognomi.
    La soluzione consiste nel confrontare prima i cognomi e poi i nomi all'interno della stessa condizione.
  • Re: [RISOLTO] Inserimento in lista ordinata alfabeticamente [C]

    Nippolo ha scritto:


    Per quanto riguarda gli interi ho implementato questo codice seguendo un tutorial su youtube:
    ...
    Premesso che non so cosa rappresenti TInfo, info e valore, il codice mi sembra corretto.
    Come vedi capita che con qualche nome sbagli e li metta in posizione sbagliata. Come mai?
    Consideriamo di voler aggiungere Bianchi Mario alla seguente lista:

    Abete Luca
    Bianchi Aldo
    Rossi Andrea
    Rossi Giovanna
    Verdi Luisa
    Verdi Paolo

    Dopo il primo while corr punterà a Bianchi Aldo, mentre dopo il secondo while corr punterà a Verdi Paolo. Quindi Bianchi Mario sarà aggiunto tra Verdi Luisa e Verdi Paolo.
    Il problema è che in caso di stesso cognome poi vai a confrontare solo i nomi ignorando i cognomi.
    La soluzione consiste nel confrontare prima i cognomi e poi i nomi all'interno della stessa condizione.

    Accade esattamente ciò che hai scritto. La cosa strana è che però non capita con tutti i cognomi uguali. Alcuni li inserisce nel posto giusto altri no.
    Ma non capisco perchè dopo il secondo while punta Verdi Paolo invece che a Rossi Andrea
    Non dovrebbe scorrere sequenzialmente tutta la lista?
    Il problema è che non so come verificare la condizione di cognome e nome contemporaneamente perchè sbaglio in qualcosa e non funziona. Hai un esempio?

    Ti metto qui le strutture dati da me inizializzate:
    
    struct s_persona
    {
      char cognome[MAX];
      char nome[MAX];
    };
    typedef struct s_persona t_persona;
    
    struct s_nodo
    {
      t_persona persona;
      struct s_nodo *next;
    };
    typedef struct s_nodo t_nodo;
    typedef t_nodo *t_lista;
    
  • Re: [RISOLTO] Inserimento in lista ordinata alfabeticamente [C]

    Ma non capisco perchè dopo il secondo while punta Verdi Paolo invece che a Rossi Andrea
    Perché da quel momento in poi saranno considerati solo i nomi e
    Mario > Aldo
    Mario > Andrea
    Mario > Giovanna
    Mario > Luisa
    Mario < Paolo
    Il problema è che non so come verificare la condizione di cognome e nome contemporaneamente perchè sbaglio in qualcosa e non funziona. Hai un esempio?
    Quando persona1>persona2?
    Quando il cognome di persona1 viene dopo il cognome di persona2 oppure quando entrambi hanno lo stesso cognome, ma il nome di persona1 viene dopo il nome di persona2.
    Non ti resta che tradurre la suddetta frase in codice!
  • Re: [RISOLTO] Inserimento in lista ordinata alfabeticamente [C]

    Ok grazie mille! Ora ho le idee meno confuse. Vedo di riuscire a tradurre il tutto in codice, in caso ti romperò le scatole.
    Grazie ancora!!
  • Re: [RISOLTO] Inserimento in lista ordinata alfabeticamente [C]

    Buongiorno, spero di essere riuscito a trovare l'algoritmo giusto per ordinare per cognome e nome, metto di seguito il codice:
    
    t_lista inserimento_lista(t_lista lista,t_persona persona)
    {
      int ctrl_1=1;
      int ctrl_2=1;
      t_lista prec,corr,nuovo;
      prec=NULL;
      corr=lista;
      nuovo=(t_nodo *)malloc(sizeof(t_nodo));
      assert(nuovo!=NULL);
      while(corr!=NULL && (ctrl_1=strcmp(persona.cognome,corr->persona.cognome))>0)
      {
        prec=corr;
        corr=corr->next;
      }
      if(ctrl_1==0)
      {
        while(corr!=NULL && (ctrl_2=strcmp(persona.nome,corr->persona.nome))>0)
        {
          prec=corr;
          corr=corr->next;
        }
        if(ctrl_2<0)
        {
          prec->next=nuovo;
          nuovo->next=corr;
          return lista;
        }
      }
      else if(ctrl_1!=0)
      {
        if(prec==NULL)
        {
          nuovo->next=lista;
          lista=nuovo;
          return lista;
        }
        else
        {
          prec->next=nuovo;
          nuovo->next=corr;
          return lista;
        }
      }
    }
    Solo che adesso con la funzione stampa mi escono questi caratteri:
    
    Ói
    Ói
    êi
    êi
    Come mai mi da questo errore nella formattazione?
    Di seguito la funzione: STAMPA
    void stampa_lista(t_lista lista)
    {
      t_lista corr; //Variabile per scorrere la lista
      corr=lista;
      while(corr!=NULL)
      {
        printf("\n%s %s",corr->persona.cognome,corr->persona.nome);
        corr=corr->next;
      }
      return;
    }
  • Re: [RISOLTO] Inserimento in lista ordinata alfabeticamente [C]

    Ciao!

    Xavier25 ha scritto:


    ...spero di essere riuscito a trovare l'algoritmo giusto per ordinare...
    Come "spero"?! L'hai provato?

    In ogni caso non ho molta voglia di mettermi a controllare questo nuovo e ancora più macchinoso codice!
    Scusa hai il codice funzionante relativo all'inserimento ordinato in una lista di interi, l'unica cosa che devi fare è modificare la condizione del while secondo il consiglio che ti ho dato nel post precedente:

    Quando persona1>persona2?
    Quando il cognome di persona1 viene dopo il cognome di persona2 oppure quando entrambi hanno lo stesso cognome, ma il nome di persona1 viene dopo il nome di persona2.
    Non ti resta che tradurre la suddetta frase in codice!


    Si tratta di una semplice espressione logica... cosa non ti convince?

    P.S.
    Nella funzione stampa_lista non c'è bisogno della variabile corr, sai dirmi il perchè?
  • Re: [RISOLTO] Inserimento in lista ordinata alfabeticamente [C]

    Nippolo ha scritto:


    Ciao!

    Xavier25 ha scritto:


    ...spero di essere riuscito a trovare l'algoritmo giusto per ordinare...
    Come "spero"?! L'hai provato?
    Si l'ho provato, ma non posso sapere se è giusto in quanto, come dicevo nello scorso messaggio, purtroppo mi da un output video con caratteri strani e quindi non posso verificare se il codice è giusto.

    Nippolo ha scritto:


    In ogni caso non ho molta voglia di mettermi a controllare questo nuovo e ancora più macchinoso codice!
    Scusa hai il codice funzionante relativo all'inserimento ordinato in una lista di interi, l'unica cosa che devi fare è modificare la condizione del while secondo il consiglio che ti ho dato nel post precedente:
    Forse mi sono fatto troppi trip mentali ed è venuto fuori un codice troppo macchinoso.

    Nippolo ha scritto:


    P.S.
    Nella funzione stampa_lista non c'è bisogno della variabile corr, sai dirmi il perchè?
    Pensavo che la variabile "corr" fosse necessaria per scorrere la lista, provando ad utilizzare lista->next stampa all'infinito senza mai uscire dal while.

    EDIT:
    Avevo sbagliato: Non avevo scritto lista=lista->next. Quindi si è possibile non usare la variabile "corr" perchè la variabile "lista" mi punta alla testa della lista.
    Continua però a stamparmi caratteri strani, quindi non posso sapere se l'ordine in lista è giusto.
  • Re: [RISOLTO] Inserimento in lista ordinata alfabeticamente [C]

    Ok, ma non vuoi proprio provarci a tradurre quella frase in codice?
    Magari il problema sono le stringhe, quindi facciamo un altro esempio... hai delle coppie di numeri che rappresentano mese e anno, sei in grado di ordinare le date? Mi spiego meglio, ipotizziamo di avere la seguente struct
    struct data
    {
        int mese;
        int anno;
    }
    Sei in grado di completare la seguente funzione?
    void fun(data data1, data data2)
    {
        if(...)
        {
            printf("data1 viene dopo data2!");
        }
    }
    Pensavo che la variabile "corr" fosse necessaria per scorrere la lista...
    Perchè la ritenevi necessaria?
    Quindi si è possibile non usare la variabile "corr"...
    Ti sei fatto un'idea del perchè?
Devi accedere o registrarti per scrivere nel forum
41 risposte