Inserimento in lista e sottolista

di il
19 risposte

Inserimento in lista e sottolista

Salve a tutti ragazzi, sto cercando di fare un programma che mi inserisce degli interi in una lista e nell'intero 5 crea una sottolista e inserisce dei caratteri, il tutto fatto con dei cicli for che poi verranno sostituiti dall'inserimento manuale (quando riuscirò a farlo funzionare).
Il programma inserisce gli interi da 0 a 9 con inserimento in testa, poi crea una sottolista nell'elemento 5 e inserisce dei caratteri. Premendo 2, si fa la stampa delle liste. Il problema è che non mi stampa correttamente la sottolista e non riesco a capire dove sbaglio.
Ho messo dei printf qua e la per capire se l'inserimento avviene correttamente e sembra proprio di si. Il problema credo sia nella funzione stampa, ma non riesco a correggerlo.

Ecco il codice....grazie a tutti in anticipo

#include <stdio.h>
#include <stdlib.h>

/***** S T R U T T U R E ******/
struct sotto_nodo
{
    char carattere;
    struct sotto_nodo *nextPtr1;
};

struct nodo
{
    int intero;
    struct nodo *nextPtr;               //puntatore al nodo successivo
    struct sotto_nodo *sottonodoPtr;   //puntatore al tipo struct sotto_nodo di nome sottonodoPtr

};

/****** T Y P E D E F ******/

typedef struct sotto_nodo SottoNodo;
typedef struct nodo Nodo;

typedef SottoNodo *SottoNodoPtr;
typedef Nodo *NodoPtr;

/****** P R O T O T I P I    D I     F U N Z IO N E ******/

void menu();
NodoPtr crea_lista(int elemento1);
void inserisci_lista (NodoPtr *head, int elementi);
SottoNodoPtr trova (NodoPtr head, int elemento);
void inserisci_sottolista (SottoNodoPtr *head1, char caratteri);
void stampa(NodoPtr testalistaPtr);

/****** M A I N ******/

int main (void)
{
    NodoPtr testaPtr = NULL;
    SottoNodoPtr testaPtr1 = NULL;

    menu();
    int scelta;
    do {

        printf("Fai una scelta: ");
        fflush(stdin);
        scanf("%d", &scelta);
        switch (scelta)
        {
            case 1:
                {
                int i;
                char j;
                int elem1 = 0 ;

                testaPtr = crea_lista(elem1);
                for (i = 1; i < 10;  i++)
                {
                    inserisci_lista(&testaPtr, i);
                    printf("inserito %d in lista principale\n", testaPtr->intero);
                }

                testaPtr1 = trova(testaPtr, 5);
                printf("\ntrovato l'elemento cercato\n\n");

                for (j = 'a' ; j < 'l'; j++)
                {

                    inserisci_sottolista(&testaPtr1, j);
                    printf("inserito %c in lista secondaria\n", testaPtr1->carattere);
                }
            }
            break;

            case 2:
                stampa(testaPtr);
            break;
        }
    }
    while (scelta != 3);
}


/****** I M P L E M E N T A Z I O N E   F U N Z I O N I ******/


void menu()
{
    printf("1. Inserire elementi nella lista principale e nella sottolista\n");
    printf("2. Stampare elementi\n");
    printf("3. Termina programma\n");
};

NodoPtr crea_lista (int elemento1)
{
NodoPtr headPtr = malloc(sizeof(Nodo));

headPtr->intero = elemento1;
headPtr->nextPtr = NULL;
headPtr->sottonodoPtr = NULL;

return headPtr;
};

void inserisci_lista (NodoPtr *head, int elementi)
{
    NodoPtr newPtr = malloc(sizeof(Nodo));
    newPtr->intero=elementi;
    newPtr->nextPtr = *head;
    *head = newPtr;
};

SottoNodoPtr trova (NodoPtr head, int elemento)
{
    while (head->intero != elemento && head != NULL)
    {
        head = head->nextPtr;
    }
    if (head->intero == elemento)
        return head->sottonodoPtr;
    else
        return NULL;
};

void inserisci_sottolista (SottoNodoPtr *head1, char caratteri)
{
   SottoNodoPtr newPtr = malloc(sizeof(SottoNodo));
   newPtr->carattere = caratteri;
   newPtr->nextPtr1 = *head1;
   *head1 = newPtr;
};

void stampa(NodoPtr testalista)
{
    printf("head -> ");
    NodoPtr copia_testalista = testalista;
    while (testalista != NULL)
    {
        printf("%d -> ", testalista->intero);
        testalista = testalista->nextPtr;
    }
    printf("NULL\n");

    SottoNodoPtr SubPtr = copia_testalista->sottonodoPtr;

    while (copia_testalista != NULL)
    {
    printf("headsub -> (%d) -> ", copia_testalista->intero);
    while (SubPtr != NULL)
    {
        printf("%d -> ", SubPtr->carattere);
        SubPtr = SubPtr->nextPtr1;
    }
    printf("NULL\n");
    copia_testalista = copia_testalista->nextPtr;
    }
};



19 Risposte

  • Re: Inserimento in lista e sottolista

    Ciao ho trovato alcuni problemi nel tuo codice
    struct nodo
    {
        int intero;
        struct nodo *nextPtr;               //puntatore al nodo successivo
        struct sotto_nodo *sottonodoPtr;   //puntatore al tipo struct sotto_nodo di nome sottonodoPtr
    
    };
    uno di questi è quanto vale il puntatore a sottolista?
    se fai riferimento solo alla funzione crea_lista
    esso varrà sempre NULL
    void inserisci_lista (NodoPtr *head, int elementi)
    {
        NodoPtr newPtr = malloc(sizeof(Nodo));
        newPtr->intero=elementi;
        newPtr->nextPtr = *head;
        *head = newPtr;
    };
    nella struttura lo definisci ma non lo consideri nella funzione sottolista.
    quando chiami la funzione inserisci_sottolista?
    nella traccia parli del elemento 5 che dava origine alla sottolista
    ma non c'è nessun confronto con questo valore.
  • Re: Inserimento in lista e sottolista

    Per quanto riguarda l'elemento 5, esso viene inserito nell'argomento della funzione "trova" che restituisce un puntatore al nodo che contiene 5.
    Questo puntatore viene poi dato come argomento alla funzione inserisci_sottolista che si trova nel secondo ciclo for, in modo tale da inserire i caratteri nella sottolista di 5
  • Re: Inserimento in lista e sottolista

    
                case 1:
                    {
                    int i;
                    char j;
                    int elem1 = 0 ;
    
                    testaPtr = crea_lista(elem1);
                    for (i = 1; i < 10;  i++)
                    {
                        inserisci_lista(&testaPtr, i);
                        printf("inserito %d in lista principale\n", testaPtr->intero);
                    }
    // questa parte deve andare all' interno del ciclo di i
                    testaPtr1 = trova(testaPtr, 5); 
                    printf("\ntrovato l'elemento cercato\n\n");
    
                    for (j = 'a' ; j < 'l'; j++)
                    {
    
                        inserisci_sottolista(&testaPtr1, j);
                        printf("inserito %c in lista secondaria\n", testaPtr1->carattere);
                    }
    // fine parte che deve andare all' interno del ciclo i                
                }
    inoltre
    
                    testaPtr1 = trova(testaPtr, 5); 
                    printf("\ntrovato l'elemento cercato\n\n");
    
                    for (j = 'a' ; j < 'l'; j++)
                    {
    
                        inserisci_sottolista(&testaPtr1, j);
                        printf("inserito %c in lista secondaria\n", testaPtr1->carattere);
                    }
                    
    ti conviene cambiarla in :
    
    if (i==5)
      {
                    testaPtr1 = trova(testaPtr, i); 
                    printf("\ntrovato l'elemento cercato\n\n");
    
                    for (j = 'a' ; j < 'l'; j++)
                    {
    
                        inserisci_sottolista(&testaPtr1, j);
                        printf("inserito %c in lista secondaria\n", testaPtr1->carattere);
                    } 
     } 
     
    la modifica ti conviene farla perchè cosi la parte viene eseguita soltanto una volta
    adesso apporta questa correzione più la gestione dei puntatori alla lista secondaria se ben ricordo funzione inserisci_lista
  • Re: Inserimento in lista e sottolista

    Innanzitutto grazie per le risposte, ho fatto le modifiche che mi hai elencato, però ancora non ho capito come risolvere il fatto che non mi stampa la sottolista.
  • Re: Inserimento in lista e sottolista

    Posta il listato con le modifiche fatte cosi vediamo che altro resta da aggiustare
    hai modificato il puntatore del elemento 5 affinche punti alla sottolista?
    scusami ma perchè in fase di stampa non fai come hai fatto in inserisci_lista?
    basta che al posto di scrivere i dati li prelevi e li stampi.
  • Re: Inserimento in lista e sottolista

    Ecco il codice, ho risolto il problema della stampa ma solo se chiamo la funzione stampa dentro il case 1, se faccio stampa dal case 2 me li stampa sbagliati, suppongo sia dovuto al fatto che la variabile è locale dentro il case 1, quindi devo fare in modo che funzioni anche dal case 2:

    Comunque questo è il codice attuale se provi a compilarlo puoi vedere tu stesso il problema :
    
    #include <stdio.h>
    #include <stdlib.h>
    
    /***** S T R U T T U R E ******/
    struct sotto_nodo
    {
        char carattere;
        struct sotto_nodo *nextPtr1;
    };
    
    struct nodo
    {
        int intero;
        struct nodo *nextPtr;               //puntatore al nodo successivo
        struct sotto_nodo *sottonodoPtr;   //puntatore al tipo struct sotto_nodo di nome sottonodoPtr
    
    };
    
    /****** T Y P E D E F ******/
    
    typedef struct sotto_nodo SottoNodo;
    typedef struct nodo Nodo;
    
    typedef SottoNodo *SottoNodoPtr;
    typedef Nodo *NodoPtr;
    
    /****** P R O T O T I P I    D I     F U N Z IO N E ******/
    
    void menu();
    NodoPtr crea_lista(int elemento1);
    void inserisci_lista (NodoPtr *head, int elementi);
    SottoNodoPtr trova (NodoPtr head, int elemento);
    void inserisci_sottolista (SottoNodoPtr *head1, char caratteri);
    void stampa(NodoPtr testalistaPtr);
    
    
    /****** M A I N ******/
    
    int main (void)
    {
        NodoPtr testaPtr = NULL;
    
    
    
        menu();
        int scelta;
        do {
    
            printf("Fai una scelta: ");
            fflush(stdin);
            scanf("%d", &scelta);
            switch (scelta)
            {
                case 1:
                    {
                    int i;
                    char j;
                    int elem1 = 0 ;
    
                    testaPtr = crea_lista(elem1);
                    for (i = 1; i < 10;  i++)
                    {
                        inserisci_lista(&testaPtr, i);
                        printf("inserito %d in lista principale\n", testaPtr->intero);
    
                    if (i==5){
                        (testaPtr->sottonodoPtr) = trova(testaPtr, 5);
                        printf("\ntrovato l'elemento cercato\n\n");
    
                            for (j = 'a' ; j < 'l'; j++)
                            {
    
                                inserisci_sottolista(&(testaPtr->sottonodoPtr), j);
                                printf("inserito %c in lista secondaria\n", testaPtr->sottonodoPtr->carattere);
                            }
                        }
                    }
                }
    
                stampa(testaPtr);
                break;
    
                case 2:
                stampa(testaPtr);
    
                break;
            }
        }
        while (scelta != 3);
    system("pause");
    return 0;
    }
    
    
    /****** I M P L E M E N T A Z I O N E   F U N Z I O N I ******/
    
    
    void menu()
    {
        printf("1. Inserire elementi nella lista principale e nella sottolista\n");
        printf("2. Stampare elementi\n");
        printf("3. Termina programma\n");
    };
    
    NodoPtr crea_lista (int elemento1)
    {
    NodoPtr headPtr = malloc(sizeof(Nodo));
    
    headPtr->intero = elemento1;
    headPtr->nextPtr = NULL;
    headPtr->sottonodoPtr = NULL;
    
    return headPtr;
    };
    
    void inserisci_lista (NodoPtr *head, int elementi)
    {
        NodoPtr newPtr = malloc(sizeof(Nodo));
        newPtr->intero=elementi;
        newPtr->nextPtr = *head;
        *head = newPtr;
    };
    
    SottoNodoPtr trova (NodoPtr head, int elemento)
    {
        while (head->intero != elemento && head != NULL)
        {
            head = head->nextPtr;
        }
        if (head->intero == elemento)
            return head->sottonodoPtr;
        else
            return NULL;
    };
    
    void inserisci_sottolista (SottoNodoPtr *head1, char caratteri)
    {
       SottoNodoPtr newPtr = malloc(sizeof(SottoNodo));
       newPtr->carattere = caratteri;
       newPtr->nextPtr1 = *head1;
       *head1 = newPtr;
    };
    
    void stampa(NodoPtr testalista)
    {
        printf("head -> ");
        NodoPtr copia_testa = testalista;
        while (testalista != NULL)
        {
            printf("%d -> ", testalista->intero);
            testalista = testalista->nextPtr;
        }
        printf("NULL\n");
    
    
        while (copia_testa != NULL)
        {
        printf("headsub -> (%d) -> ", copia_testa->intero);
    
        while (copia_testa->sottonodoPtr != NULL)
        {
            printf("%c -> ", copia_testa->sottonodoPtr->carattere);
            copia_testa->sottonodoPtr = copia_testa->sottonodoPtr->nextPtr1;
        }
        printf("NULL\n");
        copia_testa = copia_testa->nextPtr;
        }
    };
    
    
    
  • Re: Inserimento in lista e sottolista

    Comunque non ho capito cosa intendi per sistemare il puntatore dell'elemento 5 affinchè punti alla sottolista
  • Re: Inserimento in lista e sottolista

    Così funziona, quello che ho fatto è stato togliere il puntatore testaPtr1 che era un puntatore alla struttura sottonodo e al posto di testaPtr1 ho
    scritto testaPtr->sottonodoPtr e così funziona.
    Probabilmente in quel modo creavo un nuovo puntatore completamente staccato dalla struttura principale.
    Diciamo che sono andato per tentativi, quindi non ho capito benissimo come ho risolto, ma vorrei capirlo

    
    #include <stdio.h>
    #include <stdlib.h>
    
    /***** S T R U T T U R E ******/
    struct sotto_nodo
    {
        char carattere;
        struct sotto_nodo *nextPtr1;
    };
    
    struct nodo
    {
        int intero;
        struct nodo *nextPtr;               //puntatore al nodo successivo
        struct sotto_nodo *sottonodoPtr;   //puntatore al tipo struct sotto_nodo di nome sottonodoPtr
    
    };
    
    /****** T Y P E D E F ******/
    
    typedef struct sotto_nodo SottoNodo;
    typedef struct nodo Nodo;
    
    typedef SottoNodo *SottoNodoPtr;
    typedef Nodo *NodoPtr;
    
    /****** P R O T O T I P I    D I     F U N Z IO N E ******/
    
    void menu();
    NodoPtr crea_lista(int elemento1);
    void inserisci_lista (NodoPtr *head, int elementi);
    SottoNodoPtr trova (NodoPtr head, int elemento);
    void inserisci_sottolista (SottoNodoPtr *head1, char caratteri);
    void stampa(NodoPtr testalistaPtr);
    
    
    /****** M A I N ******/
    
    int main (void)
    {
        NodoPtr testaPtr = NULL;
    
    
    
        menu();
        int scelta;
        do {
    
            printf("Fai una scelta: ");
            fflush(stdin);
            scanf("%d", &scelta);
            switch (scelta)
            {
                case 1:
                    {
                    int i;
                    char j;
                    int elem1 = 0 ;
    
                    testaPtr = crea_lista(elem1);
                    for (i = 1; i < 10;  i++)
                    {
                        inserisci_lista(&testaPtr, i);
                        printf("inserito %d in lista principale\n", testaPtr->intero);
    
                    if (i==5){
                        (testaPtr->sottonodoPtr) = trova(testaPtr, 5);
                        printf("\ntrovato l'elemento cercato\n\n");
    
                            for (j = 'a' ; j < 'l'; j++)
                            {
    
                                inserisci_sottolista(&(testaPtr->sottonodoPtr), j);
                                printf("inserito %c in lista secondaria\n", testaPtr->sottonodoPtr->carattere);
                            }
                        }
                    }
                }
    
    
                break;
    
                case 2:
                stampa(testaPtr);
    
                break;
            }
        }
        while (scelta != 3);
    system("pause");
    return 0;
    }
    
    
    /****** I M P L E M E N T A Z I O N E   F U N Z I O N I ******/
    
    
    void menu()
    {
        printf("1. Inserire elementi nella lista principale e nella sottolista\n");
        printf("2. Stampare elementi\n");
        printf("3. Termina programma\n");
    };
    
    NodoPtr crea_lista (int elemento1)
    {
    NodoPtr headPtr = malloc(sizeof(Nodo));
    
    headPtr->intero = elemento1;
    headPtr->nextPtr = NULL;
    headPtr->sottonodoPtr = NULL;
    
    return headPtr;
    };
    
    void inserisci_lista (NodoPtr *head, int elementi)
    {
        NodoPtr newPtr = malloc(sizeof(Nodo));
        newPtr->intero=elementi;
        newPtr->nextPtr = *head;
        *head = newPtr;
    };
    
    SottoNodoPtr trova (NodoPtr head, int elemento)
    {
        while (head->intero != elemento && head != NULL)
        {
            head = head->nextPtr;
        }
        if (head->intero == elemento)
            return head->sottonodoPtr;
        else
            return NULL;
    };
    
    void inserisci_sottolista (SottoNodoPtr *head1, char caratteri)
    {
       SottoNodoPtr newPtr = malloc(sizeof(SottoNodo));
       newPtr->carattere = caratteri;
       newPtr->nextPtr1 = *head1;
       *head1 = newPtr;
    };
    
    void stampa(NodoPtr testalista)
    {
        printf("head -> ");
        NodoPtr copia_testa = testalista;
        while (testalista != NULL)
        {
            printf("%d -> ", testalista->intero);
            testalista = testalista->nextPtr;
        }
        printf("NULL\n");
    
    
        while (copia_testa != NULL)
        {
        printf("headsub -> (%d) -> ", copia_testa->intero);
    
        while (copia_testa->sottonodoPtr != NULL)
        {
            printf("%c -> ", copia_testa->sottonodoPtr->carattere);
            copia_testa->sottonodoPtr = copia_testa->sottonodoPtr->nextPtr1;
        }
        printf("NULL\n");
        copia_testa = copia_testa->nextPtr;
        }
    };
    
  • Re: Inserimento in lista e sottolista

    Ti rispondo piu tardi
  • Re: Inserimento in lista e sottolista

    Scusa il tempo di attesa molto lungo
    il problema era che quei puntatori che poi hai levato erano definiti a nullptr
    quando facevi il ciclo esso terminava subito perche avevi la condizione != NULL
    adesso che il programma funziona lo devi terminare aggiungendo alla fine il liberamento delle aree allocate.
    che se ben ricordo si effettua con l'istruzione free.
  • Re: Inserimento in lista e sottolista

    Perfetto, grazie tante. Ho riscontrato un altro problema. Se inserisco system("cls") per pulire il prompt dopo la visualizzazione del menù, il programma termina quando eseguo la stampa, quindi non quando viene eseguito il system("cls") ma verso la fine del programma, dandomi: "si è verificato un errore.... "(la classica schermata di windows che appare quando si blocca un programma) , tutto questo senza il system("cls") non accade. Non è un problema di inclusione di librerie perché il comando funziona perfettamente.
  • Re: Inserimento in lista e sottolista

    Altro dubbio è quello di liberare la memoria. Per liberare la memoria precedentemente allocata, lo devo fare alla fine del main, quando tutto il programma è terminato, giusto? Perché se in questo caso lo facessi all'interno della funzione "crea_lista" o all'interno di qualunque altra dove l'importanza è mantenere il puntatore quello che accadrebbe è che perderei i puntatori e quindi la lista. Cosa diversa invece è quando implemento una funzione "cancella_lista" (che in questo caso non ho fatto) dove non mi serve più il puntatore all'elemento da cancellare dalla lista.
  • Re: Inserimento in lista e sottolista

    Allora iniziamo dal punto dove devi liberare la memoria.
    la memoria la devi liberare quando esegui la chiusura del programma cioè prima dell' istruzione return 0;
    io al posto tuo il menù lo gestirei così:
    
    int scelta=0;
    while (scelta<1 || scelta>3
    {
    menu();
            printf("Fai una scelta: ");
            fflush(stdin);
            scanf("%d", &scelta);
            switch (scelta)
            {
            cas1 1:......
            case 2:{ 
            if (testaPtr==NULL) { printf("errore lista non caricata\n"); break; } 
            // questo confronto è importante perchè l'operatore potrebbe digitare 2 all'inizio cioè prima che la lista sia stata inserita!
           stampa(testaPtr);
    
                break;
                }
            default:{ break;}
            }
    }
    // libero memoria
    // termino programma
    
    se c'è qualche altra cosa che non capisci chiedi pure.
  • Re: Inserimento in lista e sottolista

    Per la gestione del menu' ho usato un costrutto while invece del tuo do perchè prima verifico e poi eseguo.
    in casi come questo il ciclo while e da preferire.
    per il motivo vedi la teoria che stà sul libro che stai usando per studiare.
Devi accedere o registrarti per scrivere nel forum
19 risposte