Gestione Esami Universitari

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Avatar utente
j0kers
Linux 2.x
Linux 2.x
Messaggi: 418
Iscritto il: dom 22 lug 2007, 1:31
Slackware: 13
Kernel: 2.6.32
Desktop: xfce4

Gestione Esami Universitari

Messaggio da j0kers »

Salve ragazzi, sono qui a postare un piccolo programmino scritto da me in C, per la gestione tramite file, di esami universitari.
Una specie di libretto universitario per intenderci, con la possibilità di:

Aggiungere esami
Visualizzare esami
Calcolare la media dei voti, somma dei CFU e somma totale degli esami sostenuti

Questo è il codice sorgente:

Codice: Seleziona tutto

/* Semplice programma per calcolare la media degli
   esami sostenuti
*/

#include <stdio.h>
#include <string.h>
#include <ctype.h>

// Struttura dati Esami
struct esami {
	char nome[50];
	int voto;
	int cfu;
	char data[10];
};
struct esami libretto;

// Funzione Aggiungi Esame
// Aggiunge un esame a libretto
add_esame(){
	FILE *esami;
	int scelta, controllo;
	char libretto_file[20];
	char rsp[1];
	
	
	system("/bin/ls -1");
	printf("Scrivi il nome del libretto da aprire: ");
	scanf("%s",&libretto_file);
	if((esami=fopen(libretto_file,"r"))==NULL){
			printf("Il libretto non esiste!\n");
			sleep(1);
			return;
	}
	esami=fopen(libretto_file,"a");
	system("clear");
	// Inserimento Esame
	do{
		printf("Inserimento nuovo esame: \n\n");
		printf("Inserisci il nome dell'esame: ");
		scanf("%s",&libretto.nome);
		printf("Inserisci il voto (min 18 max 30): ");
		scanf("%d",&libretto.voto);
		printf("Inserisci i crediti (CFU): ");
		scanf("%d",&libretto.cfu);
		printf("Inserisci la data (gg/mm/aaaa): ");
		scanf("%s",&libretto.data);
		// Controllo dati inseriti
		if(libretto.voto<18 || libretto.voto>30){
			printf("Hai inserito un voto non valido!\n");
			sleep(1);
			return;
		}else if(libretto.cfu<3 || libretto.cfu >12){
			printf("Hai inserito CFU non validi!\n");
			sleep(1);
			return;
		}
		fprintf(esami,"Esame: %s - Voto: %d - CFU: %d - Data: %s\n",libretto.nome,libretto.voto,libretto.cfu,libretto.data);
		printf("Esame aggiunto con successo.\n");
		printf("Vuoi inserire un altro esame? (s/n): ");
		scanf("%s",&rsp);
		if(strlen(rsp)>1) return;
		controllo=strcmp(rsp,"n");
	}while(controllo!=0);

	fclose(esami);

	return;
}

// Funzione Crea Libretto
// Crea un nuovo libretto universitario
crea_libretto(){
	FILE *libretto;
	char nome_libretto[20];
	int confronto;
	
	system("clear");
	printf("ATTENZIONE: \tNel caso il libretto esiste già, esso verrà sovrascritto!\n");
	printf("Inserire \'esci\' per tornare al menu principale\n\n");
	printf("Inserisci il nome del libretto: ");
	scanf("%s",&nome_libretto);
	confronto=strcmp(nome_libretto,"esci");
	if(confronto==0) return;
	libretto=fopen(nome_libretto,"w");fclose(libretto);
	printf("Libretto creato con successo.\n ");
	sleep(1);
}

// Funzione Visualizza Libretto
// Visualizza gli esami del libretto
visualizza_libretto(){
	FILE *libretto;
	char nome_libretto[20];
	char buffer[300];
	
	system("clear;ls -1");
	printf("Inserisci il nome del libretto: ");
	scanf("%s",&nome_libretto);
	if((libretto=fopen(nome_libretto,"r"))==0){
		printf("Il libretto non esiste!\n");
		sleep(1);
		return;
	}else {
		while(!feof(libretto)){
			fgets(buffer,300,libretto);
			printf("%s \n",buffer);
		}
		fclose(libretto);
	}
	sleep(5);
}
// Funzione Calcola Media esami
// Calcola la media degli esami sostenuti
calcola_media(){
	FILE *libretto;
	FILE *media_file;
	char nome_libretto[20];
	char buffer[100];
	float media=0;
	int i=0,cfu=0;
	char cmd_media[50]="cat ", cmd_cfu[50]="cat ";
	
	system("clear;ls -1");
	printf("Inserisci il nome del libretto: ");
	scanf("%s",&nome_libretto);
	if((libretto=fopen(nome_libretto,"r"))==0){
		printf("Il libretto non esiste!\n");
		sleep(1);
		return;
	}else{
		// Crea il file media.txt per
		// per il calcolo della media
		strcat(cmd_media,nome_libretto);
		strcat(cmd_media," | sed 's/.*Voto: //' | awk '{print $1}' > media.txt");
		system(cmd_media);
		// Crea il file cfu.txt per
		// per il calcolo dei cfu
		strcat(cmd_cfu,nome_libretto);
		strcat(cmd_cfu," | sed 's/.*CFU: //' | awk '{print $1}' > cfu.txt");
		system(cmd_cfu);
		if((media_file=fopen("media.txt","r"))==NULL){
				printf("Errore apertura del file!\n");
				sleep(3);
				return;
		}
		while(!feof(media_file)){
			fgets(buffer,100,media_file);
			media=media+atoi(buffer);
			i++;
		}
		fclose(media_file);
		media=media / i;
		if((media_file=fopen("cfu.txt","r"))==NULL){
				printf("Errore apertura del file!\n");
				sleep(3);
				return;
		}
		i=0;
		while(!feof(media_file)){
			fgets(buffer,100,media_file);
			cfu=cfu+atoi(buffer);
			i++;
		}
		fclose(media_file);
		printf("Hai sostenuto %d esami con una media di %2.1f per un totale di %d CFU\n\n",i-1,media,cfu);
		system("rm -rf media.txt cfu.txt");
		char c=getchar();
		//sleep(10);
	}
}
// Funzione Principale MAIN

main(){
	int scelta;

	do{
		system("clear");
		printf("Gestione Libretto Esami Universitari\n\n");
		printf("Menu Principale: \n");
		printf("1) - Crea un libretto esami\n");
		printf("2) - Aggiungi un esame ad un libretto\n");
		printf("3) - Visualizza esami di libretto\n");
		printf("4) - Calcola la media degli esami sostenuti\n");
		printf("5) - Esci dal programma\n\n");
		printf("Scegli una opzione: ");
		scanf("%d",&scelta);
		// Controllo inserimento
		
		switch(scelta){
			case 1:
				crea_libretto();
				break;
			case 2:
				add_esame();
				break;
			case 3:
				visualizza_libretto();
				break;
			case 4:
				calcola_media();
				break;
		}
	}while(scelta!=5);
}

Devo ancora risolvere un paio di cose...Ad esempio nella funzione "main" il while viene ripetuto finquando non viene premuto il numero 5,
però se inserisco una lettera il programma va in errore.
L'altra cosa da risolvere è nelle funzioni visualizza,calcola ecc.. dopo aver mostrato i risultati ho dovuto inserire uno sleep al posto di getchar
perchè non si fermava la schermata ma rientrava subito alla main.

Accetto qualsiasi consiglio per perfezionare il codice. Grazie a tutti 8)
Ultima modifica di j0kers il mer 19 mag 2010, 10:36, modificato 1 volta in totale.

Avatar utente
Blallo
Packager
Packager
Messaggi: 3302
Iscritto il: ven 12 ott 2007, 11:37
Nome Cognome: Savino Liguori
Slackware: 14.2 / 12.2
Kernel: 4.4.14-smp
Desktop: DWM
Località: Torino / Torremaggiore (FG)
Contatta:

Re: Gestione Esami Universitari

Messaggio da Blallo »

al posto della scanf metti

Codice: Seleziona tutto

fgets(buf, TA, stdin);
sscanf(buf, "%d", &scelta);
ovviamente devi aggiungere l'header string.h
e devi definire anche una stringa (che chiamo buf in questo momento), TA è la dimensione della stringa

Avatar utente
RedSkull92
Linux 3.x
Linux 3.x
Messaggi: 567
Iscritto il: mar 21 apr 2009, 17:25
Slackware: 64bit -current
Kernel: 3.5.4
Desktop: FluxBox
Località: Palermo
Contatta:

Re: Gestione Esami Universitari

Messaggio da RedSkull92 »

è normale che il programma vada in errore se inserisci una lettera, perchè tu memorizzi i dati in un int, non in un char.
Stai attento che se vuoi leggere un libretto il cui nome ha spazi, non potrai farlo perchè scanf si ferma agli spazzi, potresti utilizzare fgets leggendo dal buffer stdin.
vediamo al funzione crea_libretto.

Codice: Seleziona tutto

if((esami=fopen(libretto_file,"r"))==NULL){
         printf("Il libretto non esiste!\n");
         sleep(1);
         return;
}
esami=fopen(libretto_file,"a");
non potevi fare direttamente

Codice: Seleziona tutto

if((esami=fopen(libretto_file,"a"))==NULL)
{
         printf("Il libretto non esiste!\n");
         sleep(1);
         return;
}
else
{
        ....
}

Codice: Seleziona tutto

printf("Inserisci il voto (min 18 max 30): ");
scanf("%d",&libretto.voto);
quì non fai un controllo per verificare se è davvero da 18 a 30, potresti utilizzare un'altro do while in modo da ripetere la richiesta in caso di valore errato, anzi di terminare la funzione senza alcun motivo,idem per i CFU

Codice: Seleziona tutto

printf("Inserisci la data (gg/mm/aaaa): ");
scanf("%s",&libretto.data);
quì potevi utilizzare sscanf in modo di poter verificare l'inserimento in modo corretto.

Codice: Seleziona tutto

printf("Vuoi inserire un altro esame? (s/n): ");
scanf("%s",&rsp);
perchè prendi una stringa ? devi inserire un s o una n quindi ti basta un char.
Potevi farla molto meglio ;)
nella funzione calcola_media ti sconsiglio di usare strcat ma di usare strncat la versione SICURA, perchè così sei a rischio di BoF
oppure usi scanf("%50s",nome_libretto); in modo da evitare nomi troppo lunghi.
Ora putroppo non ho più tempo, più tardi vedos e ci sono altre cose che potresti migliorare ;)
Saluti

Avatar utente
boh
Linux 4.x
Linux 4.x
Messaggi: 1027
Iscritto il: ven 16 set 2005, 0:00
Slackware: 14.2 (x64)
Kernel: 4.4.111
Desktop: KDE 4.14.32
Località: Milano
Contatta:

Re: Gestione Esami Universitari

Messaggio da boh »

Per evitare l'errore all'inserimento della lettera apporta questa modifica allo switch:

Codice: Seleziona tutto

switch(scelta){
         case 1:
            crea_libretto();
            break;
         case 2:
            add_esame();
            break;
         case 3:
            visualizza_libretto();
            break;
         case 4:
            calcola_media();
            break;
         default:
            printf("Inserimento errato!");
      }
   }while(scelta!=5);
Il break all'ultima istruzione dello switch è opzionale :)
"Be yourself. Everyone else is already taken." ~ Oscar Wilde

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Gestione Esami Universitari

Messaggio da targzeta »

Senza nulla togliere al lavoro, ma non era più semplice un file ben formato su cui avvii uno script che calcola la media? Quarda come ti risolvo i problemi:
j0kers ha scritto:Aggiungere esami

Codice: Seleziona tutto

nano file_esami.txt
j0kers ha scritto:Visualizzare esami

Codice: Seleziona tutto

cat file_esami.txt
j0kers ha scritto:Calcolare la media dei voti, somma dei CFU e somma totale degli esami sostenuti

Codice: Seleziona tutto

mio_script.sh file_esami.txt
Quello che devi fare è solo uno script awk o perl o altro,
Emanuele

P.S. Ripeto, non voglio essere polemico, è sempre bello vedere qualcuno che si cimenta in queste cose, solo che magari uno non ci pensa e le soluzioni migliori sono sempre dietro l'angolo.
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

Avatar utente
j0kers
Linux 2.x
Linux 2.x
Messaggi: 418
Iscritto il: dom 22 lug 2007, 1:31
Slackware: 13
Kernel: 2.6.32
Desktop: xfce4

Re: Gestione Esami Universitari

Messaggio da j0kers »

Grazie per le risposte, rispondo a tutti.

Per spina:
Hai ragione però ho cercato quando meno possibile di utilizzare i comandi bash e di risolvere i problemi con il codice C.
Altrimenti lo creavo direttamente in bash shell e risolvevo molti problemi.

Per redskull:
La tua soluzione
if((esami=fopen(libretto_file,"a"))==NULL)
{
printf("Il libretto non esiste!\n");
sleep(1);
return;
}
else
{
....
}
non è molto esatta perchè apredo il file come append se inserisco un nome che non esiste il file viene comunque creato quindi la condizione di errore
non si verifica mai.
Per questo ho fatto una doppia apertura prima come "r" e poi come "a"
Con "r" se il file non esiste allora genera l'errore con "a" lo crea.
Inoltre per quanto riguarda i controlli su CFU e Voto se fai caso il controllo viene effettuato alla fine.

Per quanto riguarda il controllo nella main lo cambierò usando fgets.
Per gli sleep ??? Che mi consigliate??? In modo da bloccare le schermate 8)
comunque grazie a tutti per i consiglia

Avatar utente
targzeta
Iper Master
Iper Master
Messaggi: 6629
Iscritto il: gio 3 nov 2005, 14:05
Nome Cognome: Emanuele Tomasi
Slackware: 64-current
Kernel: latest stable
Desktop: IceWM
Località: Carpignano Sal. (LE) <-> Pisa

Re: Gestione Esami Universitari

Messaggio da targzeta »

j0kers ha scritto:...
Per spina:
Hai ragione però ho cercato quando meno possibile di utilizzare i comandi bash e di risolvere i problemi con il codice C.
Altrimenti lo creavo direttamente in bash shell e risolvevo molti problemi.
...
Ok, allora buon lavoro :thumbright:

Emanuele
Se pensi di essere troppo piccolo per fare la differenza, prova a dormire con una zanzara -- Dalai Lama

Avatar utente
j0kers
Linux 2.x
Linux 2.x
Messaggi: 418
Iscritto il: dom 22 lug 2007, 1:31
Slackware: 13
Kernel: 2.6.32
Desktop: xfce4

Re: Gestione Esami Universitari

Messaggio da j0kers »


printf("Vuoi inserire un altro esame? (s/n): ");
scanf("%s",&rsp);

perchè prendi una stringa ? devi inserire un s o una n quindi ti basta un char.
Perchè se mettevo %c non si fermava sull'inserimento del carattere bensì andava avanti con il programma
Strano ma vero.

Avatar utente
RedSkull92
Linux 3.x
Linux 3.x
Messaggi: 567
Iscritto il: mar 21 apr 2009, 17:25
Slackware: 64bit -current
Kernel: 3.5.4
Desktop: FluxBox
Località: Palermo
Contatta:

Re: Gestione Esami Universitari

Messaggio da RedSkull92 »

Perchè se mettevo %c non si fermava sull'inserimento del carattere bensì andava avanti con il programma
Strano ma vero.
metti un fflush(stdin) dopo lo scanf e si sistema.
Inoltre per quanto riguarda i controlli su CFU e Voto se fai caso il controllo viene effettuato alla fine.
Si l'ho notato infatti ho scritto che è meglio effettuare un controllo con un do while in questo modo se si digita un numero errato viene riprosta la domanda di inserire il valore finchè non si inserire un numero corretto, nel modo fatto da te invece controlli alla fine ed esci dalla funzione se c'è errore, non ha senso,se io sbaglio dato dovrò riandare nel menu, fare la scelta e reinmettere i dati, molto molto scomodo, meglio fare il controllo prima così da evitare problemi.

Avatar utente
j0kers
Linux 2.x
Linux 2.x
Messaggi: 418
Iscritto il: dom 22 lug 2007, 1:31
Slackware: 13
Kernel: 2.6.32
Desktop: xfce4

Re: Gestione Esami Universitari

Messaggio da j0kers »

Ok allora sistemerò anche questo.

Avatar utente
j0kers
Linux 2.x
Linux 2.x
Messaggi: 418
Iscritto il: dom 22 lug 2007, 1:31
Slackware: 13
Kernel: 2.6.32
Desktop: xfce4

Re: Gestione Esami Universitari

Messaggio da j0kers »

Per evitare l'errore all'inserimento della lettera apporta questa modifica allo switch:

Codice: Seleziona tutto
switch(scelta){
case 1:
crea_libretto();
break;
case 2:
add_esame();
break;
case 3:
visualizza_libretto();
break;
case 4:
calcola_media();
break;
default:
printf("Inserimento errato!");
}
}while(scelta!=5);
Non va bene.E' la stessa cosa il problema sta sulla scanf dell'intero.Credo che cambierò utilizzato sscanf o fgets.8)

Avatar utente
Blallo
Packager
Packager
Messaggi: 3302
Iscritto il: ven 12 ott 2007, 11:37
Nome Cognome: Savino Liguori
Slackware: 14.2 / 12.2
Kernel: 4.4.14-smp
Desktop: DWM
Località: Torino / Torremaggiore (FG)
Contatta:

Re: Gestione Esami Universitari

Messaggio da Blallo »

più che altro vorrei capire perchè hai fatto in modo che ogni funzione apra e chiuda i file
fai una lista e poi magari fai una "chiudi file" per salvare tutto
aprire ogni volta è un po' pesante, e inoltre devi aggiungere il nome del file ogni volta

Avatar utente
j0kers
Linux 2.x
Linux 2.x
Messaggi: 418
Iscritto il: dom 22 lug 2007, 1:31
Slackware: 13
Kernel: 2.6.32
Desktop: xfce4

Re: Gestione Esami Universitari

Messaggio da j0kers »

Infatti ho cambiato il menu in questo modo:

Codice: Seleziona tutto

	
printf("\nGestione Libretto Esami Universitari\n\n");
printf("Menu Principale: \n");
printf("1) - Crea un libretto esami\n");
printf("2) - Apri libretto\n");
printf("3) - Aggiungi un esame ad un libretto\n");
printf("4) - Visualizza esami di libretto\n");
printf("5) - Calcola la media degli esami sostenuti\n");
printf("6) - Esci dal programma\n\n");
printf("Scegli una opzione: ");
Dove prima di qualsiasi operazione bisogna aprire il libretto (file testo) altrimenti genera un errore
di file non trovato.

Per quanto riguarda il controllo nella scanf della main ho risolto in questo modo.

Codice: Seleziona tutto

if(scanf("%d",&scelta)==0){
	printf("Valore non valido!\n");
	break;
}
Per quanto riguarda l'inserimento di un nuovo esame se uso la fgets e sscanf non si ferma sull'immissione dati

Codice: Seleziona tutto

fgets(buffer,MAX,stdin);
sscanf(buffer,"%s",&libretto.nome);
MAX=100 e buffer[MAX]
Perchè non mi fa leggere da stdin ?

birg81
Linux 3.x
Linux 3.x
Messaggi: 760
Iscritto il: lun 16 gen 2006, 10:57
Nome Cognome: Biagio
Slackware: 12.2
Kernel: 3.4.7
Desktop: LxDE
Distribuzione: ArchLinux
Località: Castellammare di Stabia (NA)
Contatta:

Re: Gestione Esami Universitari

Messaggio da birg81 »

Mi rendo conto che attrarrò le critiche di molti ma benché un vero programmatore scrive in C se non in linguaggio macchina, forse era il caso di scriverlo in Java il ché è importantissimo per l'utente medio

Avatar utente
Blallo
Packager
Packager
Messaggi: 3302
Iscritto il: ven 12 ott 2007, 11:37
Nome Cognome: Savino Liguori
Slackware: 14.2 / 12.2
Kernel: 4.4.14-smp
Desktop: DWM
Località: Torino / Torremaggiore (FG)
Contatta:

Re: Gestione Esami Universitari

Messaggio da Blallo »

birg81 ha scritto:Mi rendo conto che attrarrò le critiche di molti ma benché un vero programmatore scrive in C se non in linguaggio macchina, forse era il caso di scriverlo in Java il ché è importantissimo per l'utente medio
e che c'entra scusa? :shock:

Rispondi