Cosa significa variabile dinamica?

di il
33 risposte

Cosa significa variabile dinamica?

Scrivere un programma principale che legge da std input una sequenza di numeri interi, fino ad incontrare un numero negativo, e la memorizza in un array A di puntatori a interi (dim. max 1000) nel modo seguente: per ogni intero x letto da input, se x non è presente in A, alloca una variabile dinamica in cui memorizza x e aggiunge in fondo ad A il puntatore alla nuova variabile; se x è già presente in A, aggiunge in fondo ad A il puntatore alla variabile contenente x (senza allocare una nuova variabile). Al termine il programma stampa il numero di nuove variabili allocate e la sequenza dei valori memorizzati in A.

Ho questo esercizio da svolgere, cosa significa variabile dinamica? Questo è quello che ho pensato io ma non credo sia quello che chiede.

....
int *y = new int;
*y = x;
A = y;
delete y;
n++; // contatore variabili
...

33 Risposte

  • Re: Cosa significa variabile dinamica?

    Non in troppi
  • Re: Cosa significa variabile dinamica?

    Non in troppi
    Beh, non sempre si ha tanto tempo da dedicare a rispondere VOLONTARIAMENTE. Non bisogna essere impazienti / spiritosi ...

    In ogni caso, una "variabile dinamica" è un terminologia non molto precisa. Semmai si parla di allocazione dinamica della memoria o di dato allocato dinamicamente.

    Comunque, il quesito non è molto chiaro e il codice che hai proposto troppo minimale ... forse è per questo che nessuno ti ha risposto ancora ...
    Non si capisce come affronti le parti SE e ALTRIMENTI dell'esercizio e, comunque, la delete non ha senso perché così perdi il dato allocato.
  • Re: Cosa significa variabile dinamica?

    In effetti non è molto chiaro, in particolare non capisco quale possa essere l'utilità di memorizzare nell'array dei puntatori il puntatore alla variabile che si usa come buffer in scanf()... forse per riconoscere i valori non univoci? Ma allora non sarebbe più lineare evitare di immettere quei valori e buona notte al secchio? Boh?

    Comunque, col solito "spirito enigmistico", ho provato a risolvere l'esercizio e m'è venuto fuori un programmino d'un centinaio di righe. Non mando il codice finché non avete terminato la vostra conversazione, però, se no poi mi sgridano...

    P.S.
  • Re: Cosa significa variabile dinamica?

    "A naso" vuole una specie di lista, mantenuta però dentro un array.
    Essenzialmente sarà l'allocazione sullo heap della variabile (cosa inutile, ma didatticamente estensibile ad esempio in una struttura).

    Nel contesto direi che "variabile dinamica" è... una variabile intera, allocata dinamicamente, il cui puntatore viene "serbato" all'interno del vettore.

    In una situazione del genere (tipica del mondo OO) dovrai fare attenzione ai leak della memoria, e fare anche una sorta di "distruttore" (cioè una funzione che dealloca le variabili insieme -prima- alla struttura principale, quando quest'ultima "muoia").

    La porzione è ridondante (c'è i e n che paiono fare la stessa cosa), concordo nell'attendere qualcosa di "più" completo
  • Re: Cosa significa variabile dinamica?

    No non sono ridondanti, semplicemente non avevi tutto il codice
    Comunque ho risolto da solo, volevo sapere solo cosa significa "variabile dinamica" in generale, perchè come alcuni di voi hanno detto, non è proprio una definizione "standard"! La mia era una battuta non c'è bisogno di offendersi, nessuno mi deve niente lo so Grazie a tutti per le risposte, voi come lo avete pensato?

    Ahh *IMPORTANTE* non ho capito bene la storia dei "delete", ho capito a cosa servono, ma non ho capito quando, come accennava uno di voi, dovrei fare una funzione che simula un distruttore? quando dovrei farla, dopo l'output? qualcuno mi farebbe un esempio per questo codice?

    #include <iostream>

    using namespace std;

    void alloca (int *A[], int cont, int *punt_x)
    {
    int *y = new int;
    y = punt_x;
    A[cont] = y;
    return;
    }

    int main()
    {
    int x = 0;
    int n = 0;
    int cont = 0;
    bool b = false;
    int *A[1000];
    cout << "Dai una sequenza di numeri interi (negativo per smettere):" << endl;
    do
    {
    cin >> x;
    int *punt_x = new int;
    *punt_x = x;
    if (x < 0)
    break;
    for (int i = 0; i < cont; i++)
    if (*A == x)
    {
    b = true;
    break;
    }
    if (b == false)
    {
    alloca(A,cont,punt_x);
    n++; // contatore numero di variabili
    }
    if (b == true)
    {
    A[cont] = punt_x;
    }
    b = false;
    cont++; //indice array di puntatori
    }
    while (true);
    cout << endl;
    cout << "Allocate " << n << " variabili" << endl;
    cout << "Sequenza: ";
    for (int j = 0; j < cont; j++)
    cout << *A[j] << " ";
    cout << endl;
    return 0;
    }

    //input: 4 5 4 4 3 2 2 4 6 7 -1
  • Re: Cosa significa variabile dinamica?

    La mia impressione è che tu stia allocando un po' a casaccio, mentre è una certezza che non deallochi mai la memoria allocata. Inoltre, vedo che non controlli mai che le allocazioni siano andate a buon fine, il che (per quel poco che ne so) è una potenziale fonte di grane.

    Il passaggio "se x è già presente in A, aggiunge in fondo ad A il puntatore alla variabile contenente x (senza allocare una nuova variabile)" io l'ho interpretato in modo completamente diverso dal tuo, perché secondo me richiedeva che si inserisse in A[] l'indirizzo di x, con &x. C'è da dire che mi sa che chi ha scritto l'esercizio ha un'opinione piuttosto personale in merito all'uso della lingua italiana...
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    int main() {
        int x = 0;
        int n = 0;
        int cont = 0;
    
        int *A[1000];
        memset( A, 0, sizeof(A) ); // azzera l'array, il che e' importante
    
        cout << "Dai una sequenza di numeri interi (negativo per smettere):" << endl;
    
        try {
            while( x >= 0 ) {
                cin >> x;
    
                if( x >= 0 ) {
                    bool b = false;
    
                    for( int i = 0; i < cont && b == false; i++ ) {
                        b = ( (A[i] != &x) && (*A[i] == x) );
                    }
    
                    if( b == false ) {
                        A[cont] = new int(x);
                        n++; // contatore numero di variabili
                    }
                    else {
                        A[cont] = &x;
                    }
    
                    cont++; //indice array di puntatori
                }
            }
    
            cout << endl;
            cout << "Allocate " << n << " variabili" << endl;
            cout << "Sequenza: ";
    
            for( int j = 0; j < cont; j++ ) { // questa
                if( A[j] != &x )
                    cout << *A[j] << " ";
            }
    
            cout << endl;
        } catch( ... ) {
            cout << "\nSi e' verificato un errore!\n\n";
        }
    
        // qui c'e' quella specie di "distruttore" che dealloca
        // con delete la memoria dinamica allocata con new
        for( --cont; cont>=0; --cont ) {
            if( A[cont] != &x )
                delete A[cont];
            A[cont] = NULL;
        }
    
        return 0;
    }
    In C l'avevo fatto in quest'altro modo:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define QMV 1000 // QMW: quantita' massima di valori
    
    void presentazione( void );
    void notifica_esito( int **a, int qmv, int *buff, int qEl, int qUni );
    
    int main() {
        int qEl;  // qEl: quantita' di elementi nell'array a[]
        int qUni; // qUni: quantita' dei valori univoci nell'array a[]
        int *a[QMV]; // l'array dei puntatori richiesti
        int i, x;
    
        presentazione();
    
        memset( a, 0, QMV*sizeof(*a) ); // azzera l'array
    
        qEl  = 0;
        qUni = 0;
    
        x = 0;
    
        do {
            printf( "Immetti un valore: " );
            scanf( "%d", &x );
    
            if( x >= 0 ) {
                int gp; // gp: gia' presente
    
                for( gp=0, i=0; i<qEl && !gp; ++i )
                    gp = ( *(a[i]) == x ) && ( a[i] != &x );
    
                if( !gp ) {
                    a[qEl] = malloc( sizeof(*a[qEl]) );
    
                    if( NULL != a[qEl] ) {
                        *a[qEl] = x;
                        ++qUni;
                        ++qEl;
                    }
                    else {
                        printf( "\nAllocazione della memoria fallita!\n\n" );
    
                        for( --qEl; qEl>=0; --qEl ) {
                            if( a[qEl] != &x )
                                free( a[qEl] );
                            a[qEl] = NULL;
                        }
    
                        break;
                    }
                }
                else {
                    // di questa operazione proprio non capisco il senso,
                    // ma e' questo che sembra richiedere l'esercizio!!!
                    a[qEl] = &x;
                    ++qEl;
                }
            }
        } while( x >= 0 && qEl<QMV );
    
        notifica_esito( a, QMV, &x, qEl, qUni );
    
        printf( "Premi \"invio\" per lasciare il programma...   " );
        getchar();
    
        return 0;
    }
    
    void presentazione( void ) {
        printf( "Immissione dei dati.\n" );
        printf( "Immetti una serie di massimo %d valori interi positivi.\n", QMV );
        printf( "Per terminare l'immissione, immetti un valore intero negativo." );
        printf( "\n\n" );
    }
    
    void notifica_esito( int **a, int qmv, int *buff, int qEl, int qUni ) {
        int i;
    
        if( qEl >= 0 ) {
            printf( qUni!=1 ? "\nSono stati immessi" : "\nE' stato immesso" );
            printf( " nell'array %d ", qUni );
            printf( "valor%c univoc%c", qUni!=1?'i':'e', qUni!=1?'i':'o' );
            printf( "%c\n\n", qUni>0?':':'.' );
        }
        else {
            printf( "S'e' verificato un errore, ");
            printf( "l'immissione non e' significativa.\n\n" );
        }
    
        for( i=0; i<qEl; ++i ) {
            if( a[i] != buff ) {
                printf( "%d%s", *(a[i]), i!=qEl-1?" ":"\n\n" );
                free( a[i] ); // questa punta a una variabile allocata dinamicamente
            }
            else {
                printf( i!=qEl-1 ? "" : "\n\n" );
            }
    
            a[i] = NULL; // superfluo, ma ci sta sempre bene
        }
    }
  • Re: Cosa significa variabile dinamica?

    L'output però doveva essere del genere:

    Dai una sequenza di numeri interi (negativo per smettere):
    4 5 4 4 3 2 2 4 6 7 -1

    Allocate 6 variabili
    Sequenza: 4 5 4 4 3 2 2 4 6 7

    Il C non lo conosco
    Per la parte in C++ sei stato cosi bravo che hai usato lo stesso nome per le variabili mi hai risparmiato un sacco di fatica Grazie per il "distruttore" Questo dovrebbe essere l'esercizio corretto:
    
    #include <iostream>
    #include <cstring>
    
    using namespace std;
    
    int main()
    {
     int x = 0;
     int n = 0;
     int cont = 0;
     bool b = false;
     int *A[1000];
     cout << "Dai una sequenza di numeri interi (negativo per smettere):" << endl;
     try
     {
      do
      {
       cin >> x;
       if (x < 0)
        break;
       int *punt_x = new int;
    
       for (int i = 0; i < cont; i++)
        if (*A[i] == x)
        {
         b = true;
         punt_x = A[i];
         break;
        }
    
       if (b == false)
       {
        int *y = new int(x);
        A[cont] = y;
        n++;
       }
    
       if (b == true)
        A[cont] = punt_x;
    
       b = false;
       cont++;
      }
      while (true);
     } catch (...) {cout << "Errore" << endl;}
    
     cout << endl;
     cout << "Allocate " << n << " variabili" << endl;
     cout << "Sequenza: ";
     for (int j = 0; j < cont; j++)
      cout << *A[j] << " ";
     cout << endl;
    
     for(--cont; cont >= 0; --cont) //"distruttore"
      delete A[cont];
    
     return 0;
    }
    
  • Re: Cosa significa variabile dinamica?

    Non c'è niente di C++ in quei programmi, ma (ragionavolmente) sei ai primissimi passi, quindi evito pipponi titanici su come andrebbe fatto, sia in C, sia in C++.

    PS sono pressochè illeggibili entrambi, pur essendo banali
  • Re: Cosa significa variabile dinamica?

    L'output dipende dal modo in cui si interpreta il testo dell'esercizio. Secondo me è corretta la mia versione, anche se è per forza un "secondo me", visto come è stato scritto il quesito -- sembra quasi di leggere il testo di una qualsiasi tra le nostre leggi: le leggi, le rileggi, e continui a chiederti "cosa avranno mai voluto dire?". Solo che con le leggi lo fanno apposta per potere poi esercitare impunemente quell'arbitrio che proprio le leggi dovrebbero inibire, mentre nel caso dell'esercizio temo che le ragioni non siano così "sottili".
  • Re: Cosa significa variabile dinamica?

    L'output e l'input d'esempio sono scritti nell'esercizio, e quelli sono Anche io non avevo ben capito il testo! Grazie mille Aldo per tutte le risposte!

    In quanto a m2, sarai pur bravo a programmare, questi codici faranno schifo, però tutte le tue risposte sono state inutili, ti ringrazio comunque per averci provato.
  • Re: Cosa significa variabile dinamica?

    M2, tieni sempre presente che ho imparato per i fatti miei, quindi sono come "un'isola nell'oceano".

    Comunque sarebbe anche interessante capire perché li trovi illeggibili... Volendo ne posso fare l'analisi riga per riga, e in ciascuna riga c'è un perché (e un come) univoco, dunque esplicito.

    In soldoni:
     1) dichiaro le variabili che saranno usate nel main()
     2) presento il programma, spiegando cosa fa
     3) inizializzo le variabili (tranne i, che viene inizializzata
        piu' avanti, nel "for" dove viene usata)
     4) apro un ciclo che termina quando x>0 o quando l'array e' pieno
     5) |   chiedo un dato e
     6) |   se e' valido...
     7) |   |   se il dato non c'e' ancora nell'array
     8) |   |   |   alloco la memoria destinata a contenerlo e...
     9) |   |   |   se l'allocazione riesce
    10) |   |   |   |   colloco in coda all'array il puntatore
        |   |   |   |   alla memoria allocata, aggiornando i contatori
    11) |   |   |   altrimenti, se l'allocazione fallisca)
    12) |   |   |   |   segnalo l'errore e dealloco la memoria dinamica
        |   |   |   |   eventualmente già allocata, annullando per buona
        |   |   |   |   misura i puntatori nell'array, quindi lascio il ciclo
    13) |   |   altrimenti, se il dato e' gia' nell'array
    14) |   |   |   colloco in coda all'array il puntatore
        |   |   |   del buffer x aggiornando i contatori
    15) qui viene verificata la condizione di chiusura del ciclo aperto in 4)    
    16) notifico l'esito delle operazioni
    17) segnalo che e' ora di lasciare il programma, dando il tempo di leggerne
        l'esito ponendomi in attesa di "invio"
    Le variabili dal nome "strano" (ridotto ad una sigla, per "compattare" il codice e rendermi più facile tenere sott'occhio quel che sto facendo, senza avere righe che arrivano fino in Pakistan) sono TUTTE esplicitate con un commento che ne spiega il significato, tipo "qEl: quantita' di elementi nell'array a[]".

    Nella funzione presentazione(), ci sono solo delle printf() lineari che più lineari non si può. Le ho isolate in una funzione a parte solo per "snellire" il main(), sempre per tenere sott'occhio la maggior quantità possibile del codice sul quale vado a ragionare mentre lo scrivo (è una mia necessità).

    Anche la funzione notifica_esito() è in massima parte una serie di printf(), con l'unica aggiunta della deallocazione della memoria dinamica.
    La deallocazione, effettivamente, sarebbe stato meglio lasciarla là dove la memoria dinamica viene allocata, anche perche' il nome della funzione NON esplicita questa funzionalità. Mentre stavo scrivendo queste righe, ho provveduto quindi a confinare la deallocazione della memoria in una nuova funzione "a parte", con un nome che non dà adito a dubbi: libera_memoria_dinamica().

    Edit: ho dimenticato di aggiungere il codice aggiornato...
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define QMV 1000 // QMW: quantita' massima di valori
    
    void presentazione( void );
    void notifica_esito( int **a, int *buff, int qEl, int qUni );
    void libera_memoria_dinamica( int **a, int *buff, int qEl );
    
    int main() {
        int qEl;  // qEl: quantita' di elementi nell'array a[]
        int qUni; // qUni: quantita' dei valori univoci nell'array a[]
        int *a[QMV]; // l'array dei puntatori richiesti
        int x;
    
        presentazione();
    
        memset( a, 0, QMV*sizeof(*a) ); // azzera l'array
    
        qEl  = 0;
        qUni = 0;
    
        x = 0;
    
        do {
            printf( "Immetti un valore: " );
            scanf( "%d", &x );
    
            if( x >= 0 ) {
                int i, gp; // gp: gia' presente
    
                for( gp=0, i=0; i<qEl && !gp; ++i )
                    gp = ( *(a[i]) == x ) && ( a[i] != &x );
    
                if( !gp ) {
                    a[qEl] = malloc( sizeof(*a[qEl]) );
    
                    if( NULL != a[qEl] ) {
                        *a[qEl] = x;
                        ++qUni;
                        ++qEl;
                    }
                    else {
                        printf( "\nAllocazione della memoria fallita!\n\n" );
    
                        for( --qEl; qEl>=0; --qEl ) {
                            if( a[qEl] != &x )
                                free( a[qEl] );
                            a[qEl] = NULL;
                        }
    
                        break;
                    }
                }
                else {
                    // di questa operazione proprio non capisco il senso,
                    // ma e' questo che sembra richiedere l'esercizio!!!
                    a[qEl] = &x;
                    ++qEl;
                }
            }
        } while( x >= 0 && qEl<QMV );
    
        notifica_esito( a, &x, qEl, qUni );
        libera_memoria_dinamica( a, &x, qEl );
    
        printf( "Premi \"invio\" per lasciare il programma...   " );
        getchar();
    
        return 0;
    }
    
    void presentazione( void ) {
        printf( "Immissione dei dati.\n" );
        printf( "Immetti una serie di massimo %d valori interi positivi.\n", QMV );
        printf( "Per terminare l'immissione, immetti un valore intero negativo." );
        printf( "\n\n" );
    }
    
    void notifica_esito( int **a, int *buff, int qEl, int qUni ) {
        int i;
    
        if( qEl >= 0 ) {
            printf( qUni!=1 ? "\nSono stati immessi" : "\nE' stato immesso" );
            printf( " nell'array %d ", qUni );
            printf( "valor%c univoc%c", qUni!=1?'i':'e', qUni!=1?'i':'o' );
            printf( "%c\n\n", qUni>0?':':'.' );
        }
        else {
            printf( "S'e' verificato un errore, ");
            printf( "l'immissione non e' significativa.\n\n" );
        }
    
        for( i=0; i<qEl; ++i ) {
            if( a[i] != buff )
                printf( "%d%s", *(a[i]), i!=qEl-1?" ":"\n\n" );
            else printf( i!=qEl-1 ? "" : "\n\n" );
        }
    }
    
    void libera_memoria_dinamica( int **a, int *buff, int qEl ) {
        int i;
    
        for( i=0; i<qEl; ++i ) {
            if( a[i] != buff ) {
                free( a[i] ); // questa punta a una variabile allocata dinamicamente
                a[i] = NULL; // superfluo in questo caso, ma ci sta sempre bene
            }
        }
    }
    
  • Re: Cosa significa variabile dinamica?

    aldorenati ha scritto:


    In quanto a m2, sarai pur bravo a programmare, questi codici faranno schifo, però tutte le tue risposte sono state inutili, ti ringrazio comunque per averci provato.
    In realtà, contrariamente a quanto affermi, rileggendole direi che sono perfettamente aderenti a quanto avresti dovuto fare.
    Probabilmente non sei ancora in grado di capire neppure quello che leggi, lo scrivo senza intento polemico, ma solo come costatazione.

    Se ritieni che quei programmelli siano "buoni", me ne compiaccio.

    Forse, e dico solo forse, sarebbe stato più utile per te chiedere il perchè e il percome, sicchè avresti potuto imparare qualcosa.
    E magari di buone abitudini, non di pessime.
  • Re: Cosa significa variabile dinamica?

    Aldo (mio omonimo! già questo ti dà dei punti ), non avevo a disposizione l'esempio dell'output, e comunque trovo delle incongruenze nelle specifiche imposte dal testo, e provo a spiegare perché.

    Il testo dice: "se x è già presente in A, aggiunge in fondo ad A il puntatore alla variabile contenente x (senza allocare una nuova variabile)". Dunque, abbiamo la variabile int x che si comporta come un "buffer" NON dinamico, ovvero x ha una sua collocazione in memoria che rimane sempre quella per tutta la durata della sua esistenza (credo si debba parlare del suo "scopo").

    Dal testo, ogni volta che trovo un valore già immesso devo aggiungere ad A[] "il puntatore alla variabile contente x" (cioè, parrebbe di poter dire, il puntatore alla variabile x, visto che più avanti si dice "senza allocare una nuova variabile").

    Facendo così, fin dal punto in cui immetto quel puntatore la prima volta, mi ritrovo ad avere una locazione di memoria che corrisponde a tutti gli effetti ad x stesso! Quindi, quando ricevo l'input in x, mi ritrovo con diversi punti dell'array A[] che puntano tutti al valore appena immesso, quindi a partire dal primo valore duplicato, avro SEMPRE x contenuto in A[], nella forma del suo puntatore! A me sembra che questo meccanismo impedisca, di fatto, di immagazzinare in A[] i valori doppi. Proprio per questo ho inteso la frase dell'esercizio dove si diceva di elencare in output "la sequenza dei valori memorizzati in A" come una richiesta di elencare in output la sequenza dei valori UNIVOCI memorizzati in A, visto che gli altri non sono stati memorizzati per niente...

    Questo è quel che ho ricavato dall'analisi (con tutti i miei limiti) del testo che avevo a disposizione, e questo spiega perché nel mio codice appare quattro volte la verifica A[indice] != &x (anche se, nelle funzioni esterne, presente nella forma a[indice] != buff, per via del modo in cui sono passati i parametri).
  • Re: Cosa significa variabile dinamica?

    AldoBaldo ha scritto:


    M2, tieni sempre presente che ho imparato per i fatti miei, quindi sono come "un'isola nell'oceano".

    Comunque sarebbe anche interessante capire perché li trovi illeggibili... Volendo ne posso fare l'analisi riga per riga, e in ciascuna riga c'è un perché (e un come) univoco, dunque esplicito.
    A mia volta sto sviluppando un mio programma, non che abbia tantissimo tempo in questo momento.
    comunque...

    quando scrivo che è illeggibile, intendo che è "scritto da-cani-dilettanti-hobbysti", non che non si comprende, è banale.
    Le variabili dal nome "strano" (ridotto ad una sigla,
    Sono oggettivamente illeggibili.
    Così lascia perdere l'uso del case (notazione simil-ungherese modificata).
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define QMV 1000 // QMW: quantita' massima di valori
    
    Nessuno saprà mai cos'è QMW all'interno di un sorgente non banale come questo.
    Il commento che hai messo è inutile
    
    void presentazione( void );
    void notifica_esito( int **a, int *buff, int qEl, int qUni );
    void libera_memoria_dinamica( int **a, int *buff, int qEl );
    
    1) i prototipi delle funzioni sono inutili in questo caso, basta mettere il main in fondo
    2) i nomi dei parametri sono incomprensibili
    3) non si capisce se sono parametri di input, di output, o entrambi
    4) qEl (del tutto impossibile capire cos'è) può essere benissimo UNSIGNED (anzi, dovrebbe esserlo)
    
    int main() {
        int qEl;  // qEl: quantita' di elementi nell'array a[]
        int qUni; // qUni: quantita' dei valori univoci nell'array a[]
        int *a[QMV]; // l'array dei puntatori richiesti
        int x;
    
    come detto sopra non si capisce assolutamente cosa siano queste variabili, e cosa facciano
        memset( a, 0, QMV*sizeof(*a) ); // azzera l'array
    
    A cosa dovrebbe servire? Stiamo forse parlando di stringhe null terminate?
    Mi serve sapere se gli elementi sono a zero, oppure no?
    Mi servirebbero se, ad esempio, facessi un "distruttore" che elabora tutte le righe non vuote.
    Ma se mantengo il numero degli elementi, e l'array è quindi compreso strettamente tra [0...fine] allora
    è inutile
    
        do {
            printf( "Immetti un valore: " );
            scanf( "%d", &x );
    
    cosa sarà mai x? e perchè è definito intero?
    Se vogliamo darci alla "storia" allora le variabili intere NON si chiamano X (che sono i float).
    è una derivazione delle consuetudini di default FORTRAN
    
            if( x >= 0 ) {
                int i, gp; // gp: gia' presente
    
                for( gp=0, i=0; i<qEl && !gp; ++i )
                    gp = ( *(a[i]) == x ) && ( a[i] != &x );
    
    Cosa fa questa porzione di codice?
    E, tral'altro, perchè i salta fuori dentro un ciclo (do in questo caso) ?
    Siamo sicuri di essere certi della priorità degli operatori nella condizione del ciclo for?
    A che serve ++i (se non per le seghe mentali rispetto a presunte ottimizzazioni rispetto a i++)

    ... per il resto controllo, poi edito

    if( !gp ) {
    a[qEl] = malloc( sizeof(*a[qEl]) );

    if( NULL != a[qEl] ) {
    *a[qEl] = x;
    ++qUni;
    ++qEl;
    }
    else {
    printf( "\nAllocazione della memoria fallita!\n\n" );

    for( --qEl; qEl>=0; --qEl ) {
    if( a[qEl] != &x )
    free( a[qEl] );
    a[qEl] = NULL;
    }

    break;
    }
    }
    else {
    // di questa operazione proprio non capisco il senso,
    // ma e' questo che sembra richiedere l'esercizio!!!
    a[qEl] = &x;
    ++qEl;
    }
    }
    } while( x >= 0 && qEl<QMV );

    notifica_esito( a, &x, qEl, qUni );
    libera_memoria_dinamica( a, &x, qEl );

    printf( "Premi \"invio\" per lasciare il programma... " );
    getchar();

    return 0;
    }

    void presentazione( void ) {
    printf( "Immissione dei dati.\n" );
    printf( "Immetti una serie di massimo %d valori interi positivi.\n", QMV );
    printf( "Per terminare l'immissione, immetti un valore intero negativo." );
    printf( "\n\n" );
    }

    void notifica_esito( int **a, int *buff, int qEl, int qUni ) {
    int i;

    if( qEl >= 0 ) {
    printf( qUni!=1 ? "\nSono stati immessi" : "\nE' stato immesso" );
    printf( " nell'array %d ", qUni );
    printf( "valor%c univoc%c", qUni!=1?'i':'e', qUni!=1?'i':'o' );
    printf( "%c\n\n", qUni>0?':':'.' );
    }
    else {
    printf( "S'e' verificato un errore, ");
    printf( "l'immissione non e' significativa.\n\n" );
    }

    for( i=0; i<qEl; ++i ) {
    if( a != buff )
    printf( "%d%s", *(a), i!=qEl-1?" ":"\n\n" );
    else printf( i!=qEl-1 ? "" : "\n\n" );
    }
    }

    void libera_memoria_dinamica( int **a, int *buff, int qEl ) {
    int i;

    for( i=0; i<qEl; ++i ) {
    if( a != buff ) {
    free( a ); // questa punta a una variabile allocata dinamicamente
    a = NULL; // superfluo in questo caso, ma ci sta sempre bene
    }
    }
    }
    [/code][/quote]
Devi accedere o registrarti per scrivere nel forum
33 risposte