C : chiediamo consigli agli esperti ;)

10 risposte [Ultimo messaggio]
Ritratto di anubis
anubis
(Guru)
Offline
Guru
Iscritto: 07/04/2007
Messaggi: 3656

Visto che il codice di per se funziona, forse questo topic è inutile, ma sarei veramente curioso di sapere cosa ne pensate:

#include <stdio.h>
#include <stdlib.h>
#define SIZE 2
#define LUNGHEZZA 20
 
typedef struct {
    int giorno;
    int mese;
    int anno;
} data;
 
 
typedef struct {
    char nome[LUNGHEZZA];
    char cognome[LUNGHEZZA];
    data nascita;
    int matricola;
} studente;
 
 
int importData (data *);
void importStudente (studente *m);
 
int main () {
 
    studente classe[SIZE];
    int i;
 
    //inizializzo array classe
    for (i=0; i
    strcpy(classe[i].nome,".");
    strcpy(classe[i].cognome,".");
    classe[i].nascita.giorno=0;
    classe[i].nascita.mese=0;
    classe[i].nascita.anno=0;
    classe[i].matricola=0;
    }
 
 
    for (i=0; i<SIZE; i++) {
    importStudente(&classe[i]);
    }
 
    for (i=0; i[/i][/i][/i][/i][/i][/i][/i]
[i][i][i][i][i][i]<SIZE; i++) {[/i][/i][/i][/i][/i][/i]
[i][i][i][i][i][i][i]    printf("Nome: %s", classe[i].nome);
    printf("Cognome: %s", classe[i].cognome);
    printf("Data di Nascita: %d/%d/%d\n", classe[i].nascita.giorno, classe[i].nascita.mese, classe[i].nascita.anno);
    printf("Matricola: %d\n", classe[i].matricola);
    printf("\n");
    }
 
    return 0;
}
 
void importStudente (studente *mystudente) {
 
    printf("Digitare il Nome dello Studente:\n");
    fgets(mystudente->nome, LUNGHEZZA, stdin);
 
    printf("Digitare il Cognome dello Studente:\n");
    fgets(mystudente->cognome, LUNGHEZZA, stdin);
 
    printf("Digitare la data di nascita dello Studente:\n");
    while (importData (&mystudente->nascita) == 1) {
    }
 
    printf("Digitare il Numero di Matricola dello Studente:\n");
    scanf("\n%d", &mystudente->matricola);
 
    /* Devo intercettare "\n" o con un utilizzo ricorsivo
     * di questa funzione, andrebbe a terminare l'fgets
     * per aquisire il nome.
     */
 
    while( getchar()!='\n');
 
}
 
//La funziona ritorna 0 se la data è valida, 1 altrimenti
 
int importData (data *mydata) {
 
    data controllo = {0,0,0};
 
    printf("Digitare la data nel formato gg/mm/aaaa: ");
    scanf("%d/%d/%d", &controllo.giorno, &controllo.mese, &controllo.anno);
 
 
    if ( (0 > controllo.mese) || (controllo.mese > 12) ) {
        printf("Data non valida, il mese non e' corretto\n");
        return 1;
    }
    else {
        switch (controllo.mese) {
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                if ( (0 > controllo.giorno) || (controllo.giorno > 31) ) {
                    printf("Data non valida, il giorno non e' corretto\n");
                    return 1;
                }
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                if ( (0 > controllo.giorno) || (controllo.giorno > 30) ) {
                    printf("Data non valida, il giorno non e' corretto\n");
                    return 1;
                }
                break;
            case 2:
                if( ( ( (controllo.anno%4) == 0) && (controllo.anno%100 !=0) ) || (controllo.anno%400 == 0)) {
                        if ( (0 > controllo.giorno) || (controllo.giorno > 29) ) {
                            printf("Data non valida, il giorno non e' corretto\n");
                            return 1;
                        }
                }
 
                else {
                        if ( (0 > controllo.giorno) || (controllo.giorno > 28) ) {
                            printf("Data non valida, il giorno non e' corretto\n");
                                if (controllo.giorno == 29)
                                printf("L'anno %d NON e' bisestile\n", controllo.anno);
                            return 1;
                        }
                }
                 break;
            default:
                break;
        }
 
    }
 
    mydata->giorno = controllo.giorno;
    mydata->mese   = controllo.mese;
    mydata->anno   = controllo.anno;
 
    return 0;
}
[/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i]
  [i][i][i][i][i][i][i][i][i][i][i][i] 

eventuali modifiche, miglioramenti, critiche??

Il prossimo passo sarà quello di stampare i dati relativi agli studenti non più studente per studente, ma in una tabella (nome, cognome, data nascita, matricola) con gli elementi ordinati alfabeticamente (per nome e cognome) o per anno (dal più vecchio al più giovane) o in ordine crescente (per le matricole), in base alle richieste dell'utente...[/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i][/i]

OpenSUSE Member,Packman Packager, Education Project Admin, LXDE Project Admin
Powered by http://en.opensuse.org/HP_Pavilion_dv6855el

Ritratto di anubis
anubis
(Guru)
Offline
Guru
Iscritto: 07/04/2007
Messaggi: 3656

c'è qualcosa che non va... non gli piace il codice Tongue
eccolo qui:
http://pastebin.com/m2401caf1

OpenSUSE Member,Packman Packager, Education Project Admin, LXDE Project Admin
Powered by http://en.opensuse.org/HP_Pavilion_dv6855el

Ritratto di Moreno
Moreno
(Monster)
Offline
Monster
Iscritto: 03/10/2005
Messaggi: 364

Ciao

L'unica critica di fondo che si può fare al tuo programma riguarda l'uso della struttura data.
L'uso di una struttura del genere rende un incubo qualsiasi operazione statistica (anche il solo semplice sort) su tale campo.

Da che programmazione è programmazione i campi data / ora vengono salvate sempre in un unico campo numerico con lo 0 fisso ad una determinata data (se non ricordo male 1/1/1970) questo per rendere semplicissime le operazioni sulle date (specialmente le comparazioni).

Se vuoi evitare la conversione della data puoi usare una stringa nel formato AAAAMMGG o un long int con Anno*10000 + Mese*100 + Giorno

Ciao Ciao, Moreno

Ebbene sì confesso sono un infiltrato di http://www.mandrakeitalia.org ma mi piace girare il Mondo.
Profilo

Ritratto di oNaSsIs
oNaSsIs
(Geek)
Offline
Geek
Iscritto: 12/12/2006
Messaggi: 143

Moreno ha ragione. In C soprattutto è impensabile fare un ordinamento su delle strutture allocate staticamente (costa tempo e memoria). Io fossi in te, prima di completare questo progettino,andrei un altro pochino avanti nello studio. Di solito per questo genere di operazioni si usa l'allocazione dinamica della memoria (attraverso i puntatori) e una struttura dati che si presti bene al tipo di operazioni da fare (ad esempio una lista, se ordinata potrebbe ridurre ulteriormente il numero di calcoli, magari per operazioni che vengono effettuate con una certa frequenza).
Senza dimenticare che faciliterebbero non poco l'implementazioni di qualsiasi algoritmo di ricerca/ordinamento.

Ritratto di anubis
anubis
(Guru)
Offline
Guru
Iscritto: 07/04/2007
Messaggi: 3656

l'aritmetica dei puntatori l'ho finita questa mattina, ma forse sono tonto, non vedo come potrei trovarne vantaggio qui.
@ moreno.
ho cercato qualcosa che mi facesse vedere come gestire le date come suggerito ma ho trovato solo questo:
http://thedevelopers.netsons.org/c-funzione-di-gestione-data/  (questo controllo sulla data è anche più sofisticato del mio Smile )
qui invece ho trovato praticamente la stessa struttura che ho fatto:
http://www.mrwebmaster.it/cplusplus/guide/gestione-date_290.html 

potresti farmi un esempio? Ad onor di cronaca sono interessato per mio sapere personale, dato che l'esercizio chiedeva espressamente di usare quel tipo di struttura!

OpenSUSE Member,Packman Packager, Education Project Admin, LXDE Project Admin
Powered by http://en.opensuse.org/HP_Pavilion_dv6855el

Ritratto di oNaSsIs
oNaSsIs
(Geek)
Offline
Geek
Iscritto: 12/12/2006
Messaggi: 143

Io parlavo di aritmetica dei puntatori nell'altro topic, comunque pensavo ti sarebbe tornata utile nel caso tu avessi voluto definire la dimensione dell'array a run time. Ad esempio:

studente *s;
int num_studenti;
printf("Inserire numero studenti: ");
scanf("%d",&num_studenti);
s = (studente*) malloc(num_studenti*sizeof(studente)); 
   
In alcuni codici puoi trovare anche il malloc senza niente davanti, perchè avviene un casting implicito, comunque per avere la certezza assoluta che tutto funzioni metterlo non è certo di troppo, anzi. A questo punto per accedere ai vari studenti ti basterebbe usare l'aritmetica dei  puntatori:
for(i=0;i
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (s+i)->nome=....
   

PS: sto abbozzando questo codice così su due piedi, potrebbe esserci qualche errore sintattico, ma la logica è giusta. Se hai qualche roblema posta pure.

Ritratto di Moreno
Moreno
(Monster)
Offline
Monster
Iscritto: 03/10/2005
Messaggi: 364

Ciao

Non mi stavo riferendo alle routines di input ed analisi della data ma proprio alla variabile di memorizzazione della stessa.

Invece della struttura data sarebbe meglio usare una variabile data di tipo time_t definito in time.h

#ifndef _TIME_T
#define _TIME_T
typedef long time_t;
#endif

ed usare le routines mktime e localtime per operare sulla variabile (per maggiori info http://www.cplusplus.com/reference/clibrary/ctime/ )

Se vuoi ad esempio ordinare i tuoi allievi in ordine di data di nascita con la tua struttura ti spari mentre con variabili time_t è una baggianata data che a numero maggiore corrisponde data maggiore.

Ebbene sì confesso sono un infiltrato di http://www.mandrakeitalia.org ma mi piace girare il Mondo.
Profilo

Ritratto di wal7er
wal7er
(Guru)
Offline
Guru
Iscritto: 21/09/2007
Messaggi: 572

Oltre ai consigli precedenti, ne aggiungo uno di stile:
se hai:

...
if ( ... ) {
&nbsp;&nbsp;&nbsp;&nbsp; ...
&nbsp;&nbsp;&nbsp;&nbsp; return 1
}
else {
&nbsp;&nbsp;&nbsp;&nbsp; ...
&nbsp;&nbsp;&nbsp;&nbsp; return 2
}
 

puoi sempre semplificare il codice con:

...
if ( ... ) {
&nbsp;&nbsp;&nbsp;&nbsp; ...
&nbsp;&nbsp;&nbsp;&nbsp; return 1
}
...
return 2

HP Pavilion dv5-1110el powered by OpenSUSE 13.2 64bit

http://linuxcounter.net/cert/432576.png

Ritratto di ap1978
ap1978
(Guru)
Offline
Guru
Iscritto: 01/10/2004
Messaggi: 2972

Citazione:

l'aritmetica dei puntatori l'ho finita questa mattina, ma forse sono tonto, non vedo come potrei trovarne vantaggio qui.
@ moreno.
ho cercato qualcosa che mi facesse vedere come gestire le date come suggerito ma ho trovato solo questo:
http://thedevelopers.netsons.org/c-funzione-di-gestione-data/  (questo controllo sulla data è anche più sofisticato del mio Smile )
qui invece ho trovato praticamente la stessa struttura che ho fatto:
http://www.mrwebmaster.it/cplusplus/guide/gestione-date_290.html 

potresti farmi un esempio? Ad onor di cronaca sono interessato per mio sapere personale, dato che l'esercizio chiedeva espressamente di usare quel tipo di struttura!

 
Se è richiesto l'uso di una struttura, semplicemente ignora i commenti precedenti, che fanno riferimento a convenzioni che, eventualmente, potrai imparare più avanti. Ora pensa ad imparare il C Smile
Quanto all'uso dell'allocazione dinamica in C, aspetta ad usarla quando te la spiegheranno. E in ogni caso è un'esperienza dolorosa a confronto con altri linguaggi.
Quanto ad ordinare per data, con la struttura non ottieni il massimo dell'efficienza, ma non è un'operazione così complicata. Devi semplicemente usare un algoritmo di ordinamento tre volte, in sequenza:
- Ordina per anno
- Ordina per mese
- Ordina per giorno
Ciao

ap Big Grin

Ritratto di ap1978
ap1978
(Guru)
Offline
Guru
Iscritto: 01/10/2004
Messaggi: 2972

Citazione:

Oltre ai consigli precedenti, ne aggiungo uno di stile:
se hai:

...
if ( ... ) {
&nbsp;&nbsp;&nbsp;&nbsp; ...
&nbsp;&nbsp;&nbsp;&nbsp; return 1
}
else {
&nbsp;&nbsp;&nbsp;&nbsp; ...
&nbsp;&nbsp;&nbsp;&nbsp; return 2
}
 

puoi sempre semplificare il codice con:

...
if ( ... ) {
&nbsp;&nbsp;&nbsp;&nbsp; ...
&nbsp;&nbsp;&nbsp;&nbsp; return 1
}
...
return 2
  

 
 Vero, ma non mi piace a livello di leggibilità. Preferisco la prima versione e un return di default per evitare un warning

ap Big Grin

Ritratto di wal7er
wal7er
(Guru)
Offline
Guru
Iscritto: 21/09/2007
Messaggi: 572

Non da warning ("gcc -Wall -ansi ...").
Era solo per accorciare il codice dove possibile.

HP Pavilion dv5-1110el powered by OpenSUSE 13.2 64bit

http://linuxcounter.net/cert/432576.png