PDA

Visualizza la versione completa : [C] Allocare memoria per memorizzare contatto di una rubrica


Vincent
21-10-2006, 22:13
Salve a tutti!

Ho fatto un programmino Agenda, che è stato implementato come array di struct.

Il programma è finito, ma il mio unico problema è che il prof. lo vuole con array di struct allocati dinamicamente.

Se volessi inserire un nuovo contatto nell'agenda, come devo allocare la memoria?

Cioè come faccio a capire come riallocare la memoria per aggiungere lo spazio necessario al nuovo contatto, senza perdere i dati precedentemente salvati nel mio array di struct?

Da tre giorni ci lavoro ed ancora non ho trovato la soluzione...Cosa devo controllare?

Vi ringrazio...

Spero di essere stato chiaro...
Vi allego anche il codice...



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

typedef struct
{
int ID;
char Cognome[32];
char Nome[32];
} Persona;

void Inserisci( Persona *New , int *n);
void stampa( Persona *List , int n );

int main()
{
Persona *Contatti;
int start; /* Num di contatti */

start = 0;
Contatti = NULL;

Inserisci( Contatti , &start );
stampa( Contatti , start );

system("PAUSE");
return 0;
}

void Inserisci( Persona *New , int *n )
{
int i, dim;

dim=*n;
/* Se è la prima volta che inserisco */
if ( dim == 0 )
{
/* Aggiungo dim++ = 1 elemento */
dim++;
/* Alloco lo spazio */
New =(Persona*) malloc ( sizeof ( Persona ) );
/* Per i che va da 0 a 1 */
for(i=0; i<dim ; i++)
{
/* Il primo id è 1 */
New[i].ID=dim;
/* Prendo il nome ed il cognome */
printf("Cognome: ");
scanf("%s" , New[i].Cognome);
printf("Nome: ");
scanf("%s" , New[i].Nome);
}
/* Restituisco al main la dimensione aggiornata */
n = &dim;
}
/* Se ci sono elementi nell'Array */
else
{

/* Aggiungo un elemento ai presenti */
dim = *n;
dim++;

/* Rialloco lo spazio aggiungendo dim = dim+1 elemento */
New =(Persona*) realloc ( New , dim );

for(i=0; i<dim ; i++)
{
New[i].ID=dim;
/* Prendo il nome ed il cognome */
printf("Cognome: ");
scanf("%s" , New[i].Cognome);
printf("Nome: ");
scanf("%s" , New[i].Nome);
}
}
}


void stampa( Persona *List , int n )
{
int i;
for(i=0; i<n ; i++)
{
printf("%s %s\n" , List[i].Cognome , List[i].Nome);
}
system("PAUSE");
}

Lak3d
22-10-2006, 02:55
/* Restituisco al main la dimensione aggiornata */
n = &dim;

sei sicuro che così facendo restituisci al main la dimensione aggiornata? secondo me stai soltanto cambiando il contenuto del puntatore; non è così: *n=dim ?

E poi a che ti serve riallocare? quel codice non inserirà mai più di un contatto... sarà sempre il primo contatto a essere inserito, dopodichè il codice termina la sua esecuzione... almeno così mi pare...

e fra l'altro a me la Stampa non funziona...

Lak3d
22-10-2006, 05:20
L'ho guardato meglio...


typedef struct
{
int ID;
char Cognome[32];
char Nome[32];
} Persona;

void Inserisci( Persona **New , int *n);
void stampa( Persona *List , int n );

int main(){
Persona *Contatti;
int start, choice;
start = 0;
Contatti = NULL;

printf("Premi 1 per inserire\n"
"Premi 2 per terminare\n?");
scanf("%d", &choice);

while(choice!=2){
Inserisci(&Contatti, &start );
stampa(Contatti, start );
printf("?");
scanf("%d",&choice);
}
system("PAUSE");
return 0;
}

void Inserisci( Persona **New , int *n ){
int i, dim;
Persona *NewP;

dim=*n;
if (dim == 0){
dim++;
NewP=(Persona*)malloc(sizeof(Persona));
}
else{
dim++;
NewP=(Persona*)realloc(*New, dim);
}
NewP[dim].ID=dim;
printf("Cognome: ");
scanf("%s" , NewP[dim].Cognome);
printf("Nome: ");
scanf("%s" , NewP[dim].Nome);
*n = dim;
*New=NewP;
}

void stampa( Persona *List , int n ){
int i;

for(i=1; i<=n; i++)
printf("%s %s\n" , List[i].Cognome , List[i].Nome);
}

Innanzitutto come detto sopra devi fare (*n=dim;) e non (n=&dim;), altrimenti start rimaraà sempre a zero perchè non stavi cambiando il suo valore ma semplicemente stavi facendo puntare n a dim, e uscito dalla funzione start rimane tale e quale a quando è entrato.

Poi il primo parametro di Inserisci dev'essere un puntatore a puntatore, ovvero deve puntare all'indirizzo di memoria del puntatore Contatti se vuoi poter modificare il suo indirizzo da NULL all'elemento che inserisci... e così per ogni volta che reallochi.

Ho messo un while così puoi inserire più nominativi, altrimeti si eseguiva soltanto una volta.

Vincent
22-10-2006, 12:47
Sei stato davvero gentilissimo! :yuppi: :yuppi: Non avrei mai pensato al doppio puntatore!

Vincent
22-10-2006, 14:03
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
/* !
* La struttura Telefono è utilizzata per memorizzare il Numero Telefonico
* del Contatto ed il tipo ( "Etichetta" ) di numero
*/
typedef struct { unsigned int ID; /*!< Variabile intera senza segno di
* indentificazione univoca del numero telefonico */

char NumTel[50]; /*!< Stringa contenente il numero telefonico*/

char Etichetta [50]; /*!< Stringa contenente la tipologia di
* numero telefonico: "Casa" , "Ufficio" , "Fax" , etc...*/
} Telefono;


/*
La struttura Persona utilizzata per allocare un nuovo Contatto
*/
typedef struct { unsigned int ID;
char Cognome [50];
char Nome [50];
Telefono Tel;
char Indirizzo[100];
} Persona;

void Inserisci( Persona **New , int *n);
void stampa( Persona *List , int n );

int main(){
Persona *Contatti;
int start, choice;
start = 0;
Contatti = NULL;

printf("Premi 1 per inserire\n"
"Premi 2 per terminare\n?");
scanf("%d", &choice);

while(choice!=2){
Inserisci(&Contatti, &start );
stampa(Contatti, start );
printf("?");
scanf("%d",&choice);
}
free(Contatti);
system("PAUSE");
return 0;
}

void Inserisci( Persona **New , int *n )
{ int i, dim;
Persona *NewP;

dim=*n;

if (dim == 0){
dim++;
NewP=(Persona*)malloc(sizeof(Persona));
}
else{
dim++;
NewP = (Persona*)realloc(*New, dim);
}

system("CLS");

/* Inserimento dati... */
printf ( "\nInserimento Persona\n" );

NewP[dim].ID=dim;
/* ...stampo l'ID */
printf("\nID: %d\n" , NewP[dim].ID);
/* Inserimento Cognome del Contatto nella struttura di appoggio */
printf("Cognome: ");
scanf("%s" , NewP[dim].Cognome );
/* Inserimento Nome del Contatto nella struttura di appoggio */
printf("Nome: ");
scanf ( "%s" , NewP[dim].Nome );
/* Inserimento Numero Telefonico del Contatto nella struttura di appoggio */
printf("Numero: ");
scanf("%s" , NewP[dim].Tel.NumTel );
/* Inserimento Tipo di Numero Telefonico del Contatto nella struttura di appoggio */
printf("Tipo Numero: ");
scanf("%s" , NewP[dim].Tel.Etichetta );

/* Inserimento Indirizzo del Contatto nella struttura di appoggio */
getchar();
printf("Indirizzo: ");
fgets( NewP[dim].Indirizzo , 100 , stdin );


/* Restutuisco al main i valori aggiornati */
*n = dim;
*New=NewP;

/* Stampo un messaggio di di avviso e termino la procedura */
system("CLS");
printf ( "\nContatto inserito\n" );
system("PAUSE");
system("CLS");


return;

}

void stampa ( Persona *List , int n )
{ int i, /* Variabile di iterazione per i cicli */
len; /* Lunghezza effettiva del file "Contatti.txt" */

system("CLS");

printf("\n");
printf("\t\t +-----------------------------+\n");
printf("\t\t + Stampa Contatti + \n");
printf("\t\t +-----------------------------+\n\n");

printf(" --------------------------------------------------------------------------\n");
printf("ID\tCognome\tNome\tTelefono\tTipo\tIndirizzo\n" );
printf(" --------------------------------------------------------------------------\n");

/* Se non c'è nessun contatto, ossia la lunghezza del file è "zero" */
if ( n == 0 )
{
printf(" -> Nessun Contatto Presente <-\n");
}
/* Altrimenti stampa la lista di contatti */
else
{
for(i=1; i<=n; i++)
{
printf("%d\t%s\t%s\t%s\t%s\t%s\n" , List[i].ID , List[i].Cognome , List[i].Nome ,
List[i].Tel.NumTel , List[i].Tel.Etichetta ,
List[i].Indirizzo);
}
}
printf("\n -----------------------------------------------------------------------n\n");

printf("\n\n");

system("PAUSE");
system("CLS");
return;

}


Mi sono complicato un pò la vita...ma non funziona!
Mi fa inserire il primo contatto fino all'indirizzo, appena inserisco l'indirizzo, si impalla tutto!
HELP MEEEEEEEEEEE!!!

Marcoski
22-10-2006, 14:19
Una domandina stupida utilizzare una struttura ricorsiva anzichè un array di strutture non era più semplice?

Lak3d
22-10-2006, 14:24
/* Inserimento Indirizzo del Contatto nella struttura di appoggio */
getchar();
printf("Indirizzo: ");
fgets( NewP[dim].Indirizzo , 100 , stdin );

perchè fgets? serve per scrivere su file...


while ( (C=getchar() )!='\n')
NewP[dim].Indirizzo=c;

così inserisci l'indirizzo...
Poi sinceramente non so cosa stai facendo perchè vedo che parli di un file Contatti.txt di cui io non vedo nè il classico puntatore FILE * nè le funzioni di scrittura su file.

Lak3d
22-10-2006, 14:25
Originariamente inviato da Marcoski
Una domandina stupida utilizzare una struttura ricorsiva anzichè un array di strutture non era più semplice?

stessa cosa che volevo suggerirgli io... una lista concatenata avrebbe risolto tutto più velocemente... ma a quanto leggo è obbligato per motivi scolastici a svilupparlo in quel modo.

Vincent
22-10-2006, 14:40
perchè fgets? serve per scrivere su file...


Perchè l'indirizzo non è una stringa...Via A. Manzoni n. 21 lo prendo con fgest, passandogli il mio array e come file lo standard input...

Per il file contatti.txt lascia perdere... mi serivarà dopo per salvare il contenuto dell'array...
ma se non funziona così, figuriamoci con i files... :dhò:





while ( (C=getchar() )!='\n')
NewP[dim].Indirizzo=c;



Non funziona questo mi da errore: 94 prova.c incompatible types in assignment

Chiedo un suggerimento: se dovesse farla voi implementata mediante array di struct, come fareste?

Io ho sviluppato tutte le funzioni per array statico, allocato staticamente.

Ma il mio prof vuole che sia implementata con array statico allocato dinamicamente...

E' pazzo! :berto:

Dopo lo vorrà implementato con le liste! :fighet: che a mio avviso è più semplice!

Grazie ancora!

Vincent
22-10-2006, 17:29
typedef struct
{
int ID;
char Cognome[32];
char Nome[32];
} Persona;

void Inserisci( Persona **New , int *n);
void stampa( Persona *List , int n );

int main(){
Persona *Contatti;
int start, choice;
start = 0;
Contatti = NULL;

printf("Premi 1 per inserire\n"
"Premi 2 per terminare\n?");
scanf("%d", &choice);

while(choice!=2){
Inserisci(&Contatti, &start );
stampa(Contatti, start );
printf("?");
scanf("%d",&choice);
}
system("PAUSE");
return 0;
}

void Inserisci( Persona **New , int *n ){
int i, dim;
Persona *NewP;

dim=*n;
if (dim == 0){
dim++;
NewP=(Persona*)malloc(sizeof(Persona));
}
else{
dim++;
NewP=(Persona*)realloc(*New, dim);
}
NewP[dim].ID=dim;
printf("Cognome: ");
scanf("%s" , NewP[dim].Cognome);
printf("Nome: ");
scanf("%s" , NewP[dim].Nome);
*n = dim;
*New=NewP;
}

void stampa( Persona *List , int n ){
int i;

for(i=1; i<=n; i++)
printf("%s %s\n" , List[i].Cognome , List[i].Nome);
}
Non funziona! Se inserisco gli elementi, ok. Ma se poi voglio uscire dopo aver inserito gli elementi si blocca!

Loading