Newsgroup: it.comp.lang.c
Titolo: Allocazione e matrici !

Vorrei proporvi un quesito.
Devo realizzare un programma che carica il contenuto di un file in una
matrice.
Supponiamo che il contenuto del file sia per esempio :
 5  5   10  11  5   4   23
        98  15  12  18  19
          3   8   9  56    48
         52  14  16  24  77
         51  43  85  91   2
I primi due record rappresentano la dimensione della matrice , i successivi
gli elementi della matrice che sono interi.
Avevo pensato di realizzare una funzione "carica" che al suo inteno ne
contiene altre 3 : "apri" (che apre il file in lettura),"indici" (che carica
i primi due record nelle variabili maxrighe e maxcolonne con fscanf) ed
infine "elementi" ( che dovrebbe realizzare la vera e propria matrice).
Il mio problema si presenta proprio in questo ultimo punto .
Dovendo infatti accedere alla matrice da punti diversi del programma si pone
il problema di come dichiararla.
So benissimo che la via più facile è quella di dichiarare una matrice
sovradimensionata , ma sappiamo tutti che questo non è nè elegante nè
efficiente.
Mi chiedevo quindi come si facesse ad allocare lo spazio "al volo " (per
così dire dinamicamente)  per una matrice.
E come posso fare poi ad accedervi dai vari punti del programma ?
Grazie a tutti per le risposte.


  Esistono millanta e millanta modi di fare cio` e molti di questi li
avresti potuti direttamente qpprendere dalla lettura del gruppo,
dacche` questa e` una delle domande piu` frequentemente poste cui
l'inesausto Laforgia non manca mai di rispondere.
  L'allocazione al "volo", o dinamicamente, per cosi` dire, *e`* la
soluzione del tuo problema, tant'e` che come ipotesi fornisci
addirittura le dimensioni della matrice da leggere.
  La soluzione classica per l'implementazione bidimensionale e`
	int **matrix=malloc(M*sizeof(int *));
	for(i=0;i<N;i++) *(matrix+i)=malloc(N*sizeof(int));
dove M ed N sono le dimensioni della matrice stessa. Ma nulla ti vieta
implementazioni diverse, come quella monodimensionale:
	typedef struct tag_matrix {
		int rows,cols;
		int *elements;
	} matrix_t;
	matrix_t matrix;
	matrix.rows=M;
	matrix.cols=N;
	matrix.elements=malloc(N*M*sizeof(int));
che, se da un lato di consente di tenere sempre a portata di mano le
dimensioni della matrice, da un altro ti costringe a scrivere le
funzioni di accesso agli elementi.
  Implementazioni piu` complesse, per esempio mediante liste
collegate, ti consento di risparmiare spazio nel caso di matrici
sparse, per le matrici diagonali o triangolari puoi modificare
all'uopo l'implementazione monodimensionale, ecc.
 
--
Alla prossima,
Marco

 dove M ed N sono le dimensioni della matrice stessa.
Mi sorge però un dubbio : come faccio in questo caso ad accedere ai singoli
elementi della matrice.
Grazie ancora per le tue risposte.

 elementi della matrice.
  matrix[i][j];
--
Alla prossima,
Marco

 elementi della matrice.
Come se si trattasse di un normale array.
Es:
matrix[0][0] e' il primo elemento, matrix[0][1] il secondo e cosi' via.
-- 
"Windows 95 is a 32-bit shell for a 16-bit extension to an 8-bit
operating system designed for a 4-bit microprocessor by a 2-bit
company that can't stand one bit of competition."
La mia (penosa, per ora) homepage: 
http://digilander.iol.it/burton666



 ha scritto nel messaggio
news:bUxB7.87661$1H1.9...@news.infostrada.it...


che avete proposto voi ?
Che la seconda e' corretta, la prima e' da evitare.
In C, visto il debole controllo dei tipi, e' sempre bene
evitare di castare il valore di ritorno di malloc.
Il cast era necessario nel C pre-ANSI, per intenderci,
quello trattato nel K&R I versione.
Con l'approvazione dello standard C89 si e' stabilito che il
cast da puntatore void a qualsiasi altro tipo di puntatore
e' automatico in C.
-- 
The Follet

 voi ) .
La funzione malloc ritorna un puntatore a void; questo implicherebbe il
doverlo "castare" (cioè doverlo convertire) ad un puntatore di tipo
richiesto, ed è ciò che viene fatto con (char *) malloc(...), che casta
il tipo ritornato in un puntatore a char. In realtà, il casting viene
fatto in automatico dal compilatore quando assegni il valore di ritorno
della funzione ad un puntatore di altro tipo.
Ciao,
Cecco

 che avete proposto voi ?
Questa è un'aggiunta alle altre risposte; quindi spero tu le
abbia lette. In realtà, chi usa la prima forma non lo fa per
compatibilità con il C più antico (K&R ver. 1) ma per
compatibilità col C++; si dice che il C sia un sottoinsieme
del C++, ma se vuoi che sia veramente così devi usare la
prima forma accettata in C++ e non la seconda, che non lo è.
Molti programmatori C rifiutano la compatibilità col C++,
specie Andrea La Forgia. Io personalmente non sono
d'accordo, ma è vero che lasciare che il cast avvenga in
automatico permette di individuare alcuni errori (cast
impliciti tra puntatori di cui nessuno dei due è void *, o
cast tra puntatori e non puntatori) in compilazione, mentre
si perde questa possibilità col il casting esplicito (forma
1).
Ciao
--
Paolo Giarrusso

Molti programmatori C rifiutano la compatibilità col C++,
Non e' questione di rifiuto della compatibilita' col C++.
Compilando in C++ si e' protetti dal compilatore, compilando
in C, no.  Se si vuol mantenere la compatibilita' del C++ e'
bene compilare in modalita' C++ e non in modalita' C.
Se si programma in C++ si e' obbligati ad usare il cast,
mentre se lo si fa in C non e' obbligatorio.
Questa non obbligatorieta' potrebbe condurre a dei problemi.
Programmare in C significa compilare secondo lo standard C e
non quello C++, adottare lo stile del C (ovvero la mancanza
del cast) e fare molta piu' attenzione che nel C++.
-- 
The Follet