Pagina 2 di 2 primaprima 1 2
Visualizzazione dei risultati da 11 a 15 su 15
  1. #11
    Utente di HTML.it L'avatar di Scara95
    Registrato dal
    Jul 2009
    residenza
    Zimella (VR)
    Messaggi
    2,589
    Un consiglio, mai eseguire istruzioni di input output all'interno di una funzione che non dovrebbe prevedere IO, come quella che hai scritto tu.
    Quindi parto con qualche correzione
    codice:
    void freeMat(int **&m, size_t size) {
        for(int i = 0; i < size; ++i)
            delete[] m[i];
        delete[] m;
        //correzione sul mio stesso codice :D anche se non strettamente necessaria
        m = NULL; //in caso di doppia deallocazione non lancia errore
    }
    
    
    int calc_ind_min(int ** m,int size,int r) //non è necessaria &, ti lascio approfondire
    {
        int min=m[r][0];
        int i,indmin=0;
        for (i=0;i<size;i++)
        {
          if (m[r][i]<min)
          {
            min=m[r][i];
            indmin=i;
          }
        }
        //meglio evitare IO all'interno di funzione non create SPECIFICATAMENTE per IO
        return indmin;
    }
    
    
    //...
        for(r=0;r<size;r++)
        {
            cout << calc_ind_min(m,size,r);
        }
    //...
    Passiamo ora a rispondere alle tue domande.
    size_t non è altro che un intero positivo che rappresenta le grandezze in bytes, è definito proprio come typedef unsigned int size_t;.
    Analizziamo la funzione per l'allocazione della matrice. In particolare, assumendo size l'ordine della matrice quadrata e m una variabile int **,
    codice:
        m = new int *[size];
        for(int i = 0; i < size; ++i)
            m[i] = new int[size];
    Per l'allocazione della matrice non la si considera come tale, ma come array di array: ad esempio la matrice
    codice:
    m
    1 2 3
    4 5 6
    7 8 9
    è rappresentata dome un array
    codice:
    m = A B C
    dove A B C sono
    codice:
    A = 1 2 3
    B = 4 5 6
    C = 7 8 9
    Perciò l'allocazione di divide in due parti: una prima parte che alloca un array di puntatori ad interi
    codice:
        m = new int *[size];
    e una parte dove ad ogni puntatore è assegnato un array di interi
    codice:
        for(int i = 0; i < size; ++i)
            m[i] = new int[size];
    La deallocazione avviene all'inverso, prima si deallocano i blocchi interni, poi quelli esterni. Qui per la precisione si parla di jagged arrays. Puoi cercare su internet.
    "Quid enim est, quod contra vim sine vi fieri possit?" - Cicerone, Ad Familiares

  2. #12
    Aggiungo solo una coppia di brevi esempi (ormai una FAQ) sull'allocazione dinamica "da manuale" di array multidimensionali.

    Esempio di base, volutamente incompleto:
    codice:
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void)
    {
        size_t righe, colonne, i, j;
        int **matrice;
    
        printf(" Righe........: ");
        scanf("%d", &righe);
        printf(" Colonne......: ");
        scanf("%d", &colonne);
        puts("");
    
        matrice = (int **)malloc(righe * sizeof(int *));
        if (NULL == matrice)
        {
            fputs("Errore di allocazione base array !\n", stderr);
            return 1;
        }
        
        for (i = 0; i < righe; ++i)
        {
            int *p;
            p = (int *)malloc(colonne * sizeof(int));
            if (NULL != p)
            {
                matrice[i] = p;
            }
            else
            {
                fprintf(stderr, "Errore di allocazione alla riga %d!\n", i);
                while (i--)
                {
                    free(matrice[i]);
                }
                free(matrice);
                return 2;
            }
        }
    
        for(i = 0; i < righe; ++i)
        {
            for(j = 0; j < colonne; ++j)
            {
                printf("Inserisci elemento riga %d e colonna %d: ", i, j);
                scanf("%d", &matrice[i][j]);
                puts("");
            }
        }
    
        for(i = 0; i < righe; ++i)
        {
            printf("matrice[%d] = {%d", i, matrice[i][0]);
            for(j = 1; j < colonne; ++j)
            {
                printf(", %d", matrice[i][j]);
            }
            puts("}");
            free(matrice[i]);
        }
        free(matrice);
    
        return 0;
    }
    Esempio di allocazione indiretta, entro una funzione accessoria.
    codice:
    /************************************************************************/
    /** Scopo del programma:...............................................**/
    /************************************************************************/
    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    
    #define ASIZE (8)
    
    typedef enum {FALSE, TRUE} Bool_t;
    
    Bool_t matrix_alloc(int ***m, const size_t row, const size_t col)
    {
        size_t i;
    
        assert(row > 0);
        assert(col > 0);
    
        /*
        ** PRIMO STEP: allocazione array di base
        */
        *m = (int **)malloc(row * sizeof(int *));
        if (NULL == *m)
        {
            fputs("Errore di allocazione base array !\n", stderr);
            return (FALSE);
        }
    
        for (i = 0; i < row; ++i)
        {
            int *p;
            /*
            ** SECONDO STEP: allocazione di ogni singolo array-riga
            */
            p = (int *)malloc(col *sizeof(int));
            if (NULL != p)
            {
                /*
                ** TERZO e ULTIMO STEP: collegamento riga ad array base
                */
                (*m)[i] = p;
            }
            else
            {
                fprintf(stderr, "Errore di allocazione alla riga %d!\n", i);
                while (i--)
                {
                    free((*m)[i]);
                    fprintf(stderr, "%d ", i);
                }
                free(*m);
                return (FALSE);
            }
        }
        return (TRUE);
    }
    
    int main(void)
    {
        int **array;
        size_t righe, colonne;
        size_t i, j;
        Bool_t status;
    
        righe   = ASIZE;
        colonne = ASIZE;
    
        printf("Allocazione dinamica di un array "
               "bidimensionale %d x %d\n",
               righe, colonne);
    
        status = matrix_alloc(&array, righe, colonne);
    
        if(status)
        {
            printf("** Allocazione effettuata. "
                   "Inizializzazione di %d celle in corso...\n",
                   righe * colonne);
    
            for (i = 0; i < righe; ++i)
            {
                for (j = 0; j < colonne; ++j)
                {
                    array[ i ][ j ] = i * 10 + j;
                }
            }
    
            puts("** Contenuto dell'array:");
            for (i = 0; i < righe; ++i)
            {
                for (j = 0; j < colonne; ++j)
                {
                    printf( "array[%d][%d] = %02d\n", i, j, array[ i ][ j ]);
                }
                free(array[i]);
            }
            free(array);
        }
    
        return (EXIT_SUCCESS);
    }/* EOF: alloc_array.c */
    Infine, un esempio ancora più avanzato che mostra una panoramica di metodi di allocazione dinamica a vari livelli di indirezione.

    Aggiungo solo un paio di note che forse potranno tornare utili all'OP solo in una fase più avanzata dello studio.

    1) L'uso di jagged arrays va imparato (per scopi scolastici) e poi dimenticato. Nel real world l'allocazione in un blocco unico impera nel 99% del codice, per motivi che spaziano dalle prestazioni, alla robustezza, alla manutenibilità del codice: i rari casi nei quali si ricorre ad un array di arrays come nella manualistica e nella didattica sono legati, ad esempio, alla rappresentazione di matrici sparse e/o di array di liste, alberi ed altri ADT che possano beneficiare della potenzialità di una simile struttura, ossia la capacità di referenziare con un solo array di base altri array di lunghezze potenzialmente molto diverse tra loro.

    2) In linguaggio C++ è comunque del tutto sconsigliato l'uso degli array C-alike. Esistono apposite classi come vector, valarray, list, string e altre. Si veda questo famoso thread per una spiegazione in merito.
    Ultima modifica di M.A.W. 1968; 11-06-2014 a 13:42
    • Un plauso a Grisha Perelman, raro esempio di genuino anticonformismo umano e scientifico.

  3. #13
    Ringrazio entrambi! Quindi Scara se ho capito bene non sempre devo dichiarare parametri di I/O per le funzioni? Ma se non lo faccio non rischio che il compilatore mi dia errori?
    Mi è molto più chiaro lo scopo di size_t, e ho compreso concettualmente come funziona l'allocazione di array di array! Inoltre poco fa ho aggiunto una nuova funzione al mio programma, completandolo. Ecco qui:

    codice:
    #include <iostream>#include <fstream>
    #include <cstdlib>
    
    
    
    
    using namespace std;
    
    
    // lettura matrice da file + allocazione
    int **readMat(int**&m, size_t& size) 
    {
        ifstream in("mat.txt");
        in >> size;
        m = new int *[size];
        for(int i = 0; i < size; ++i)
            m[i] = new int[size];
        for(int i = 0; i < size; ++i)
            for(int j = 0; j < size; ++j)
                in >> m[i][j];
        return m;
    }
    
    
    // Liberazione memoria
    void freeMat(int **&m, size_t size) {
        for(int i = 0; i < size; ++i)
            delete[] m[i];
        delete[] m;
    }
    
    
    // Calcolo del minimo delle righe
    int   calc_ind_min(int **m,int size,int r)
    {
        int min=m[r][0];
        int i,indmin=0;
        for (i=0;i<size;i++)
        {
          if (m[r][i]<min)
          {
            min=m[r][i];
            indmin=i;
          }
        }
        
        return indmin;
    }
    // Calcolo del massimo delle colonne + calcolo e stampa del punto di sella
    
    int trova_punto_sella(int**m,int size, int t)
    {
          int sella;
          int posc;
          posc = calc_ind_min(m,size,t);
          int maxcol=m[t][posc];
          for(int i=0;i<size;i++)
          {
                  if(maxcol<m[i][posc])
                     maxcol=m[i][posc];
          }
          if(maxcol==m[t][posc])
          {
                  sella=maxcol;
                  cout<<sella<<" Punto di sella in posizione "<<t<<" "<<posc<<endl;
                  return sella;
           }
           else
           return -1;
     
    }
    
    
    int main(void) {
        size_t size;
        int **m;
        readMat(m, size);
       // stampa a video della matrice allocata
        for(int i = 0; i < size; ++i) {
            for(int j = 0; j < size; ++j)
                cout << m[i][j] << '\t';
            cout << endl;
        }
        
        int r;
        for(r=0;r<size;r++)
        {
            calc_ind_min(m,size,r);
        }
        cout << endl;
        cout << endl;
        
        int t;
        for(t=0;t<size;t++)
        
    { trova_punto_sella(m,size,t);
    }
        freeMat(m, size);
        return 0;
    }
    Ultima modifica di DaemonDestroyer; 11-06-2014 a 16:00

  4. #14
    Ti ringrazio MAW per i materiali da te fornitomi, poiché sono diciamo nella fase iniziale dello studio del C++, mi saranno molto utili. Mi permetto di dire, che spesso confronti come questo sui forum (almeno nel mio caso) risultano molto più utili alla comprensione e allo studio dei linguaggi informatici che non leggere dai libri universitari, spesso non molto chiari...

  5. #15
    Utente di HTML.it L'avatar di Scara95
    Registrato dal
    Jul 2009
    residenza
    Zimella (VR)
    Messaggi
    2,589
    Quote Originariamente inviata da DaemonDestroyer Visualizza il messaggio
    Quindi Scara se ho capito bene non sempre devo dichiarare parametri di I/O per le funzioni?
    No hai mal interpretato: devi evitare operazioni di IO all'interno delle funzioni se non create appositamente per quello scopo, cioè devi evitare cin>> cout<< ...
    Il principio è: se non è necessario alla funzione non includerlo nella funzione, ma nel main.
    Concordo con M.A.W. che è molto migliore l'allocazione di un blocco unico.
    "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.