[C] Aiuto creazione simil-semplice programma

di il
6 risposte

[C] Aiuto creazione simil-semplice programma

Allora innanzi tutto grazie per essere entrati e quindi avermi dato una chance. Siccome sto cominciando a controllare le strutture principali del C volevo lanciarmi nella stesura di qualcosa di più complesso dei soliti algoritmi matematici o simili che si fanno per imparare.
L'obbiettivo sarebbe creare un programma (ovviamente per console, senza GUI) che assista nella gestione di un elenco di invitati ad un eventuale evento, tenendo conto di partecipazioni confermate e non, degli eventuali +1 richiesti, e che permetta con alcune funzioni di facilitarne la gestione.
Ovviamente l'elenco invitati non deve essere volatile, ma costantemente salvato su un file che funga da sorta di "database" così che sia sempre uguale ad ogni esecuzione del programma.
Avevo già realizzato qualcosa di simile e funzionante ma volevo ora riscriverlo in modo che gestisse innanzitutto in modo dinamico la memoria, ed inoltre organizzarlo in modo più solido rispetto al precedente. E qui stanno sorgendo i primi problemi...
Inoltre io ho sempre messo tutto nel "main.c" ma per praticità mi piacerebbe che le funzioni stessero in un altro file, solo che quando includo il mio file di funzioni e il mio header con i prototipi sbaglio qualcosa poichè quando provai mi diede errore, ma questo è per ora un problema secondario.

Innanzitutto ho definito una struttura/lista Invitato in questo modo

struct Invitato{
	char nome[MAX];
	char cognome[MAX];
	int partecipa;                            // Confermata = 1, non confermata = 0, in forse = 2
	int uno;                                   // Eventuali +1, stesse regole per "partecipa"	
	struct Invitato *next;	                 // Puntatore alla prossima "cella"
};
typedef struct Invitato Invitato;	          // Così non mi devo portare dietro struct ogni volta
I primi problemi li sto avendo con l'inserimento dinamico di un nuovo invitato e il salvataggio dell'elenco su file. Nonostante i miei sforzi non sono ancora ferratissimo sui puntatori. Comunque la funzione di inserimento è la seguente (Non capisco se è sbagliata, a me pare logicamente coerente)

Invitato *Inserisci_Invitato(Invitato *list){
	Invitato *ptmp;
	ptmp = list;
	
	while (ptmp != NULL){					// Scorre la lista alla ricerca dell'ultima "cella", nel caso la lista sia vuota dovrebbe saltare l'operazione
		ptmp = ptmp->next;
	}
	
	ptmp=(Invitato *)malloc(sizeof(Invitato));

	printf("Inserisci Nome: ");
	scanf("%s", &ptmp->nome);
	printf("Inserisci Cognome: ");
	scanf("%s", &ptmp->cognome);
	printf("Partecipazione confermata?(1=si, 0=no 2=forse) ");
	scanf("%d", &ptmp->partecipa);
	printf("+1? (1=si, 0=no, 2=forse) ");
	scanf("%d", &ptmp->uno);
	printf("\n");
	ptmp->next = NULL;               // Marca la nuova fine 
	
	return list;
}

La funzione successiva è quella che dovrebbe salvare su file la lista di invitati. La funzione non stampa na cippa sul file, nè restituisce il messaggio di errore o di confermata scrittura, semplicemente non fa niente.

void Salva_Lista_Su_File(Invitato *list){
	FILE *fp;

	if (!(fp=fopen("elenco.txt","w")))  {								// ELENCO.TXT
		printf("ERRORE nell'apertura del file elenco.txt\n\n");
	}else{
		while(list != NULL){
			fprintf(fp, "%15s\t%20s\t%5d\7%5d\n", list->nome, list->cognome, list->partecipa, list->uno);
			list = list->next;
		}
		printf("Dati scritti con successo\n");
	}
	fclose(fp);
}

Inoltre ho scritto una funzione di stampa-lista che dovrebbe stampare la lista salvata in run-time. Non stampa na cippa manco questa, il codice è

void Stampa_Lista(Invitato *list){
	int i=1;
	
	if (list == NULL){
		printf("Elenco vuoto. Inserisci degli invitati");
	}
	
	while(list != NULL){
		printf("%d)", i);
		printf ("%10s", list->nome); 
		printf ("%20s", list->cognome); 
		if (list->partecipa == 0){
			printf("\t  Non Confermato");
		}else if(list->partecipa == 1){
			printf("\t      Confermato");
		}else{
			printf("\t        In Forse");
		}
		if (list->uno == 0){
			printf("\t\t\n");
		}else if(list->uno == 1){
			printf("\t\t+1\n");
		}else{
			printf("\t\t+1 In Forse\n");
		}
		i++;
		list = list->next;				// Scorre di un elemento
	}
	
	printf("\n");
}

Non capisco perchè non succeda niente, la soluzione più probabile che mi viene in mente è che non stampi niente su file o su schermo perchè qualcosa non va nell'accquisizione dei dati da tastiera. BOH!
Insomma è un po un casino qualcuno può darmi una mano?

6 Risposte

  • Re: [C] Aiuto creazione simil-semplice programma

    Cominciamo da qui:
      while (ptmp != NULL){               // Scorre la lista alla ricerca dell'ultima "cella", nel caso la lista sia vuota dovrebbe saltare l'operazione
          ptmp = ptmp->next;
       }
       
       ptmp=(Invitato *)malloc(sizeof(Invitato));
    l'istruzione
    ptmp=(Invitato *)malloc(sizeof(Invitato));
    non ti consente di "collegarti" all'ultimo elemento della lista perchè l'ultimo elemento della lista non viene aggiornato con il puntatore all'elemento che allochi.
    Per fare quello che vuoi fare devi conservarti il puntatore all'ultimo elemento pieno e assegnare il risultato della malloc al campo next di quest'ultimo (che ovviamente era NULL).
    Quello che fai tu è creare un elemento appeso nell'heap scollegato dalla lista.
    In genere, se si pensa di operare spesso sul fine lista è opportuno memorizzare e tenere aggiornato anche un puntatore all'ultimo elemento. Altrimenti, quando scorri la lista ti tieni anche il puntatore all'ultimo elemento o fai il test su ptmp->next invece che su ptmp (attento a farlo bene).
    Ragiona un po e vediamo cosa si può fare.

    Ciao.
  • Re: [C] Aiuto creazione simil-semplice programma

    Mi ci sto scervellando su ma proprio non capisco il senso della tua risposta:
    tu mi dici di conservare il puntatore all'ultimo elemento pieno, e non al marcatore di fine lista NULL.
    Tuttavia ciò dipende dal fatto che effettivamente esista un elemento pieno, mentre invece, almeno la prima volta, la lista sarà ancora vuota, e quindi il puntatore alla lista punterà direttamente NULL.
    Non riesco a capire perchè non funzioni e perchè il malloc risulti scollegato.
    Confermi che ptmp punti al marcatore NULL? Se così fosse malloc dovrebbe allocare il nuovo elemento al posto di NULL e causare lo slittamento del NULL (tra parentesi tocca a me fare si che il nuovo elemnto punti a NULL o lo capisce da solo? Ora che ci penso, ne dubito...) quindi se l'elemento precedente (qualora esistente altrimeni direttamente il puntatore alla lista) prima puntava a NULL, ora punta al nuovo elemento no? Casomai potrebbe essere l'errore che il nuovo elemento invece che puntari a NULL punti a un fico secco e quindi comprometti le funzioni che operano sulla lista. Non so sono un po confuso, ma mi ci sto mettendo d'impegno. Grazie comunque della risposta

    EDIT
    Mi ero distratto e mi ero dimenticato di avere già marcato nella funzione che l'ultimo elemento avrebbe dovuto puntare a NULL:
    
    ptmp->next = NULL;
  • Re: [C] Aiuto creazione simil-semplice programma

    Non mi sorprende che non vedi la soluzione. Ciò accade, in genere, per il seguente fatto:
    chi comincia a programmare salta spesso i passi fondamentali , che sono: l'analisi dei requisiti, la progettazione e, solo alla fine, l'implementazione, e va direttamente alla scrittura del codice. Questo è come cercare di costruire una casa senza fare le verifiche geologiche e i calcoli di staticità e dinamicità della struttura.
    Se vuoi porre rimedio già dal tuo livello, prova ad analizzare i requisiti, ad esempio la traccia del tuo esercizio, disambiguare tutto ciò che è disambiguabile, scomporre il problema "grande" in problemi più piccoli e provare a risolvere i problemi più piccoli scrivendo la soluzione in linguaggio naturale.
    Ciao.
  • Re: [C] Aiuto creazione simil-semplice programma

    Concordo pienamente con la tua logica didattica, ma di fatto io ci sono stato un bel po a cercare di risolvere, giungendo ai dubbi che ti ho appena esposto. Quando avevi cercato di indirizzrmi, facendo quindi poi sorgere i nuovi quesiti, mi sono messo mano alla matita e ho cercato di capire senza scrivere un acca di codice in più e ne ho intenzione di farlo finchè nei miei fogli cartacei non sarà chiaro lo schema. Il punto è che non riesco a capire la logica dell'errore, e per questo ho chiesto maggiori chiarimenti tuttora irrisolti. Non potresti rispondermi a quelle domande per favore? Grazie comunque
  • Re: [C] Aiuto creazione simil-semplice programma

    Ho capito: l'errore logico del mio ragionamento è che quando uso malloc con un puntatore non è lo spazio allocato ad essere allocato a partire dall'indirizzo puntato dal puntatore ma il puntatore a puntare a un nuovo indirizzo di memoria....
  • Re: [C] Aiuto creazione simil-semplice programma

Devi accedere o registrarti per scrivere nel forum
6 risposte