View Full Version : doppio array di puntatori
marco.gheza
26-07-2007, 08:02
I need some help!!
Costruisco una matrice quadrata di puntatori allocando la memoria in questo modo (dove dim=dimensione asse x e anche asse y):
float **matrix;
matrix=(float **)malloc((dim*dim*sizeof(float)));
for(m=0;m<dim;m++)
{
matrix[m] = (float *) malloc(dim*sizeof(float));
}
Poi, questa matrice dovrei passarla ad un puntatore (float **matrix) in una struct chiamata LSU.
Però, con questo comando:
LSU[i].matrix=&matrix[0][0]
che funziona bene con gli array unidimensionali, non riesco! Mi dà questo warning:
assignment from incompatible pointer type.
Qualcuno ha qualche suggeriemtno gentilmente??
sottovento
26-07-2007, 10:54
Ciao,
prima questione: perche' la prima allocazione e':
matrix=(float **)malloc((dim*dim*sizeof(float)));
a cui fai poi seguire l'allocazione di ogni riga? Se fai seguire la singola riga di allocazione, allora questa puo' avere semplicemente dimensione pari a dim, no?
Oppure "gestisci la bidimensionalita'" tu, allocando un semplice array dim*dim e facendo matrix[riga * dim + colonna].
In secondo luogo, quando scrivi &matrix[0][0], ottieni semplicemente un puntatore ad un float (non un puntatore a puntatore a float), pertanto il warning visualizzato e' corretto.
Domanda: invece di complicarti la vita, non e' possibile usare
LSU[i].matrix=matrix
?
mapomapo
26-07-2007, 11:12
l'allocazione della matrice funziona in questa maniera:
-allochi un vettore colonna di puntatori;
-con un ciclo for fai eseguire le malloc sul vettore colonna;
quindi le istruzioni diventano:
#define DIM 5;
#include <stdio.h>
#include <stdlib.h>
void alloca_matrice(float **, int);
void main()
{
float **matrice;
alloca_matrice(matrice, DIM);
//A questo punto puoi creare una routine che assegni "matrice" (è già float **!!!) alla tua struct LSU
}
void alloca_matrice(float **matrix, int A)
{
int i;
matrix = malloc(A*sizeof(float *)); //Alloco il vettore colonna
for(i=0;i<A;i++) //Per ogni elemento del vettore alloco la riga
matrix[i] = malloc(A*sizeof(float));
}
Per quanto riguarda la malloc non è necessario fare il casting esplicito in C.
Per ogni funzione alloca è opportuno definire una dealloca che operi in senso inverso, si intende.
Puoi provare a giochicchiare ampliando lo stralcio di codice che ho scritto.
Vito
marco.gheza
26-07-2007, 13:25
X SOTTOVENTO
...niente!!
La malloc ora funziona, però quando si tratta di passare la matrice bidimensionale alla struct, non lo fa. La lettura del file è giusta e la matrice bidimensionale viene popolata correttamente. Però, non appena scrivo
LSU.matrix[i]=matrix;
poi nel doppio array di puntatori non riesce più a leggere i dati letti e non stampa più la matrice.
marco.gheza
26-07-2007, 13:45
scusa, LSU[i].matrix.matrix. Ho sbagliato a scrivere....
Boh, non funziona...
sottovento
26-07-2007, 15:30
Mi viene un dubbio: come hai definito LSU[i].matrix.matrix?
E' un doppio puntatore a float? Oppure la tua intenzione e' quella di registrare riga x riga?
marco.gheza
26-07-2007, 15:36
io ho una struct fatta così:
struct LSU
{
int LSU_id;
int number_of_cluster;
int *cluster;
float **matrix;
};
poi creo
float **trans_matrix;
trans_matrix=malloc(dim*sizeof(float*));
in questa matrice doppia, salvo dei numeri float.
Poi voglio passare a matrix (nella struct) la matrice creata tramite il comando che mi hai suggerito tu:
LSU[i].matrix=trans_matrix
dove i indica l'i-esima struct creata. Alla fine dovrei avere alcune strutture LSU ciascuna con la sua matrice quadrata.
mapomapo
26-07-2007, 18:49
hai dichiarato il vettore di struct nel main??
potresti postare il codice intero della parte?
ciò che hai scritto mi sembra giusto!
Vito
marco.gheza
26-07-2007, 19:01
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
float **trans_matrix;
struct LSU
{
int LSU_id; // numero sequenziale dell'LSU considerata
int number_of_cluster; // numero di cluster presenti nell'LSU considerata
int *cluster; // elenco di cluster effettivamente presenti nell'LSU considerata
float **matrix; // matrice delle transizioni
};
/*
* questo programma legge un file testo contenente la suddivisione in cluster del filmato,
* ponendo le varie voci in una struct chiamata 'cluster'
*/
int main(int argc, const char *argv[])
{
FILE *matrix;
if (argc!=2) // check if number of argument is correct
{
printf("\n Usage: ./read_LSU FILE_IN.view#LSUmat\n");
exit (1);
}
matrix=fopen(argv[1],"r"); // read file .txt which describes each shot
if (matrix==NULL){
printf("Error while opening file FILE_IN.view#LSUmat!\n");
exit(1);
}
struct LSU *array_LSU; // alla posizione i dell'array ci sarà una struct relativa ad un cluster
int number_of_LSU, ii=0, jj=0, kk, ll, mx;
int xx, yy;
int temp_num_cluster;
fscanf(matrix, "%d\n", &number_of_LSU);
array_LSU=malloc(number_of_LSU*sizeof(struct LSU));
while((fscanf(matrix, "%d", &(array_LSU[ii].LSU_id))) != EOF)
{
fscanf(matrix, "%d", &(array_LSU[ii].number_of_cluster));
int *array_cluster;
array_cluster=malloc(array_LSU[ii].number_of_cluster*sizeof(int));
for(kk=0; kk < array_LSU[ii].number_of_cluster; kk++)
fscanf(matrix, "%d",&array_cluster[kk]);
array_LSU[ii].cluster=&array_cluster[0];
temp_num_cluster = array_LSU[ii].number_of_cluster;
/***********************************************************************************
leggo la MATRICE DELLE TRANSIZIONI e trasferisco i dati nella struct
***********************************************************************************/
trans_matrix=malloc(temp_num_cluster*sizeof(float*));
for(mx=0;mx<temp_num_cluster;mx++)
trans_matrix[mx] = malloc(temp_num_cluster*sizeof(float));
for(yy=0; yy<temp_num_cluster; yy++)
{
for(xx=0; xx<temp_num_cluster; xx++)
{
fscanf(matrix, "%f", &trans_matrix[xx][yy]);
}
}
array_LSU[ii].matrix=trans_matrix;
ii++;
}
return 0;
}
mapomapo
26-07-2007, 22:41
non ho letto attentamente il codice...ma la prima cosa che mi viene in mente di dirti è un consiglio: cambia il nome al file pointer...
Vito
sottovento
27-07-2007, 06:35
Suona davvero strano...
Prima di tutto, sei davvero sicuro che quella sia la linea "incriminata"?
Se, per esempio, la commenti, riesci a compilare senza il warning in questione?
Beh, per risolvere il warning potresti usare un cast, del tipo:
array_LSU[ii].matrix=(float **)trans_matrix;
Mi sa che questo fa sparire il warning. Pero' il problema e' capire il motivo di questo warning. Se lo facciamo sparire magari nascondiamo il problema, invece che risolverlo.
Ho controllato il codice ed e' tutto OK. Purtroppo non ho il tempo di farlo girare. Mi sento pero' di darti un consiglio: verifica sempre, dopo la malloc() che la memoria sia stata allocata correttamente (se non lo e', il puntatore sara' a NULL). Metti un piccolo controllo, quanto meno con un messaggio di errore ed un exit() nel caso che la malloc() ritorni NULL, per evitare di perdere le ore a cercare un problema inesistente in caso di errore in allocazione.
sottovento
27-07-2007, 06:41
Ciao,
mi sono preso un minuto di tempo ed ho compilato il tuo codice (usando Visual C++).
Risultato: non mi compare il warning che hai riportato. In compenso il compilatore mi avverte che la malloc() ritorna un puntatore a void*, quindi devo fare il cast del valore ritornato al tipo di destinazione (cioe' float*, float** oppure LSU*).
A parte questo, si compila tutto correttamente e senza altri warning
Spero ti possa essere utile
marco.gheza
27-07-2007, 08:05
Ti mando in allegato il file testo che dovrebbe leggere. Ho messo solo 2 matrici per renderlo + semplice.
Quando legge questo file, la matrice che uso come temporanea, riceve giusta nelle sue posizioni i numeri; poi, se provo a trasferire questa matriuce nel doppio array di puntatori e poi rifaccio stampare questo array, mi dà segmentation fault:
0.00 0.50 0.50 0.00 0.00
0.00 0.20 0.20 0.20 0.40
0.33 0.33 0.33 0.00 0.00
0.00 0.00 0.00 0.00 1.00
0.00 1.00 0.00 0.00 0.00
Segmentation fault
Non so davvero + che fare. Perchè non è un problema di compilazione a questo punto.........
sottovento
27-07-2007, 08:12
Ok, ci do' un'occhiata piu' tardi. Spero di esserti utile
trallallero
27-07-2007, 09:04
e´ di solito buona norma mettere qualche printf in giro per capire cosa sta succedendo. Io l´ho provato e funziona. Il file di input l´ho chiamato xxx.dat e ho aggiunto qualche printf. Per il resto non ho cambiato niente.
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
float **trans_matrix;
struct LSU
{
int LSU_id; // numero sequenziale dell'LSU considerata
int number_of_cluster; // numero di cluster presenti nell'LSU considerata
int *cluster; // elenco di cluster effettivamente presenti nell'LSU considerata
float **matrix; // matrice delle transizioni
};
/*
* questo programma legge un file testo contenente la suddivisione in cluster del filmato,
* ponendo le varie voci in una struct chiamata 'cluster'
*/
int main(int argc, const char *argv[])
{
FILE *matrix;
if (argc!=2) // check if number of argument is correct
{
printf("\n Usage: ./read_LSU FILE_IN.view#LSUmat\n");
exit (1);
}
matrix=fopen(argv[1],"r"); // read file .txt which describes each shot
if (matrix==NULL){
printf("Error while opening file FILE_IN.view#LSUmat!\n");
exit(1);
}
struct LSU *array_LSU; // alla posizione i dell'array ci sara una struct relativa ad un cluster
int number_of_LSU, ii=0, jj=0, kk, ll, mx;
int xx, yy;
int temp_num_cluster;
fscanf(matrix, "%d\n", &number_of_LSU);
printf( "%d\n", number_of_LSU );
array_LSU=malloc(number_of_LSU*sizeof(struct LSU));
while((fscanf(matrix, "%d", &(array_LSU[ii].LSU_id))) != EOF)
{
fscanf(matrix, "%d", &(array_LSU[ii].number_of_cluster));
printf( "array_LSU[%i].number_of_cluster: <%i>\n", ii, array_LSU[ii].number_of_cluster );
int *array_cluster;
array_cluster=malloc(array_LSU[ii].number_of_cluster*sizeof(int));
for(kk=0; kk < array_LSU[ii].number_of_cluster; kk++)
{
fscanf(matrix, "%d",&array_cluster[kk]);
printf( "array_cluster[%i]: <%i>\n", kk, array_cluster[kk] );
}
array_LSU[ii].cluster=&array_cluster[0];
temp_num_cluster = array_LSU[ii].number_of_cluster;
/***********************************************************************************
leggo la MATRICE DELLE TRANSIZIONI e trasferisco i dati nella struct
***********************************************************************************/
trans_matrix=malloc(temp_num_cluster*sizeof(float*));
for(mx=0;mx<temp_num_cluster;mx++)
trans_matrix[mx] = malloc(temp_num_cluster*sizeof(float));
for(yy=0; yy<temp_num_cluster; yy++)
{
for(xx=0; xx<temp_num_cluster; xx++)
{
fscanf(matrix, "%f", &trans_matrix[xx][yy]);
printf( "trans_matrix[%i][%i]: <%f>\n", xx, yy, trans_matrix[xx][yy] );
}
}
array_LSU[ii].matrix=trans_matrix;
ii++;
}
return 0;
}
questo e´ l´output
2
array_LSU[0].number_of_cluster: <5>
array_cluster[0]: <35>
array_cluster[1]: <19>
array_cluster[2]: <7>
array_cluster[3]: <38>
array_cluster[4]: <4>
trans_matrix[0][0]: <0.000000>
trans_matrix[1][0]: <0.500000>
trans_matrix[2][0]: <0.500000>
trans_matrix[3][0]: <0.000000>
trans_matrix[4][0]: <0.000000>
trans_matrix[0][1]: <0.000000>
trans_matrix[1][1]: <0.200000>
trans_matrix[2][1]: <0.200000>
trans_matrix[3][1]: <0.200000>
trans_matrix[4][1]: <0.400000>
trans_matrix[0][2]: <0.330000>
trans_matrix[1][2]: <0.330000>
trans_matrix[2][2]: <0.330000>
trans_matrix[3][2]: <0.000000>
trans_matrix[4][2]: <0.000000>
trans_matrix[0][3]: <0.000000>
trans_matrix[1][3]: <0.000000>
trans_matrix[2][3]: <0.000000>
trans_matrix[3][3]: <0.000000>
trans_matrix[4][3]: <1.000000>
trans_matrix[0][4]: <0.000000>
trans_matrix[1][4]: <1.000000>
trans_matrix[2][4]: <0.000000>
trans_matrix[3][4]: <0.000000>
trans_matrix[4][4]: <0.000000>
array_LSU[1].number_of_cluster: <3>
array_cluster[0]: <8>
array_cluster[1]: <0>
array_cluster[2]: <40>
trans_matrix[0][0]: <0.000000>
trans_matrix[1][0]: <1.000000>
trans_matrix[2][0]: <0.000000>
trans_matrix[0][1]: <0.150000>
trans_matrix[1][1]: <0.770000>
trans_matrix[2][1]: <0.080000>
trans_matrix[0][2]: <0.000000>
trans_matrix[1][2]: <1.000000>
trans_matrix[2][2]: <0.000000>
sottovento
27-07-2007, 09:23
Ho fatto qualche prova con Visual C++ (questo passa il convento :) )
Ho ottenuto anch'io il crash, MA NON sull'assegnamento in questione, bensi' sulla fscanf()!
Il debugger mi segnalava un errore strano, per cui ho cercato su msdn, trovando che si tratta di un bug (se cosi' possiamo chiamarlo): http://support.microsoft.com/kb/37507/en-us
Non conoscendo l'ambiente in cui operi, non so se questo ti puo' essere utile.
Ad ogni modo, il problema e' sparito seguendo le indicazioni di quell'articolo, cioe' semplicemente inizializzando la variabile float prima di usarla:
for(yy=0; yy<temp_num_cluster; yy++)
{
for(xx=0; xx<temp_num_cluster; xx++)
{
trans_matrix[xx][yy] = 0.0; // Solo questo
fscanf(matrix, "%f", &trans_matrix[xx][yy]);
}
}
Se l'ambiente e' un altro, non e' ovviamente detto che ti risolva il problema. Comunque vale la pena di provare.
Tieni presente che sul mio sistema l'errore era di manipolazione dei float, pertanto potresti aver bisogno, su altri sistemi, di linkare la libreria matematica (per es. su unix/linux, linkare con l'opzione -lm)
trallallero
27-07-2007, 09:25
faccio bene a non usare MAI la scanf :D
marco.gheza
27-07-2007, 09:29
RISOLTO!!!
Dopo aver castato con float* tutto funziona...sembra che nella struct ci sia tutto. Perciò problema risolto! Grazie a sottovento e a tutti quelli che si sono sbattuti.
a presto
trallallero
27-07-2007, 09:33
http://support.microsoft.com/kb/37507/en-us[/url]
comunque solo windows puo´ avere una schifezza di baco simile :O
sottovento
27-07-2007, 09:38
comunque solo windows puo´ avere una schifezza di baco simile :O
Io ne ho di peggio: l'altro giorno sono salito in macchina e mi sono accorto che non c'era il volante. Ero salito DIETRO! :D
Ma quel che e' peggio, e' che e' vero!
trallallero
27-07-2007, 09:45
Io ne ho di peggio: l'altro giorno sono salito in macchina e mi sono accorto che non c'era il volante. Ero salito DIETRO! :D
Ma quel che e' peggio, e' che e' vero!
http://www.freesmileys.org/emo/cool10.gif
fattene meno :asd:
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.