Esercizio sulle matrici

di il
45 risposte

Esercizio sulle matrici

Ciao a tutti!
Eccomi già qua che vi tormento.. Scusate il disturbo.
Ho un esercizio sulle matrici che non riesco a cavarci fuori i piedi...
Ecco il testo:

Creare i file matrix.h e matrix.c che consentano di utilizzare la seguente struttura:

struct matrix {
        size_t N, M;
        double *data;
};
E la funzione :
extern struct matrix *mat_transpose( const struct matrix *mat);

La struct consente di rappresentare matrici di dimensione arbitraria, dove N è il numero di righe, M è il numero di colonne e data è un puntatore a NxM valori di tipo double memorizzati per righe.
La funzione accetta come parametro un puntatore ad una matrice e deve ritornarne la trasposta, allocata dinamicamente sull'heap. Il puntatore alla matrice non sarà mai NULL.

Allora il mio file matrix.h è il seguente :

#if!defined MATRIX_H
#define MATRIX_H

#include <stdlib.h>
struct matrix {
         size_t N, M;
         double *data;
};

extern struct matrix *mat_transpose (const struct matrix *mat);

#endif
Poi ho creato un file main.c

#include "matrix.h"
#include <stdio.h>

int main(void)
{
      struct matrix A;
      A.N = 2;
      A.M = 3;
      A.data = malloc(sizeof(double) * 6);

      A.data[0] = 1.0;
      A.data[1] = 2.0;
      A.data[2] = 3.0;
      A.data[3] = 4.0;
      A.data[4] = 5.0;
      A.data[5] = 6.0;

     printf( "%d\n" , mat_transpose(&A));
}
Fin qui penso che sia giusto.. Adesso arrivano gli errori nell'implementazione della funzione mat_transpose..
Ecco il file matrix.c

#include "matrix.h"

//N rappresenta il numero di righe, M il numero di colonne

struct matrix *mat_transpose( const struct matrix *mat)
{
       size_t i = 0;  // i = indice di riga
       size_t j = 0;  // j = indice di colonna
       struct matrix trasposta;

       for( i = 0; i < (mat->N); i++)
       {
             for( j = 0; j < (mat->M); j++)
             {
                   trasposta.N = mat->M;
                   trasposta.M = mat->N;
              }
        }
}
Allora il mio obiettivo è scambiare le righe con le colonne perché questa è la definizione di matrice trasposta. Solo che se faccio come ho fatto, non mi scambia niente.
Vorrei metterci gli indici i e j in questo modo..

(trasposta.N)[i] = (mat->M)[j];
(trasposta.M)[j] = (mat->N)[i];
Solo che il compilatore mi da un sacco di errori.. E quindi non penso sia la cosa corretta da fare..
Cioè non so come fare in modo di scambiare le righe con le colonne..
Ed essendoci anche la struct mi causa un po' di problemi..

Poi occorre mettere anche il return poiché la funzione deve ritornare una struct matrix..
Se metto però

return &trasposta;
Mi dà un warning che dice:
"Returning address of local variable or temporary "

Mi potreste aiutare??

Nell'attesa di una risposta vi ringrazio anticipatamente !

45 Risposte

  • Re: Esercizio sulle matrici

    Purtroppo non riesci a cavarci fuori i piedi perche' e' evidente che non hai minimamente compreso una serie di concetti fondamentali della programmazione in generale e del C in particolare.

    Non posso mettermi a spiegare tutto quello che ti serve: sono diversi capitoli del libro di testo!!!
    
    #if!defined MATRIX_H
    #define MATRIX_H
    
    #include <stdlib.h>
    struct matrix {
             size_t N, M;
             double *data;
    };
    
    extern struct matrix *mat_transpose (const struct matrix *mat);
    
    #endif
    
    Questo va bene
    
    #include "matrix.h"
    #include <stdio.h>
    
    int main(void)
    {
          struct matrix A;
          A.N = 2;
          A.M = 3;
          A.data = malloc(sizeof(double) * 6);
    
          A.data[0] = 1.0;
          A.data[1] = 2.0;
          A.data[2] = 3.0;
          A.data[3] = 4.0;
          A.data[4] = 5.0;
          A.data[5] = 6.0;
    
         [b]printf( "%d\n" , mat_transpose(&A)); [/b]
    }
    
    Questo e quasi giusto a parte la riga printf( "%d\n" , mat_transpose(&A));

    Ma se (codice tuo!!!) mat_transpose ritorna un puntatore ad una struttura matrix, che vuol dire quella printf?

    Cosi', assolutamente nulla!!! E' totalmente sbagliata!!!
    
        #include "matrix.h"
    
        //N rappresenta il numero di righe, M il numero di colonne
    
        struct matrix *mat_transpose( const struct matrix *mat)
        {
               size_t i = 0;  // i = indice di riga
               size_t j = 0;  // j = indice di colonna
               struct matrix trasposta;
    
               for( i = 0; i < (mat->N); i++)
               {
                     for( j = 0; j < (mat->M); j++)
                     {
                           [b]trasposta.N = mat->M;
                           trasposta.M = mat->N;[/b]
                      }
                }
        }
    
    
    Qui inizi correttamente, ma le righe trasposta.N = mat->M; trasposta.M = mat->N; sono utili, ma messe li non hanno minimamente senso.

    Inoltre, da questo codice, e' evidente che non hai capito i concetti fondamentali di allocazione della memoria, utilizzo dello stack (e allocazione nello stack), ritorno del valore di una funzione e di che cosa e' un vettore e come vi si accede.

    Nella prima parte del codice sembrava che avessi chiaro questi concetti, ma mi sa che e' solo un copia/incolla di codice gia' esistente, e non scritto con cognizione di causa.

    Solo per spiegare questi argomenti ci sono interi capitoli nei libri di testo.
    
    (trasposta.N)[i] = (mat->M)[j];
    (trasposta.M)[j] = (mat->N)[i];
    
    Ovviamente questo codice non ha minimamente senso, ma, ovviamente, e' una conseguenza delle lacune precedenti.

    E, conseguenza delle righe di codice sensa senso, hai corrspondenti errori generati dal compilatore!

    Quindi, la soluzione e': devi ricominciare a studiare dal primo capitolo del libro!
  • Re: Esercizio sulle matrici

    migliorabile ha scritto:


    
    #include "matrix.h"
    #include <stdio.h>
    
    int main(void)
    {
          struct matrix A;
          A.N = 2;
          A.M = 3;
          A.data = malloc(sizeof(double) * 6);
    
          A.data[0] = 1.0;
          A.data[1] = 2.0;
          A.data[2] = 3.0;
          A.data[3] = 4.0;
          A.data[4] = 5.0;
          A.data[5] = 6.0;
    
         [b]printf( "%d\n" , mat_transpose(&A)); [/b]
    }
    
    Questo e quasi giusto a parte la riga printf( "%d\n" , mat_transpose(&A));

    Ma se (codice tuo!!!) mat_transpose ritorna un puntatore ad una struttura matrix, che vuol dire quella printf?

    Cosi', assolutamente nulla!!! E' totalmente sbagliata!!!
    La printf posso anche toglierla ... Tanto non è richiesta dal problema.
    Era solo per me poichè volevo vedere quello che stampava... Ma visto che è totalmente sbagliata, la posso togliere.

    migliorabile ha scritto:


    
        #include "matrix.h"
    
        //N rappresenta il numero di righe, M il numero di colonne
    
        struct matrix *mat_transpose( const struct matrix *mat)
        {
               size_t i = 0;  // i = indice di riga
               size_t j = 0;  // j = indice di colonna
               struct matrix trasposta;
    
               for( i = 0; i < (mat->N); i++)
               {
                     for( j = 0; j < (mat->M); j++)
                     {
                           [b]trasposta.N = mat->M;
                           trasposta.M = mat->N;[/b]
                      }
                }
        }
    
    
    Qui inizi correttamente, ma le righe trasposta.N = mat->M; trasposta.M = mat->N; sono utili, ma messe li non hanno minimamente senso.

    Inoltre, da questo codice, e' evidente che non hai capito i concetti fondamentali di allocazione della memoria, utilizzo dello stack (e allocazione nello stack), ritorno del valore di una funzione e di che cosa e' un vettore e come vi si accede.

    Nella prima parte del codice sembrava che avessi chiaro questi concetti, ma mi sa che e' solo un copia/incolla di codice gia' esistente, e non scritto con cognizione di causa.

    Solo per spiegare questi argomenti ci sono interi capitoli nei libri di testo.
    Dove le posso mettere allora quelle due righe di codice se sono esatte?
    Lo ammetto che l'allocazione dinamica non l'ho compresa benissimo. Sui libri non ci si capisce niente. A lezione ho capito poco, ma qualcosa ho capito. Allora cosa bisogna fare? AMMAZZARSI?

    Lei ha perfettamente ragione. Riprenderò in mano il libro per l'ennesima volta e riguarderò quel poco che c'è sulle matrici.
    Grazie lo stesso. Mi rifarò vivo se avrò fatto qualcosa. Altrimenti mi toccherà andare a ripetizioni private.
    Cordiali saluti.
  • Re: Esercizio sulle matrici

    AMMAZARSI non e' una soluzione
    E' solo un modo per svicolare il problema

    Ricomincia con cose semplici:

    1) che cosa e' un vettore
    2) creare un vettore
    3) riempirlo con dei valori (11,12,13,14,....)
    4) stamparlo
    5) crea un nuovo vettore contenente gli stessi valori del vettore di partenza PIU' CENTO, e stampalo (quindi 111, 112, 113, 114, ...)

    Ora, una matrice puo' essere vista anche come un vettore: immagina di concatenare tutte le righe una all'altra. Immagina di inizializzarlo con i numeri 11,12,13 (prima riga), 21,22,23 (seconda riga),...

    Quindi trova una regola (ed e' banale, bastano + e *) che a partire dagli indici di riga e colonna della matrice, ti porta ad una posizione del vettore.

    Bene, a questo punto hai tutte le informazioni per implementare il tuo esercizio!

    Ci sarebbe ache altri modi di implementare la matrice: ma, al momento, sono piu' complicati.
  • Re: Esercizio sulle matrici

    migliorabile ha scritto:


    AMMAZARSI non e' una soluzione
    E' solo un modo per svicolare il problema

    Ricomincia con cose semplici:

    1) che cosa e' un vettore
    2) creare un vettore
    3) riempirlo con dei valori (11,12,13,14,....)
    4) stamparlo
    5) crea un nuovo vettore contenente gli stessi valori del vettore di partenza PIU' CENTO, e stampalo (quindi 111, 112, 113, 114, ...)

    Ora, una matrice puo' essere vista anche come un vettore: immagina di concatenare tutte le righe una all'altra. Immagina di inizializzarlo con i numeri 11,12,13 (prima riga), 21,22,23 (seconda riga),...

    Quindi trova una regola (ed e' banale, bastano + e *) che a partire dagli indici di riga e colonna della matrice, ti porta ad una posizione del vettore.

    Bene, a questo punto hai tutte le informazioni per implementare il tuo esercizio!

    Ci sarebbe ache altri modi di implementare la matrice: ma, al momento, sono piu' complicati.
    Ok.
    Allora ricominciamo :
    1) un vettore o array è una variabile in cui è possibile memorizzare più valori tutti dello stesso tipo.
    2)
    Un vettore si può creare così:
    int a[10];
    Questo è un vettore di grandezza 10, cioè un blocco costituito da 10 elementi consecutivi:
    a[0],a[1],a[2], ... , a[9].

    3)
    Riempiamo il vettore:
    int a[10] = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20};

    4)
    Stampiamo il vettore precedente :
    
    #include <stdio.h>
    int i = 0;
    
    for( i=0; i<10; i++)
    {
    printf( "%d ", a[i]);
    }
    
    5)
    Non saprei...
    Scusa la mia ignoranza. Vado a leggere sul libro se trovo qualcosa.
  • Re: Esercizio sulle matrici

    Ciao!
    Allora la trasposta ho capito come si fa..
    Ho preso in considerazione questo codice fatto molto bene che ho trovato su internet' che però non ha la struct per definire la matrice
    
    #define _CRT_SECURE_NO_WARNINGS
    #include <stdlib,h>
    #include <stdio.h>
    
    int main(void)
    {
         int **M; //matrice di input 
         int **MT; //matrice trasposta
         int n, m;
         int i, j;
         int val;
    
         printf( "Numero di righe di M: ");
         scanf( "%d", &n);
         printf( "Numero di colonne di M: ");
         scanf( "%d", &m);
    
         M = (int**)malloc(n * sizeof(int*)); //allochiamo M
         for ( i=0; i<n; i++)
               M[i] = (int*)malloc(m * sizeof(int));
    
         MT = (int**)malloc(m * sizeof(int*)); //allochiamo la trasposta
         for ( i=0; i<m; i++)
              MT[i] = (int*)malloc(n * sizeof(int));
       
         for ( i=0; i<n; i++)
              for ( j=0; j<m; j++)
              {
                   scanf ("%d", &val); //leggiamo i valori di M
                   M[i][j] = val;
              }
            
         for ( i=0; i<n; i++) //calcoliamo la matrice trasposta MT
               for ( j=0; j<m; j++)
                    MT[j][i] = M[i][j];
    
        for ( i=0; i<m; i++) // stampiamo la trasposta
        {
              for( j=0; j<n; j++)
              {
                    printf( "%d ", MT[i][j]);
              }
              printf( "\n");
        }
        return 0;
    }
    
    Io ho provato a seguirlo ma per l'allocazione dinamica con la struct mi causa dei problemi..
    Io ho provato a scrivere così ma è sbagliato..
    
    A.data = (double**)malloc(A.N * sizeof(double*));
    for (i = 0; i < A.N; i++)
          A.data[i] = (double*)malloc(A.M * sizeof(double));
    
    Mi dà purtroppo ben due errori..
    Come posso correggerlo??
  • Re: Esercizio sulle matrici

    C'è qualcuno ??
  • Re: Esercizio sulle matrici

    Mi dà purtroppo ben due errori..
    Possiamo sapere quali?
  • Re: Esercizio sulle matrici

    oregon ha scritto:


    Mi dà purtroppo ben due errori..
    Possiamo sapere quali?
    Si, scusami..
    Allora mi dà due errori nelle due righe di codice che ho inserito nel post precedente..
    Il primo dice che : "double* differs in levels of indirection from double**".
    Il secondo dice che: " cannot convert from double* to double".

    Come posso aggiustarlo?
  • Re: Esercizio sulle matrici

    In effetti, ti sta dicendo che il campo

    double *data;

    è un semplice puntatore a double e non un doppio puntatore

    double **

    come vorresti usarlo nelle righe di codice.

    Quindi dovrai scrivere

    double **data;
  • Re: Esercizio sulle matrici

    oregon ha scritto:


    In effetti, ti sta dicendo che il campo

    double *data;

    è un semplice puntatore a double e non un doppio puntatore

    double **

    come vorresti usarlo nelle righe di codice.

    Quindi dovrai scrivere

    double **data;
    Ok allora ho modificato come mi hai detto..
    Così :
    
    double **data = (double**)malloc(A.N. * sizeof(double*));
    for( i=0; i<A.N; i++)
          data[i] = (double*)malloc(A.M * sizeof(double));
    
    Ora però mi dà un altro errore ..
    Quando inserisco gli elementi della matrice mi dice che la variabile locale A usata non è inizializzata...
    Ma io all'inizio ho scritto che
    
    struct matrix A;
    
    L'errore mi appare qui:
    
    A.data[0] = 1.0;
    A.data[1] = 2.0;
    A.data[2] = 3.0;
    A.data[3] = 4.0;
    A.data[4] = 5.0;
    A.data[5] = 6.0;
    
    Come posso risolverlo ?
  • Re: Esercizio sulle matrici

    Quando ti ho detto di usare

    double **data;

    intendevo l'elemento della struttura non di usare un'altra variabile.
    E che avresti potuto poi scrivere
    
    A.data = (double**)malloc(A.N * sizeof(double*));
    for (i = 0; i < A.N; i++)
          A.data[i] = (double*)malloc(A.M * sizeof(double));
  • Re: Esercizio sulle matrici

    oregon ha scritto:


    Quando ti ho detto di usare

    double **data;

    intendevo l'elemento della struttura non di usare un'altra variabile.
    E che avresti potuto poi scrivere
    
    A.data = (double**)malloc(A.N * sizeof(double*));
    for (i = 0; i < A.N; i++)
          A.data[i] = (double*)malloc(A.M * sizeof(double));
    Continuo a non capire..
    Allora mi hai detto di usare l'elemento della struttura data.
    Quindi dovrei scrivere così :
    
    double **data;
    
    E poi:
    
    A.data = (double**)malloc(A.N. * sizeof(double*));
    for( i=0; i<A.N; i++)
         A.data[i] = (double*)malloc(A.M. * sizeof(double));
    
    Però mi da gli stessi due errori di prima..
  • Re: Esercizio sulle matrici

    Non può darti gli stessi errori se hai modificato la struttura... Controlla meglio e mostra nuovamente tutto il codice.
  • Re: Esercizio sulle matrici

    oregon ha scritto:


    Non può darti gli stessi errori se hai modificato la struttura... Controlla meglio e mostra nuovamente tutto il codice.
    Eh no scusami..
    Non posso modificare la struct perchè è nel testo dato dal mio prof..
    È per questo che non so come modificarlo..
Devi accedere o registrarti per scrivere nel forum
45 risposte