Visualizzazione dei risultati da 1 a 8 su 8

Hybrid View

  1. #1
    Utente di HTML.it L'avatar di Scara95
    Registrato dal
    Jul 2009
    residenza
    Zimella (VR)
    Messaggi
    2,589
    Ho commentato il codice spiegando gli errori e correggendolo.
    Ci sono ancora alcuni errori logici, ho scritto dove sono.

    Edit: al momento non libera tutta la memoria. E' un errore anche questo.
    codice:
    /*
    * Dizionario realizzato mediante struttura circolare doppiamente collegata.
    * 
    *       classe StrutturaCollegata implementa Dizionario:
    *        dati:                                                                  S(n) = @(n)
    *             una collezione di n record contenenti ciascuno una quadrupla
    *             (prev, elem, chiave, next), dove prev e next sono puntatori
    *             al precedente e successivo record della collezione.
    *             Manteniamo inoltre un puntatore list che contiene l'indirizzo
    *             di un record se la collezione non è vuota e null altrimenti.
    *        operazioni:
    *             insert(elem e, chiave k)                                          T(n)=O(1)
    *                         viene creato un record p con elemento e e chiave k.
    *                         Se list=null, si effettua p->next=p, p->prev=p e
    *                         list=p . Altrimenti si collega il record p tra
    *                         list e list->next effettuando p->next=list->next,
    *                         list->next->prev=p, p->prev=list e list->next=p.
    *             delete(chiave k)                                                  T(n)=O(n)
    *                         si trova il record P con chiave k come nella
    *                         search; poi si effettua p->prev->next=p->next e
    *                         p->next->prev=p->prev; infine viene distrutto
    *                         il record p.
    *             search(chiave k)-> elem                                           T(n)=O(n)
    *                         se list=null si restituisce null. Altrimenti si
    *                         scandisce la struttura saltando di record in
    *                         record con p=p->next fino a quando non diventa
    *                         p=list, verificando se qualche p ha chiave k.
    *                         In caso positivo si restituisce l'elemento
    *                         trovato e null altrimenti.
    */
    
    /*stdio non ti è necessaria se non usi funzioni di IO*/
    #include <stdio.h>
    
    /*Usi malloc, strcmp e strcpy, queste sono necessarie*/
    #include <string.h>
    #include <stdlib.h>
    
    /*Devi sempre allocare spazio per i caratteri.
      Io qui ho supposto che una chiave sia lunga al massimo 50 caratteri,
      se vuoi puoi ridurli o aumentarli o utilizzare l'allocazione dinamica*/
    typedef char STRINGA[50];
    
    typedef struct dato {
            struct dato* prec;
            int elemento;
            STRINGA chiave;
            struct dato* succ;
    } DATO;
    
    /*Stiamo lavorando in C, non esistono i metodi*/
    typedef DATO* DIZIONARIO; 
    
    void creadiz(DIZIONARIO *diz)
    {
         *diz = NULL;
    }
    
    void inserisci(DIZIONARIO *d, int el, STRINGA ch)
    {
         /*ti serve un puntatore, non la struttura*/
         DATO *p;
         p = malloc(sizeof(DATO));
         
         p->elemento = el;
        /*le strinche si copiano con strcpy in C,
          studia da un libro il perché, troppo lungo*/
         strcpy(p->chiave, ch);
         
         if ((*d) == NULL) {
                  p->prec = p;
                  p->succ = p;
                  (*d) = p;
         } else {
                p->succ = (*d)->succ;
                (*d)->succ->prec = p;
                p->prec = (*d);
                (*d)->succ = p;
         }
    }
    
    /*la logica è scorretta se il dizionario contiene solo 1 elemento
      o se cancella il primo elemento inserito*/
    int cancella(DIZIONARIO* d, STRINGA ch)
    {
         /*devi dichiarare che cos'è p*/
         DATO *p = *d;
         /*Non puoi ritornare NULL perché di tipo int.
           Potresti ritornare (int)NULL ma questo è equivalente a 0.
           In ogni caso una cancellazione va sempre a buon fine,
           percui non ti servirebbe un valore di ritorno*/
         if (p == NULL) {
                  return 0;
         } else {
                /*do {} while(); altrimenti viene subito interrotto*/
                do {
                      /*le strinche si comparano con strcmp in C,
                        studia da un libro il perché, troppo lungo*/
                      if( strcmp(p->chiave, ch) == 0 ) {
                          p->prec->succ = p->succ;
                          p->succ->prec = p->prec;                      
                          free(p);
                          return 1;
                      } else {
                             p = p->succ;
                      }
                } while ( p != (*d) );
         }
         return 0;
    }
    
    /*il ritornare uno 0 non è corretto se elemento può valere 0*/
    int cerca(DIZIONARIO* d, STRINGA ch)
    {
         /*devi dichiarare che cos'è p*/
         DATO *p = *d;
         /*Non puoi ritornare NULL perché di tipo int.
           Potresti ritornare (int)NULL ma questo è equivalente a 0.*/ 
         if (p == NULL) {
                  return 0;
         } else {
                /*do {} while(); altrimenti viene subito interrotto*/
                do {
                      /*le strinche si comparano con strcmp in C,
                        studia da un libro il perché, troppo lungo*/
                      if( strcmp(p->chiave, ch) == 0 ) {
                          return p->elemento;
                      } else {
                             p = p->succ;
                      }
                } while ( p != (*d) );
         }
         
         return 0;
    }
    
    /* test main. Non presenta i casi in cui cancella è sbagliato. */
    int main(void) {
        DIZIONARIO d;
        creadiz(&d);
        printf("pere: %d\n", cerca(&d, "pere")); 
        inserisci(&d, 5, "mele");
        inserisci(&d, 3, "pere");
        printf("pere: %d\n", cerca(&d, "pere"));
        cancella(&d, "pera");
        printf("pere: %d\n", cerca(&d, "pere"));
        cancella(&d, "pere");
        printf("pere: %d\n", cerca(&d, "pere"));
        return 0;
    }
    "Quid enim est, quod contra vim sine vi fieri possit?" - Cicerone, Ad Familiares

  2. #2
    Innanzi tutto grazie mille per la risposta ...
    Visto che mi hai praticamente corretto tutto volevo chiederti alcune delucidazioni se non ti dispiace.. anche per capire meglio tutto!
    A parte le inclusioni (ok stdlib, string mi hai illuminato ero convinto si potessero copiare le stringhe tranquillamente, ri-grazie)
    coomunque ricapitolando:

    1) Ho visto che mi hai corretto la definizione di STRINGA ... ma se io uso
    codice:
    typedefchar * STRINGA;
    
    non dovrebbe in automatico creare un array di caratteri della lunghezza della stringa che di volta in volta vado a passare?

    2) Hai ragione non ci avevo pensato che idiota. Niente metodi in C!!! Quindi mi tocca passare ogni volta l'elemento su cui operare alle funzioni... e ovviamente trasformare tutto in puntatori (fin qui ci sono)
    Ma così facendo dove lo metto il puntatore "list" che dovrebbe puntare al primo record se esistente o a null altrimenti..

    3) Perchè la logica è scorretta se vi è solo un elemento? o se si cancella il primo elemento inserito? (sempre per via della sparizione del puntatore "list" o non c'entra? )

    4) ok i ritorni li sistemavo dopo grazie comunque!

    5) Un ultima domanda, se all'interno delle funzioni invece di creare un altro "Dato *p" potrei utilizzare direttamente il "*d" che passo come argomento alla funzione o questo andrebbe a creare casini???

  3. #3
    Utente di HTML.it L'avatar di Scara95
    Registrato dal
    Jul 2009
    residenza
    Zimella (VR)
    Messaggi
    2,589
    Quote Originariamente inviata da deimos88 Visualizza il messaggio
    1) Ho visto che mi hai corretto la definizione di STRINGA ... ma se io uso
    codice:
    typedefchar * STRINGA;
    
    non dovrebbe in automatico creare un array di caratteri della lunghezza della stringa che di volta in volta vado a passare?
    Forse intendi
    codice:
    typedef char *STRINGA;
    In ogni caso no: char * è solo un puntatore a carattere che contiene un indirizzo di memoria, questa memoria devi allocarla tu. Il metodo più semplice è usare un array al posto di un puntatore, il metodo più difficile è quello di aggiungere un po' di funzioni che ti gestiscano la memoria e allacorla dinamicamente.
    Quote Originariamente inviata da deimos88 Visualizza il messaggio
    2) Hai ragione non ci avevo pensato che idiota. Niente metodi in C!!! Quindi mi tocca passare ogni volta l'elemento su cui operare alle funzioni... e ovviamente trasformare tutto in puntatori (fin qui ci sono)
    Ma così facendo dove lo metto il puntatore "list" che dovrebbe puntare al primo record se esistente o a null altrimenti..
    Puoi creare una struttura e che non è altro la parte di non-metodi che utilizzeresti in un linguaggio ad oggetti, tuttavia nel tuo codice hai un solo elemento per cui il creare una struttura con un solo elemento è (per dire) un surplus, quindi ti basta un puntatore all'elemento.

    Quote Originariamente inviata da deimos88 Visualizza il messaggio
    3) Perchè la logica è scorretta se vi è solo un elemento? o se si cancella il primo elemento inserito? (sempre per via della sparizione del puntatore "list" o non c'entra? )
    Perché l'elemento della lista da cui tu accedi agli altri è sempre il primo che hai inserito, quindi se cancelli il primo elemento inserito non sarai più in grado di accedere agli altri.
    Perché se la lista ha un solo elemento e lo cancelli la "testa" della lista non sarà impostata a NULL.

    Quote Originariamente inviata da deimos88 Visualizza il messaggio
    4) ok i ritorni li sistemavo dopo grazie comunque!
    Ti avrebbero dato errore o warning in compilazione.

    Quote Originariamente inviata da deimos88 Visualizza il messaggio
    5) Un ultima domanda, se all'interno delle funzioni invece di creare un altro "Dato *p" potrei utilizzare direttamente il "*d" che passo come argomento alla funzione o questo andrebbe a creare casini???
    Sì e no, cerca di capire da solo il perché
    "Quid enim est, quod contra vim sine vi fieri possit?" - Cicerone, Ad Familiares

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.