Newsgroup: it.comp.lang.c
Titolo: matrici

Sicuramente c'e' qualche cavolata, ma non riesco proprio a vederla.
Chi mi aiuta?
Grazie,
Ema
Il codice (prova.c)
-----------------------------------------------
01    #include <stdio.h>
02
03    void f(char * * m) {
04      int i, j;
05
06      for (i=0; i< 5; i++)
07        for (j=0; j<5; j++)
08          printf("%c ",m[i][j]);
09    }
10
11    int main(void) {
12      char p[5][5];
13      int i, j;
14
15      for (i=0; i< 5; i++)
16        for (j=0; j<5; j++)
17          p[i][j] = 'a' + (char) (i * j);
18
19      f(p);
20
21      return 0;
22    }
-----------------------------------------------
La compilazione:
-----------------------------------------------
# gcc -Wall prova.c
prova6.c: In function `main':
prova6.c:19: warning: passing arg 1 of `f' from incompatible pointer type
-----------------------------------------------
L'esecuzione:
-----------------------------------------------
# a.out
Segmentation fault
-----------------------------------------------

 prova6.c:19: warning: passing arg 1 of `f' from incompatible pointer type
Il compilatore avverte che il problema sta nella chiamata della funzione
f().
E il char** non permette al compilatore di conoscere la formattazione della
tua matrice.
Usa:
void f(char m[5][5[) {
e il gcc ti sorriderà :))
Se poi vuoi aggiungere un po' di eleganza, aggiungi un bel typedef. Provo a
scriverlo, scusa la formattazione del testo ma io appartengo alla vecchia
scuola di pensiero :))
#include <stdio.h>
typedef char MiaMatrice[5][5];
void f(MiaMatrice m)
{
  int i, j;
  for (i=0; i< 5; i++)
    for (j=0; j<5; j++)
      printf("%c ", m[i][j]);
}
int main(void)
{
  MiaMatrice p;
  int i, j;
  for (i=0; i<5; i++)
    for (j=0; j<5; j++)
      p[i][j] = 'a' + (char) (i * j);
  f(p);
  return 0;
}
Ciao,
Paolo.

 tua matrice.
Che intendi per  "la formattazione della tua matrice"?
Io credevo che il tipo
char * *
fosse compatibile col tipo
char [][]
...
Se la mia funzione f() fosse piu' generale e prendesse una matrice di cui
non so a priori le dimensioni, ma che mi vengono passate come parametri,
come dovrei fare? Detto in C (il codice seguente soffre del solito
problema):
Il codice (prova.c)
-----------------------------------------------
01    #include <stdio.h>
02
03    void f(char * * m, int lung, int larg) {
04      int i, j;
05
06      for (i=0; i< lung; i++)
07        for (j=0; j<larg; j++)
08          printf("%c ",m[i][j]);
09    }
10
11    int main(void) {
12      char p[5][5];
13      int i, j;
14
15      for (i=0; i< 5; i++)
16        for (j=0; j<5; j++)
17          p[i][j] = 'a' + (char) (i * j);
18
19      f(p,5,5);
20
21      return 0;
22    }
-----------------------------------------------
Grazie di nuovo.
Ciao,
Ema

problema):
Un'alternativa e':
#include <stdio.h>
void f (int *arr, int x, int y);
int main ()
 {
  int a[3][2] ={ { 1,2}, {3,4}, { 5,6} };
  f (&a[0][0], 3, 2);
 return 0;
 }
void f (int *arr, int x, int y)
 {
  int i, j;
   for (i=0; i < x; i++)
      for (j=0; j< y; j++)
	 printf ("%d",arr[i*y+j]);
 }

 }
Piccola spiegazione:
ricorda che le matrici in matematica vengono indicate con M x N (se
l'uso di x e y ti trae in inganno sostituiscile appunto con m ed n)
dove m e' il numero di righe ed n e' il numero di colonne.
Nella funzione all'array accedi tramite arr[i*y+j]. Ricorda che l'aria
di memoria e' contigua e la rappresentazione matriciale in 2
dimensioni e' solo una nostra rappresentazione della struttura, per
questa ragione, per ottenere la giusta cella di memoria del tuo array,
dovrai scrivere i*y+j
Spero di aver descritto abbastanza bene da farti capire come funziona
la cosa... se non l'ho fatto fammi sapere e "cerchero'" di darti una
risposta piu' chiara
Ciao,
Maurizio

 [...]
La spiegazione e' chiara, grazie, ma rimane il fatto che la soluzione che
hai fornito non mi sembra molto corretta dal punto di vista logico:
volendo lavorare con un oggetto matrice (a due dimensioni) vorrei accederci
come se fosse una matrice (ovvero con due indici).
La soluzione che hai fornito funziona, ma mi sembra un po' artificiosa. E'
come se lavorassi su interi e siccome so che gli interi sono fatti di 4
byte, per sommarli facessi la somma byte per byte, operazione che sa fare
benissimo la cpu al mio posto.
Lo stesso, l'accesso ad una matrice si fa alla fin fine con la formuletta
che hai detto te; pero' perche' me ne devo occupare io quando c'e' il
compilatore che lo sa fare benissimo?
Non so se mi sono spiegato.
Comunque non mi e' ancora chiara una cosa:
gentilmente tu mi hai fornito _un'alternativa_;
quindi non si puo' scrivere questa cosa qua senza ottenere degli errori?
--------------------
void f(char * *, int, int);
int main(void) {
char m[N][M];
...
f(m,N,M);
...
}
-------------------
Scusate se c'ho un po' di confusione.
Beh, grazie dell'interessamento.
Ciao,
Ema

-------------------
Bhe...un array bidimensionale non puo' essere passato come un array
normale... nella chiamata alla funzione dovrai sempre specificare
almeno la seconda dimensione (vado a memoria non lo faccio da una
vita...) facendo qualcosa del tipo 
f ( &m[][m] , n, m )
passare solo m non e' possibile xche' devi "addestrare" il compilatore
dicendo come e' fatto il tuo array multidimensionale...
In generale devi specificare, durante la chiamata della tua funzione,
tutte le dimensioni dell'array oltre la prima... se vuoi usarlo come
un array tradizionale nella tua funzione...altrimenti devi per forza
(o almeno io non conosco altri metodi) usarlo come ti ho mostrato io
in precedenza...
ecco xche' char ** e char [][] sono la stessa cosa ma al contempo sono
differenti...o meglio: sono differenti nel modo in cui vengono
usati...
Ciao, 
Maurizio
p.s. se hai altri dubbi chiedi pure... ora ho scritto velocemente la
mail xche' vado di fretta...ma se servono altre spiegazioni e con
calma ti rispondero' 

f ( &m[][m] , n, m )
[cut]
Ecco...ho cannato infatti, il modo corretto e' quello riportato nel
seguente esempio che contiene il paragone ai due metodi che ho
proposto
--------------------------inizio codice---------------------
#include <stdio.h>
void f (int *arr, int x, int y)   
 {
  int i, j;
   for (i=0; i < x; i++)
      for (j=0; j< y; j++)
	 printf ("%d",arr[i*y+j]);
 }
void f2 (int arr[][2], int x, int y)
 {
   int i,j;
 
   for (i=0; i < x ; i++ )
      for (j = 0; j < y ; j++ )
         printf ( "%d",arr[i][j] );      
 }
int main ()
 {
  int a[3][2] ={ { 1,2}, {3,4}, { 5,6} };
  f (&a[0][0], 3, 2);
  f2 (a, 3, 2);
 
  return 0;
 }
------------------------fine codice---------------------
Se gli altri conoscono metodi alternativi a quelli proposti qui da me
anche io saro' lieto di apprenderli ;o)
Ciao, 
Maurizio

 Maurizio
Ok, grazie della pazienza e di tutte le dritte.
Per fare cio' che mi serve dichiarero' un char **, e gestiro' l'allocazione
della memoria a mano.
Grazie di tutto.
Ciao,
Ema

 ha scritto nel messaggio
news:bbi4is$9p1cs$1...@ID-190851.news.dfncis.de...



Scusate se sono duro.
Credo di aver chiara l'aritmetica dei puntatori e le lievi differenze tra un
qualcosa dichiarato come puntatore o come array.
Pero', se non ho capito male cio' che avete detto (riguardo al fatto che se
ho un parametro dichiarato come puntatore il compilatore non e' in grado di
sapere come gestirlo sotto forma di array multidimensionale), il codice
seguente non dovrebbe funzionare perche' passo alla funzione "f" un "int *
*" senza riferimenti al fatto che sia una matrice (e in effetti non e'
dichiarato come matrice, ma come puntatore), ma poi lo uso come tale
("m[i][j]").
In realta' questo codice, a me, funziona.
Se avete voglia di commentare non puo' farmi che piacere...
Ciao e grazie.
Ema
-----------------------------------------------
#include <stdio.h>
#include <signal.h>
void f(int * * m, int max_i, int max_j) {
  int i, j;
  for (i=0; i< max_i; i++)
    for (j=0; j<max_j; j++)
      printf("%d ",m[i][j]);
}
int main(void) {
  int * * p;
  int i, j;
  p = (int * *) malloc(5 * sizeof(int *));
  for (i=0; i< 5; i++) {
    p[i] = (int *) malloc(5 * sizeof(int));
    for (j=0; j<5; j++)
      p[i][j] = 'a' * i + j;
  }
  f(p,5,5);
  return 0;
}
-----------------------------------------------

 In realta' questo codice, a me, funziona.
Ok, ma non è una matrice...
E' un array di puntatori e potrebbe benissimo essere geometricamente di
qualsiasi forma.
Infatti nel main definisci p come int** e lo passi poi alla funzione come
int**. E allora?
Cerchiamo di visualizzarlo, praticamente allochi (che brutto termine) sei
diverse "strisce" di memoria, ciascuna di cinque bytes.
Nella prima striscia inserisci tutti gli indirizzi, le "intestazioni" delle
altre cinque strisce.
In ciascuna delle altre cinque strisce inserisci i dati.
Nulla vieta tra l'altro di avere una delle strisce, supponiamo la terza, più
lunga delle altre.
Il fatto che poi accedi ai dati tramite la sintassi m[i][j], non significa
altro che utilizzare il puntatore m[i] incrementato di j.
In effetti hai giusto riprodotto la condizione citata dell'argomento char**
argv :)
Tornando indietro, il problema iniziale era dovuto al fatto che nel tuo
programma creavi una matrice p[5][5], cercavi di passarla ad una funzione
come puntatore di puntatore **m confidando nell'intercambiabilità delle due
cose, e volevi riutilizzarla poi come una matrice m[5][5].
Invece una matrice p[5][5] alloca 25 bytes consecutivi in memoria, è di
forma rettangolare e, come già detto, scrivere p[2][3] significa puntare
all'indirizzo di p[0][0] incrementato di 2*3+5.
Se tale di tale matrice chiedi per assurdo il valore p[2][6] (dico sei) sai
cosa ottieni, vero?
Il contenuto della cella numero sedici, ovvero p[3][1].
Se ripeti l'esperimento nel tuo codice, con quei puntatori, e chiedi m[2][6]
ottieni quasi sicuramente un errore di violazione d'accesso.
Ciao,
Paolo


OK, grazie 1K!
Ema