Pagina 1 di 1

[C] Matrice ...

Inviato: gio 29 nov 2007, 20:15
da DaD
Non riesco a capire perchè questo codice mi restituisca un warring.
Il codice è questo;

Codice: Seleziona tutto

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

int main(void){
   int a[2][3] = {{2, 3, 4},
                  {3, 4, 5}};
   printf("L'elemento massimo è %d\n", max_matrice(a, 2, 3));
   getchar();
   return 0;
}

/* matrix.h */
int max_matrice(int **a, int n, int m){
   int i, j, max = a[0][0];
   for(i = 0; i <= n; i++){
      for(j = 0; j <= m; j++){
          if(a[i][j] > max)
             max = a[i][j];
      }
   }
}
Il warring è questo;

Codice: Seleziona tutto

warning: passing argument 1 of 'max_matrice' from incompatible pointer type
In pratica da quello che ho capito sbaglio a passargli la matrice, ma non riesco a capire l'errore dove sia ...

Re: [C] Matrice ...

Inviato: gio 29 nov 2007, 20:23
da nicop
DaD ha scritto:Non riesco a capire perchè questo codice mi restituisca un warring.
Il codice è questo;

Codice: Seleziona tutto

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

int main(void){
   int a[2][3] = {{2, 3, 4},
                  {3, 4, 5}};
   printf("L'elemento massimo è %d\n", max_matrice(a, 2, 3));
   getchar();
   return 0;
}

/* matrix.h */
int max_matrice(int **a, int n, int m){
   int i, j, max = a[0][0];
   for(i = 0; i <= n; i++){
      for(j = 0; j <= m; j++){
          if(a[i][j] > max)
             max = a[i][j];
      }
   }
}
Il warring è questo;

Codice: Seleziona tutto

warning: passing argument 1 of 'max_matrice' from incompatible pointer type
In pratica da quello che ho capito sbaglio a passargli la matrice, ma non riesco a capire l'errore dove sia ...
Dad non ne sono tanto sicuro,ma se non ricordo male usando questo dichiarazione

Codice: Seleziona tutto

int **a
gli passi come parametro un puntatore ad un puntatore.Prova semplicemte a passare come parametro il puntatore,ovvero così

Codice: Seleziona tutto

int *a
spero di non aver detto una cavolata...
ciaoo

Inviato: gio 29 nov 2007, 20:33
da gallows
In C non puoi convertire un T[][] in T**, se devi implementare una matrice ti consiglio una struttura opaca, che peraltro ti permette una facile gestione degli errori.

Inviato: gio 29 nov 2007, 20:46
da DaD
gallows ha scritto:In C non puoi convertire un T[][] in T**, se devi implementare una matrice ti consiglio una struttura opaca, che peraltro ti permette una facile gestione degli errori.
Scusa la mia ignoranza gallows ma cosa intendi per "struttura opaca"?
Intendi dire di inzializzare la matrice in questo modo: a[n][m]?
nicop ha scritto: Dad non ne sono tanto sicuro,ma se non ricordo male usando questo dichiarazione

Codice: Seleziona tutto

int **a
gli passi come parametro un puntatore ad un puntatore.Prova semplicemte a passare come parametro il puntatore,ovvero così

Codice: Seleziona tutto

int *a
spero di non aver detto una cavolata...
ciaoo
Nicop mi sai che hai ragione, infatti ripassando gli appunti ho visto che in pratica in quel modo posso gestire array di array, ma non degli array 2D classici.

Inviato: gio 29 nov 2007, 21:42
da absinthe
devi al minimo allocare dinamicamente la matrice se la vuoi usare così...

roba tipo:

Codice: Seleziona tutto

const int righe=2;
const int colonne=3;
int **a=NULL;

a = (int*) malloc(sizeof(int)*righe);
int r=0;
for (r=0; r<righe; r++) 
    a[r] = (int) malloc(sizeof(int)*colonne); 
a sto punto però non mi ricordo se è più velocepassare l'indirizzo dell'array....

Codice: Seleziona tutto

int max_matrice(int ***a_ptr, int n, int m);
ad ogni modo potresti farti una struttura tipo:

Codice: Seleziona tutto

typedef _matrix {
int r; /*righe*/
int c; /*colonne*/
int **data; /*dati*/

//... altre cose utili
} matrix;

int max_matrice(matrix *prt_to_a_matrix_struct);

int max_matrice (matrix *my_ptr) {
int max =-1 /*scegli un init migliore...*/

int i, j;
for (i=0; i< my_ptr->r; i++)
    for (j=0; j< my_ptr->c; j++)
        if(my_ptr->data[i][j] > max)
            max = my_ptr->data[i][j]

return max;
}
per inciso le librerie industriali implementano le matrici in un unica riga per velocizzare le operazioni di allocazione e calcolo...

M

PS: l'ho fatta a naso potrebbero esserci errori!

Inviato: gio 29 nov 2007, 22:13
da gallows
DaD ha scritto:
gallows ha scritto:In C non puoi convertire un T[][] in T**, se devi implementare una matrice ti consiglio una struttura opaca, che peraltro ti permette una facile gestione degli errori.
Scusa la mia ignoranza gallows ma cosa intendi per "struttura opaca"?
Intendi dire di inzializzare la matrice in questo modo: a[n][m]?
Intendo ad esempio un'implementazione come questa:

Codice: Seleziona tutto

typedef unsigned int   uint;
typedef int            mx_t;

typedef struct _Matrix Matrix;

struct _Matrix {
    mx_t*  data;
    uint   cols;
    uint   rows;
};

/* con una libreria come la seguente: */
/* (codice non testato) */

Matrix* matrix_init(uint rows, uint cols)
{
    Matrix* mx = malloc( sizeof(Matrix) );

    if ( rows && cols )
        mx->data = malloc( rows * cols * sizeof(mx_t) );
    else
        mx->data = NULL;

    mx->rows = rows;
    mx->cols = cols;

    return mx;
}

void matrix_destroy(Matrix* mx)
{
    free( mx->data );
    free( mx );
}

mx_t matrix_get_cell(const Matrix* mx, uint i, uint j)
{
    if (i >= mx->rows || j >= mx->cols)
        /* gestisci l'errore */

    return mx->data[mx->cols * i + j];
}

int matrix_set_cell(Matrix* mx, uint i, uint j, mx_t v)
{
    if (i >= mx->rows || j >= mx->cols)
        return -1;

    mx->data[mx->cols * i + j] = v;

    return 0;
}
Un metodo ancora migliore sarebbe usare un void* invece dell'ingenuo mx_t, in modo da poter usare, con la stessa libreria, matrici di tipi diversi (ricorda che void* non si può dereferenziare, devi lavorare direttamente con la memoria).

Inviato: gio 29 nov 2007, 22:47
da DaD
Grazie delle delucidazioni, stavo leggendo proprio ora sul libro che per utilizzare in quel modo una matrice devo per forza di cosa allocare lo spazio in memoria dinamicamente per quest'ultima.

@gallows, vedo di studiarmi il tuo codice che mi sembra abbastanza completo, naturalmente stai parlando con un neofita del c eh :D

Re: [C] Matrice ...

Inviato: gio 29 nov 2007, 22:53
da corrado
DaD ha scritto:Non riesco a capire perchè questo codice mi restituisca un warring.
Il codice è questo;

Codice: Seleziona tutto

/* matrix.h */
int max_matrice(int **a, int n, int m){
   int i, j, max = a[0][0];
   for(i = 0; i <= n; i++){
      for(j = 0; j <= m; j++){
          if(a[i][j] > max)
             max = a[i][j];
      }
   }
}
Una curiosità... ma nella scansione delle righe e delle colonne non dovresti mettere come condizione di uscita solo il "<" (minore)?

Saluti
corrado

Inviato: ven 30 nov 2007, 0:12
da lamarozzo
Sei vuoi passare un array bidimensionale ad una funzione basta fare

Codice: Seleziona tutto

//dichiarazione
void funzione (int *matrice[2]);

int main()
{
  int a[3][2];
  funzione(a);
}  

Ricordati che nella lista di parametri devi sempre dichiarare la grandezza (in questo caso 2) dell'ultima dimensione dell'array.

Gli array multidimensionali sono la soluzione più comoda se ne conosci le dimensioni al tempo di compilazione. Altrimenti devi ricorrere all'allocazione dinamica. Se con la matrice in questione devi fare operazioni intensive (calcoli) devi fare in modo che occupi uno spazio contiguo in memoria.

Ad esempio seguendo il codice di Gallows. Soltanto che io eviterei di implementare le funzioni set e get per accedere alla matrice per non appesantire troppo il programma.

Gallows suggeriva di usare i void* per scrivere codice generico. Il problema di quella soluzione, a mio avviso, è la type safety. C'è un'altra soluzione: usare le macro del preprocessore. I fortunati utilizzatori del c++ hanno invece i potentissimi template.

A presto.

P.S. Corrado ha ragione

Inviato: ven 30 nov 2007, 1:41
da phobos3576
lamarozzo ha scritto:Sei vuoi passare un array bidimensionale ad una funzione basta fare

Codice: Seleziona tutto

//dichiarazione
void funzione (int *matrice[2]);

int main()
{
  int a[3][2];
  funzione(a);
}  

Ricordati che nella lista di parametri devi sempre dichiarare la grandezza (in questo caso 2) dell'ultima dimensione dell'array.

Gli array multidimensionali sono la soluzione più comoda se ne conosci le dimensioni al tempo di compilazione. Altrimenti devi ricorrere all'allocazione dinamica. Se con la matrice in questione devi fare operazioni intensive (calcoli) devi fare in modo che occupi uno spazio contiguo in memoria.

Ad esempio seguendo il codice di Gallows. Soltanto che io eviterei di implementare le funzioni set e get per accedere alla matrice per non appesantire troppo il programma.

Gallows suggeriva di usare i void* per scrivere codice generico. Il problema di quella soluzione, a mio avviso, è la type safety. C'è un'altra soluzione: usare le macro del preprocessore. I fortunati utilizzatori del c++ hanno invece i potentissimi template.

A presto.

P.S. Corrado ha ragione
Lamarozzo ... attenzione alla sintassi ...

Sul passaggio di vettori bidimensionali come argomenti di funzioni hai ragione; un vettore bidimensionale in C è un "vettore di vettori".
Il nome di un vettore bidimensionale è quindi l'indirizzo del suo primo elemento, che è a sua volta un vettore; proprio per questo motivo il C deve conoscere la seconda dimensione del vettore (in sostanza, il C deve per forza conoscere la dimensione di ogni elemento del vettore).

Se io scrivo:

Codice: Seleziona tutto

int   myvect[3][4] = {{1, 2, 3, 4}, {3, 2, 0, 1}, {5, 8, 1, 1}};
sto definendo un vettore di 3 elementi dove ogni elemento è un blocco da (4*sizeof(int)) byte.

E' sbagliata invece la sintassi::

Codice: Seleziona tutto

int max_matrice(int **a, int n, int m);
(puntatore ad un puntatore ad int)

ed anche:

Codice: Seleziona tutto

int maxmatrice(int *a[], int n, int m);
(vettore di ??? puntatori a int)

ed anche:

Codice: Seleziona tutto

int max_matrice(int *a[4], int n, int m);
Infatti:

Codice: Seleziona tutto

int *a[4]
significa: "vettore di 4 puntatori a int

La sintassi corretta è:

Codice: Seleziona tutto

(*a)[4]
che significa: "puntatore ad un vettore di int

Quindi il prototipo corretto per max_matrice è:

Codice: Seleziona tutto

int max_matrice(int (*a)[3], int n, int m);
P.S. A parte questo, il codice scritto da DaD per calcolare il valore massimo mi sembra sbagliato; la versione giusta dovrebbe essere:

Codice: Seleziona tutto

/* matrix.h */
int max_matrice(int (*a)[3], int n, int m){
	int i, j, max = a[0][0];
	for(i = 0; i < n; i++){
		for(j = 0; j < m; j++){
			if(a[i][j] > max)
				max = a[i][j];
		}
	}
	return max;
}

Inviato: ven 30 nov 2007, 10:08
da lamarozzo
phobos3576 ha scritto: Lamarozzo ... attenzione alla sintassi ...
Sì hai ragione, è questione di precedenza dell'operatore di accesso agli array su quello di deferenziazione. E' stata una svista causata dall'ora tarda e dal fatto che quando ho risposto stavo scrivendo uno script Python e non ero tarato sulle sottigliezze del C :lol:

Inviato: ven 30 nov 2007, 22:13
da DaD
phobos3576 ha scritto:P.S. A parte questo, il codice scritto da DaD per calcolare il valore massimo mi sembra sbagliato; la versione giusta dovrebbe essere:

Codice: Seleziona tutto

/* matrix.h */
int max_matrice(int (*a)[3], int n, int m){
	int i, j, max = a[0][0];
	for(i = 0; i < n; i++){
		for(j = 0; j < m; j++){
			if(a[i][j] > max)
				max = a[i][j];
		}
	}
	return max;
}
Si ma int m, a questo punto non serve visto che la matrice sarà sempre N X 3, giusto?

Inviato: sab 1 dic 2007, 0:05
da phobos3576
DaD ha scritto:Si ma int m, a questo punto non serve visto che la matrice sarà sempre N X 3, giusto?
Certo, visto che devi gestire un vettore dove ogni suo elemento è un altro vettore da 3 int.
Quindi, all'interno di max_matrice puoi sostituire m con il valore 3.

Se, invece, vuoi gestire matrici bidimensionali con numero variabile di righe e colonne, allora ti conviene ricorrere all'allocazione dinamica della memoria, come ti hanno già suggerito altri.