PDA

View Full Version : [C]Problema con matrice dinamica in una struttura


federik1982
16-08-2007, 22:38
Innanzitutto chiedo scusa per tutti gli errori che faro', e' la prima volte che posto qui, ma sono disperato (ho un esame a fine agosto).

In breve devo creare una struttura semplice semplice che mi consenta di gestire un reparto d'ospedale con posti letto prenotabili per un anno.Bon.
Lasciamo stare i vari pezzi commentati, e' tutto work in progress. La cosa che non riesco a capire è come mai dopo che riempo la mia matrice con dei numeri (puramente a caso di prova), poi non riesco piu ad accedervi, difatti mi esce un bel processor fault quando nel main per prova ho tentato di cambiare un valore. Sicuramente e' un errore banale e grave (nel senso che sono stupido), daltronde io odio programmare...
Se per caso qualcuno lo legge anche solamente, grazie :D



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

#define MAX 50
#define GIORNI 20

typedef struct s_reparto
{
char reparto [MAX+1];
char ospedale [MAX+1];
int num_letti;
int *matrice[];
}tipo_reparto;

int num_reparti,indice_riga,indice_col,indice;
FILE *cf;
tipo_reparto *reparto;

void leggifile(void);
//void prenota(void);


void main()
{

leggifile();
// prenota();
indice=0;
reparto[indice].matrice[1][0]=1;
for (indice_riga=0;indice_riga<reparto[indice].num_letti;indice_riga++) //stampa di controllo, e pure limitata a 12 per comodita'
{
for(indice_col=0;indice_col<12;indice_col++)
printf("%d ",reparto[indice].matrice[indice_riga][indice_col]);
printf("\n");
}
fclose(cf);

}

void leggifile()
{

if((cf=fopen("piemonte.txt","r+"))==NULL)
printf("errore in apertura file\n");
else
{
fscanf(cf,"%d",&num_reparti); //finche' non finisco il file dovro' creare le caselle della mia struttura
reparto=(tipo_reparto*)malloc(num_reparti*sizeof(tipo_reparto)); //cosi' dovrei creare un tot di allocazioni in
while (!feof(cf)) //memoria con una struttura tipo_reparto
{
for (indice=0;indice<num_reparti;indice++)
{
fscanf(cf,"%s%s%d",reparto[indice].ospedale,reparto[indice].reparto, &reparto[indice].num_letti);
//ora per ogni reparto di ospedale devo creare la matrice con tutti i letti disponibili o meno

for (indice_riga=0;indice_riga<reparto[indice].num_letti;indice_riga++)
{
reparto[indice].matrice[indice_riga]=(int *)malloc(GIORNI*sizeof(int));
for (indice_col=0;indice_col<GIORNI;indice_col++)
reparto[indice].matrice[indice_riga][indice_col]=3; //per ora setto tutti gli spazi della matrice a 0, lo uso per indicare
//che i letti sono tutti liberi
}
//stampa di prova per la matrice, ridotta anche
for (indice_riga=0;indice_riga<reparto[indice].num_letti;indice_riga++) //stampa di controllo, e pure limitata a 12 per comodita'
{
for(indice_col=0;indice_col<12;indice_col++)
printf("%d ",reparto[indice].matrice[indice_riga][indice_col]);
printf("\n");
}



} //chiudo il primo for
} //chiudo il while
} //chiudo if
//stampa di prova solo per vedere ospedale ,reparto e numero letti
for (indice=0;indice<num_reparti;indice++)
{
printf("ospedale: %s ,reparto: %s ,numero letti: %d \n",reparto[indice].ospedale,reparto[indice].reparto, reparto[indice].num_letti);
}
// fclose(cf);
}


/*
void prenota()
{
char reparto_p[MAX+1];
int giorni_p=0;
while (giorni_p!=-1)
{
if(giorni_p!=-1) //per evitare di fare il primo passo altrove faccio subito un altro controllo...rozzo...ma semplice
{
printf ("Inserire il reparto in cui si vuole prenotare e il numero di giorni da prenotare: (-1 per terminare)\n");
scanf("%s %d",reparto_p,&giorni_p);
//adesso dovremo vedere se troviamo un reparto che abbia un letto disponibile per quei tot giorni richiesti
//e dobbiamo anche trovare quello che ce li ha prima
for (indice_reparto=0; indice_reparto<num_reparti; indice_reparto++) //scorriamo tutti i reparti
{

}

} //chiudo if
} //chiudo while
}

*/

cionci
17-08-2007, 16:07
Hai sbagliato l'allocazione della matrice...
Devi fare così:

int **matrice;
int i;

matrice = (int **) malloc(sizeof(int *) * num_letti);

for(i = 0; i < GIORNI; ++i)
matrice[i] = (int *) malloc(sizeof(int) * GIORNI);
Ovviamente inserendo la matrice nella struttura non cambia praticamente niente.

federik1982
17-08-2007, 17:24
grazie mille, provo immediatamente e faccio sapere :D

federik1982
17-08-2007, 17:53
Ho provato a cambiare seguendo quello che mi hai detto

Nel pezzo interessato ho fatto cosi':


for (indice_riga=0;indice_riga<reparto[indice].num_letti;indice_riga++)
{
reparto[indice].matrice=(int **) malloc(sizeof(int *) * reparto[indice].num_letti);
for(i = 0; i < GIORNI; ++i)
reparto[indice].matrice[i] = (int *) malloc(sizeof(int) * GIORNI);
for (indice_col=0;indice_col<GIORNI;indice_col++)
reparto[indice].matrice[indice_riga][indice_col]=3;


il risultato e' che si', ora riesco ad accedere liberamente alla mia matrice, ma in compenso, dopo due passi di ciclo,invece di inserirmi tutti "3", mi mette numeri a casaccio, e non solo, va nel caos anche la stampa separata del nome ospedale e reparto.
Ad ogni modo continuo a lavorarci su e grazie !







#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>

#define MAX 50
#define GIORNI 20

typedef struct s_reparto
{
char reparto [MAX+1];
char ospedale [MAX+1];
int num_letti;
int **matrice;
}tipo_reparto;

int num_reparti,indice_riga,indice_col,indice;
FILE *cf;
tipo_reparto *reparto;

void leggifile(void);
//void prenota(void);


void main()
{

leggifile();
// prenota();
indice=0;
reparto[indice].matrice[0][0]=1;
for (indice_riga=0;indice_riga<reparto[indice].num_letti;indice_riga++) //stampa di controllo, e pure limitata a 12 per comodita'
{
for(indice_col=0;indice_col<12;indice_col++)
printf("%d ",reparto[indice].matrice[indice_riga][indice_col]);
printf("\n");
}
fclose(cf);

}

void leggifile()
{
int i;

if((cf=fopen("piemonte.txt","r+"))==NULL)
printf("errore in apertura file\n");
else
{
fscanf(cf,"%d",&num_reparti);
reparto=(tipo_reparto*)malloc(num_reparti*sizeof(tipo_reparto));
while (!feof(cf))
{
for (indice=0;indice<num_reparti;indice++)
{
fscanf(cf,"%s%s%d",reparto[indice].ospedale,reparto[indice].reparto, reparto[indice].num_letti);
for (indice_riga=0;indice_riga<reparto[indice].num_letti;indice_riga++)
{
reparto[indice].matrice=(int **) malloc(sizeof(int *) * reparto[indice].num_letti);
for(i = 0; i < GIORNI; ++i)
reparto[indice].matrice[i] = (int *) malloc(sizeof(int) * GIORNI);
for (indice_col=0;indice_col<GIORNI;indice_col++)
reparto[indice].matrice[indice_riga][indice_col]=3; //per ora setto tutti gli spazi della matrice a 0, lo uso per indicare
//che i letti sono tutti liberi
}
//stampa di prova per la matrice, ridotta anche
for (indice_riga=0;indice_riga<reparto[indice].num_letti;indice_riga++) //stampa di controllo, e pure limitata a 12 per comodita'
{
for(indice_col=0;indice_col<12;indice_col++)
printf("%d ",reparto[indice].matrice[indice_riga][indice_col]);
printf("\n");
}



} //chiudo il primo for
} //chiudo il while
} //chiudo if
//stampa di prova solo per vedere ospedale ,reparto e numero letti
for (indice=0;indice<num_reparti;indice++)
{
printf("ospedale: %s ,reparto: %s ,numero letti: %d \n",reparto[indice].ospedale,reparto[indice].reparto, reparto[indice].num_letti);
}
// fclose(cf);
}

federik1982
17-08-2007, 18:07
niente da fare, sono negato.
Il fatto è che mi serve per forza dentro la struttura per fare in modo che ogni reparto abbia N letti e ogni letto abbia 365 slot da riempire o meno se sono occupati o non. :mc:

cionci
17-08-2007, 18:11
Hai fatto un po' di confusione ;) O meglio un po' l'avevo fatto anche io con gli indici :D

reparto[indice].matrice=(int **) malloc(sizeof(int *) * reparto[indice].num_letti);
for (indice_riga=0;indice_riga<reparto[indice].num_letti;indice_riga++)
{
reparto[indice].matrice[i] = (int *) malloc(sizeof(int) * GIORNI);
for (indice_col=0;indice_col<GIORNI;indice_col++)
reparto[indice].matrice[indice_riga][indice_col] = 3;

federik1982
17-08-2007, 18:20
assolutamente magnifico
ho a malapena capito il significato, pero' funziona
se passo sto esame mi laureo e addio C :muro: :muro: :muro: :muro: :muro: :muro: :muro: :muro: :muro: :muro: :muro:

Ad ogni modo tra oggi e domani sviluppo il programma se ho altri intoppi ritorno

Grazie infinite sei stato rapido e disponibile, piu' di cosi' non potevo desiderare :D

cionci
17-08-2007, 18:24
assolutamente magnifico
ho a malapena capito il significato, pero' funziona

Se non hai capito chiedi ;)
Comunque è semplice: si alloca un vettore di puntatori e poi si alloca un vettore per ogni puntatore del vettore di puntatori...

federik1982
17-08-2007, 18:46
oh cavolo...ho fatto una segnalazione invece di una risposta...spero di non aver fatto casino...dannata fretta...se trovo un moderatore l'avverto -__-

comunque avevo solo scritto che non mi era molto chiaro il senso di
int **matrice, non l'avevo mai trovata prima come sintassi, a parte in qualche lista, ma con senso diverso

cionci
17-08-2007, 18:54
oh cavolo...ho fatto una segnalazione invece di una risposta...spero di non aver fatto casino...dannata fretta...se trovo un moderatore l'avverto -__-
Ehm :D
<---------
Nessun problema ;)
comunque avevo solo scritto che non mi era molto chiaro il senso di
int **matrice, non l'avevo mai trovata prima come sintassi, a parte in qualche lista, ma con senso diverso
E' un puntatore a un puntatore...l'avrai trovato anche quando vai a modificare un puntatore all'interno di un funzione e vuoi che la modifica avvenga anche nel chiamante ;)
Non è niente di particolare: in questo caso la motivazione è insita in quello che ci andiamo a mettere dentro. Per un vettore con allocazione dinamica normale si usa un puntatore, in questo caso visto che dovrà contenere un vettore allocato dinamicamente di puntatori serve appunto un puntatore a puntatore.

federik1982
17-08-2007, 19:09
okkk grazie

Adesso in teoria devo solo implementare delle ricerche e dei settaggi della matrice, tanti ma dovrebbe essere semplici, spero.

cionci
17-08-2007, 19:12
Mi raccomando se vuoi deallocare la struttura devi fare il passaggio inverso: deallocare uno per uno i vettori di interi, deallocare il vettore di puntatori e poi deallocare la struttura.

federik1982
17-08-2007, 19:45
si hai ragione
ma grazie agli dei è una cosa che non ci chiederanno mai e poi mai

ma siccome sono curioso...
io so usare solo le istruzioni di free per liberare memoria
di solito lo faccio quando uso i malloc per le liste. Con le strutture non ho mai provato, suppongo sia uguale.

cionci
17-08-2007, 19:54
Se elimini un reparto devi anche liberare la memoria ;)
Si fa con la free...solo che non puoi farlo direttamente perché all'interno della struttura matrice contiene altra memoria allocata dinamicamente. Quindi devi usare la free, ma nell'ordine che ti ho detto. In pratica l'ordine inverso rispetto a quello con cui hai chiamato malloc ;)