[C] Matrice ...

Area di discussione libera.

Moderatore: Staff

Regole del forum
1) Rispettare le idee altrui.
2) Evitare le offese dirette.
3) Leggere attentamente le risposte ricevute
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Rispondi
Avatar utente
DaD
Linux 2.x
Linux 2.x
Messaggi: 371
Iscritto il: mer 7 feb 2007, 18:19
Nome Cognome: Antonio Barra
Slackware: 13
Kernel: 3.0
Desktop: KDE 4
Distribuzione: Mac OS X
Contatta:

[C] Matrice ...

Messaggio 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 ...

Avatar utente
nicop
Linux 2.x
Linux 2.x
Messaggi: 232
Iscritto il: mer 18 gen 2006, 11:21
Nome Cognome: Nicola Palmieri
Slackware: 12.0
Kernel: 2.6.21.5
Desktop: Gnome Slacky
Località: San Martino In P. (Cb)
Contatta:

Re: [C] Matrice ...

Messaggio 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

Avatar utente
gallows
Staff
Staff
Messaggi: 3471
Iscritto il: lun 20 set 2004, 0:00
Desktop: cwm
Distribuzione: OpenBSD
Località: ~/
Contatta:

Messaggio 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.

Avatar utente
DaD
Linux 2.x
Linux 2.x
Messaggi: 371
Iscritto il: mer 7 feb 2007, 18:19
Nome Cognome: Antonio Barra
Slackware: 13
Kernel: 3.0
Desktop: KDE 4
Distribuzione: Mac OS X
Contatta:

Messaggio 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.

Avatar utente
absinthe
Iper Master
Iper Master
Messaggi: 2354
Iscritto il: dom 15 mag 2005, 0:00
Nome Cognome: Matteo Nunziati
Slackware: 12.1 - defunct
Kernel: 2.6.32-5-amd64
Desktop: gnome
Distribuzione: debian squeeze
Località: Prato
Contatta:

Messaggio 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!
Ultima modifica di absinthe il ven 30 nov 2007, 9:43, modificato 1 volta in totale.

Avatar utente
gallows
Staff
Staff
Messaggi: 3471
Iscritto il: lun 20 set 2004, 0:00
Desktop: cwm
Distribuzione: OpenBSD
Località: ~/
Contatta:

Messaggio 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).

Avatar utente
DaD
Linux 2.x
Linux 2.x
Messaggi: 371
Iscritto il: mer 7 feb 2007, 18:19
Nome Cognome: Antonio Barra
Slackware: 13
Kernel: 3.0
Desktop: KDE 4
Distribuzione: Mac OS X
Contatta:

Messaggio 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

Avatar utente
corrado
Linux 2.x
Linux 2.x
Messaggi: 218
Iscritto il: dom 13 feb 2005, 0:00
Nome Cognome: corrado
Slackware: current
Kernel: 2.6.29.6-smp
Desktop: kde-4
Località: isola del liri
Contatta:

Re: [C] Matrice ...

Messaggio 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

Avatar utente
lamarozzo
Linux 3.x
Linux 3.x
Messaggi: 732
Iscritto il: gio 14 lug 2005, 0:00
Desktop: xfce
Distribuzione: archlinux
Località: Roma

Messaggio 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

Avatar utente
phobos3576
Staff
Staff
Messaggi: 2980
Iscritto il: dom 17 apr 2005, 0:00
Slackware: 13.1
Kernel: 2.6.37-smp
Desktop: KDE 4.5.3

Messaggio 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;
}

Avatar utente
lamarozzo
Linux 3.x
Linux 3.x
Messaggi: 732
Iscritto il: gio 14 lug 2005, 0:00
Desktop: xfce
Distribuzione: archlinux
Località: Roma

Messaggio 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:

Avatar utente
DaD
Linux 2.x
Linux 2.x
Messaggi: 371
Iscritto il: mer 7 feb 2007, 18:19
Nome Cognome: Antonio Barra
Slackware: 13
Kernel: 3.0
Desktop: KDE 4
Distribuzione: Mac OS X
Contatta:

Messaggio 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?

Avatar utente
phobos3576
Staff
Staff
Messaggi: 2980
Iscritto il: dom 17 apr 2005, 0:00
Slackware: 13.1
Kernel: 2.6.37-smp
Desktop: KDE 4.5.3

Messaggio 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.

Rispondi