URGENTE problema con liste allocate dinamicamente (liste dinamiche)

di il
14 risposte

URGENTE problema con liste allocate dinamicamente (liste dinamiche)

Ciao a tutti sono un nuovo utente, frequento ingegneria informatica ed ho bisogno di un aiuto con le liste dinamiche. Sto facendo qualche semplice programma per esercitarmi in vista dell'esame, ma ho un grosso problema sin da subito nel realizzare un sottoprogramma che permette all'utente di creare una lista lunga a piacimento, utilizzando un intero negativo per terminarla. il tutto è inserito in un programma più ampio che permette poi di contare il numero di elementi della stessa lista dinamica appena creata.

Vi posto il mio programma di seguito nella speranza che qualcuno riesca ad aiutarmi.
P.S. Il problema potrebbe essere anche nel sottoprogramma che conta gli elementi perchè non l'ho testato, ma ne dubito fortemente.

#include <stdio.h>
#include <stdlib.h>
typedef struct ElemLista
{
    int Dato;
    struct ElemLista *Prossimo;
} TipoLista;
void CreaRiempiLista(TipoLista *Testa)
{
    int N;
    TipoLista *PuntProvv;
    scanf("%d", &N);
    if (N < 0)
    {
        Testa = NULL;
    }
    else
    {
        PuntProvv = malloc(sizeof(TipoLista));
        PuntProvv->Dato = N;
        PuntProvv->Prossimo = NULL;
        Testa = PuntProvv;
        while (N > 0)
        {
            scanf("%d", &N);
            if (N < 0)
            {
                return;
            }
            else
            {
                PuntProvv->Prossimo = malloc(sizeof(TipoLista));
                PuntProvv = PuntProvv->Prossimo;
                PuntProvv->Dato = N;
                PuntProvv->Prossimo = NULL;
            }
        }
    }
}
void N_TipoLista(TipoLista *Testa)
{
    TipoLista *PuntProvv;
    int Contatore = 0;
    PuntProvv = Testa;
    while (PuntProvv != NULL)
    {
        Contatore++;
        PuntProvv = PuntProvv->Prossimo;
    }
    printf("la lista contiene %d oggetti", Contatore);
    return;
}
void main()
{
    TipoLista *Testa;
    printf("Inserisci gli elementi della lista separati da un invio\n\n");
    CreaRiempiLista(Testa);
    N_TipoLista(Testa);
}

14 Risposte

  • Re: URGENTE problema con liste allocate dinamicamente (liste dinamiche)

    Ciao, secondo te quale dovrebbe essere l'output del seguente programma?
    #include <stdio.h>
    
    void fun(int n)
    {
        n = n * 2;
    }
    
    int main()
    {
        int a = 5;
        fun(a);
        printf("%d", a);
    }
  • Re: URGENTE problema con liste allocate dinamicamente (liste dinamiche)

    Se non mi sbaglio c'è un errore perchè il sottoprogramma è void, ed i sotto programmi non modificano le variabili che gli vengono assegnate, a meno che non siano array o puntatori (che sono la stessa cosa praticamente). Detto questo l'output dovrebbe essere: 5. Non capisco comunque in che modo possa aiutarmi a risolvere il mio problema.
  • Re: URGENTE problema con liste allocate dinamicamente (liste dinamiche)

    Ma sinceramente non capisco cosa c'entri col mio programma. Qualcuno potrebbe darmi una mano?
  • Re: URGENTE problema con liste allocate dinamicamente (liste dinamiche)

    Il fatto che non lo capisci E' ESATTAMENTE il tuo problema!

    Ti si sta' dando una mano: sei o no un (futuro) INGEGNERE?

    Quindi OSSERVA BENE il codice che ti e' stato proposto, ANALIZZA ogni singolo statement e ASSICURATI di capire che cosa fa e PERCHE'.

    LASCIA PERDERE la lettura da tastiera, fa solo perdere tempo
  • Re: URGENTE problema con liste allocate dinamicamente (liste dinamiche)

    bistemmacchina ha scritto:


    Ma sinceramente non capisco cosa c'entri col mio programma. Qualcuno potrebbe darmi una mano?
    Premesso che non ho letto in modo approfondito il codice che hai postato e quindi non so se ci sono altri errori, ma da un'occhiata molto veloce mi sono subito accorto che c'era qualcosa che non andasse e il mio precedente post voleva essere un input per aiutarti a correggere questo "errore" in modo autonomo.
    Dal momento che il precedente esempio non ha sortito l'effetto desiderato, ritento con questo più esplicito frammento di codice:
    #include <stdio.h>
    
    void fun(int *ptr)
    {
        ptr = NULL;
    }
    
    int main()
    {
        int a = 5;
        int *p = &a;
        printf("%x", p);
        fun(p);
        printf("\n%x", p);
    }
    Cosa noti? Riesci a cogliere il parallelismo col tuo codice?
  • Re: URGENTE problema con liste allocate dinamicamente (liste dinamiche)

    È poco che studio informatica, potrei avere qualche lacuna nel mio studio che non mi permette di identificare il problema. Potreste degnarvi, voi sommi programmatori, di abbassarvi al mio livello e spiegarmi semplicemente dove sta l'errore senza sollevare nuovi punti di domanda? O siete troppo superiori? Mamma mia quanta saccenza...
  • Re: URGENTE problema con liste allocate dinamicamente (liste dinamiche)

    Per esempio non ho mai visto il tipo %x
  • Re: URGENTE problema con liste allocate dinamicamente (liste dinamiche)

    Per esempio non ho mai visto il tipo %x
    Gli indirizzi di memoria sono spesso scritti in esadecimale e lo specificatore di formato %x serve appunto per stampare valori esadecimali.
    è poco che studio informatica, potrei avere qualche lacuna nel mio studio che non mi permette di identificare il problema. Potreste degnarvi, voi sommi programmatori, di abbassarvi al mio livello e spiegarmi semplicemente dove sta l'errore senza sollevare nuovi punti di domanda? O siete troppo superiori? Mamma mia quanta saccenza...
    Per quanto mi riguarda non sono un "sommo programmatore", ma un dilettante che utilizza la programmazione come esercizio di logica!
    Se hai notato della saccenza mi dispiace, ma il mio scopo, visto anche il tuo corso di studi e visto che le liste concatenate non sono certo tra i primi argomenti ad essere affrontati in un corso di informatica, era semplicemente quello di indurti a ragionare.

    Il codice che ho postato si limita a stampare per due volte il contenuto (un indirizzo di memoria) di uno stesso puntatore. Tra i due printf() però viene invocata la funzione fun() che setta a NULL (di solito pari a 0) il puntatore passato alla funzione. Lanciando il programma si nota però che in entrambi i casi viene stampato lo stesso indirizzo di memoria:
    - se questo è l'output che ti saresti aspettato, allora quello nel codice da te postato è solo un errore di distrazione;
    - se invece ti saresti aspettato due valori diversi allora bisogna ragionare su cosa non ha funzionato.
    Il problema è che il passaggio della variabile p alla funzione fun() avviene per valore. Al riguardo riporto un frammento di un mio recente post in un altro topic:

    Nippolo ha scritto:


    In C il passaggio di un parametro ad una funzione avviene sempre per valore.
    Quando esegue la chiamata di una funzione, il programma costruisce una copia di ogni argomento, creando delle variabili locali nell'ambito della funzione; ciò significa che tutte le modifiche, fatte dalla funzione al valore di un argomento, hanno effetto soltanto nell'ambito della funzione stessa.
    Se invece si vuole che le modifiche apportate dalla funzione all'argomento non vadano perdute, bisogna modificare l'argomento attraverso il suo indirizzo di memoria. Ciò significa che in C, per simulare un passaggio per riferimento, bisogna passare alla funzione un puntatore di ordine superiore rispetto alla variabile che si vuole modificare attraverso la funzione.

    Esempi:
    - variabile di tipo int ==> argomento di tipo int*;
    - variabile di tipo char* ==> argomento di tipo char**;
    - variabile di tipo float*** ==> argomento di tipo float****.
    Quindi tornando al tuo codice, tutte le modifiche apportate all'argomento Testa dalla funzione CreaRiempiLista() andranno perse una volta tornati al main().

    Sottolineo ancora una volta che non ho letto approfonditamente il codice che hai postato, ma mi sono limitato a portare alla tua attenzione il primo errore che mi è balzato agli occhi. Se una volta corretto il suddetto errore noti che il programma continua a non funzionare facci sapere e nel caso possiamo ragionarci.
  • Re: URGENTE problema con liste allocate dinamicamente (liste dinamiche)

    Grazie mille per la risposta e scusa per la mia vecchia risposta dove ti ho dato del saccente. Ho scritto dopo un pomeriggio intero passato a cercare di trovare il problema ed ero molto nervoso... .Comunque proverò ad utilizzare la tua strada. P.S. non si potrebbe ovviare al "problema" facendo restituire al programma un puntatore e quindi facendo ua funzione tipo "TipoLista *CreaRiempiLista ()"? Teoricamente questa funzione dovrebbe creare al suo interno un puntatore alla lista dinamica, creare la lista, riempirla, per poi "sputarmi fuori" sul main un puntatore alla lista appena creata. Ditemi se potrebbe andare come strada per la risoluzione. Oppure pensavo anche di poter scrivere una funzione "RiempiLista" a parte, e di mettere la creazione della lista nel main, in modo tale da risolvere il problema dato che a quel punto i valori int all'interno delle mie struct verrebbero conservati utilizzando la funzione "RiempiLista"(sempre se ho capito bene). Detto questo ci tenevo a sottolineare che non ne sapevo nulla di questa cosa che vengono conservati solamente gli indirizzi ad un oggetto, e non l'oggetto stesso. Mi è stato detto che per partito preso, le function conservassero solo gli array e i puntatori in quanto array e puntatori, ma non per il motivo che mi hai detto tu. Senza voler peccare di superbia, penso sia questo il motivo per cui non riuscivo a comprendere i vostri esempi. Comunque grazie mille in anticipo anche per le future risposte. Aspetto il tuo\vostro parere sui miei due "metodi alternativi".Ciao
  • Re: URGENTE problema con liste allocate dinamicamente (liste dinamiche)

    Ciao, scrivo per rispondermi da solo. Ha funzionato sia la tua strada che la mia prima risoluzione alternativa, ovvero quella della funzione "TipoLista *CreaRiempiLista ()" precisamente scritta così:
    
    #include <stdio.h>
    #include <stdlib.h>
    typedef struct ElemLista
    {
        int Dato;
        struct ElemLista *Prossimo;
    } TipoLista;
    TipoLista *CreaRiempiLista()
    {
        int N;
        TipoLista *PuntProvv, *Testa;
        printf("Inserisci gli elementi della lista separati da un invio\n\n");
        scanf("%d", &N);
        if (N < 0)
        {
            Testa = NULL;
            return (Testa);
        }
        else
        {
            PuntProvv = malloc(sizeof(TipoLista));
            PuntProvv->Dato = N;
            PuntProvv->Prossimo = NULL;
            Testa = PuntProvv;
            while (N > 0)
            {
                scanf("%d", &N);
                if (N < 0)
                {
                    return (Testa);
                }
                else
                {
                    PuntProvv->Prossimo = malloc(sizeof(TipoLista));
                    PuntProvv = PuntProvv->Prossimo;
                    PuntProvv->Dato = N;
                    PuntProvv->Prossimo = NULL;
                }
            }
        }
    }
    
    Comunque grazie mille per aver colmato questa mia (direi importante) lacuna sulle functions. P.S. c'è un modo di chiudere il topic? sono nuovo sui forum in generale...
  • Re: URGENTE problema con liste allocate dinamicamente (liste dinamiche)

    non si potrebbe ovviare al "problema" facendo restituire al programma un puntatore e quindi facendo ua funzione tipo "TipoLista *CreaRiempiLista ()"?
    Certo!
    Detto questo ci tenevo a sottolineare che non ne sapevo nulla di questa cosa che vengono conservati solamente gli indirizzi ad un oggetto, e non l'oggetto stesso. Mi è stato detto che per partito preso, le function conservassero solo gli array e i puntatori in quanto array e puntatori, ma non per il motivo che mi hai detto tu.
    Magari io stesso non mi sono spiegato bene al riguardo, ma da quello che hai scritto non sono sicuro che tu abbia capito bene cosa io intendessi.
    A scanso di equivoci, come andrebbe modificato il seguente codice affinché le modifiche apportate al puntatore p passato alla funzione siano conservate?
    #include <stdio.h>
    
    void fun(int *ptr)
    {
        ptr = NULL;
    }
    
    int main()
    {
        int a = 5;
        int *p = &a;
        printf("%x", p);
        fun(p);
        printf("\n%x", p);
    }
    Ovviamente la funzione deve restare di tipo void.
  • Re: URGENTE problema con liste allocate dinamicamente (liste dinamiche)

    Allora, stando a quello che ho capito per far si che venga modificato un oggetto, bisogna dare in pasto al calcolatore un puntatore a quell'oggetto. Dato che si vuole modificare un puntatore, la funzione fun dovrebbe ricevere come argomento un puntatore a puntatore di tipo int. di conseguenza il codice dovrebbe essere
    #include <stdio.h>
    #include <stdlib.h>
    
    void fun(int **ptr)
    {
        *ptr = NULL;
    }
    
    int main()
    {
        int a = 5;
        int *p = &a, **b = &p;
        printf("%x", p);
        fun(b);
        printf("\n%x", p);
    }
  • Re: URGENTE problema con liste allocate dinamicamente (liste dinamiche)

    Un'altra domanda veloce... perchè quando utilizzi il NULL non usi la stdlib? La definizione di NULL non dovrebbe essere qui?
  • Re: URGENTE problema con liste allocate dinamicamente (liste dinamiche)

    La funzione va bene, per quanto riguarda il main basta fare qualcosa del genere:
    int main()
    {
        int a = 5;
        int *p = &a;
        printf("%x", p);
        fun(&p);
        printf("\n%x", p);
    }
    non c'è bisogno di dichiarare un puntatore doppio.
    Un'altra domanda veloce... perchè quando utilizzi il NULL non usi la stdlib? La definizione di NULL non dovrebbe essere qui?
    Non saprei dirti, credo dipenda dalla versione della libreria. In ogni caso se il compilatore non mi fa storie evidentemente la macro di NULL è stata definita.
Devi accedere o registrarti per scrivere nel forum
14 risposte