[C] popolare una struct da tastiera

di il
7 risposte

[C] popolare una struct da tastiera

Ciao a tutti,
sto scrivendo un programma che popoli una struct (NOME,COGNOME,ETA') con input da tastiera.
non capisco perchè una volta popolata non stampi.. il programma infatti crasha appena raggiunge la printf, sapreste dirmi perché?
#include <stdio.h>
#include <stdlib.h>
#define MAX_STRINGA 200
#define CONTATTI 3

typedef char String[MAX_STRINGA];
typedef struct{
 String nome;
 String cognome;
 int eta;
}Contatto;
typedef Contatto Elenco[CONTATTI];
//int utentepiuvecchio(Contatto[],int N);

int main()
{
    int i,a;
    Elenco elenco;

    for(i=0;i<CONTATTI;i++){
     printf("nome:\n");
     scanf("%s",elenco[i].nome);
     printf("cognome:\n");
     scanf("%s",elenco[i].cognome);
     printf("età:\n");
     scanf("%d",elenco[i].eta);
    }

     printf("inserisci un numero contatto:\n");
     scanf("%d",&a);
     printf("%s %s %d",elenco[a].nome, elenco[a].cognome, elenco[a].eta);
    return 0;
}

7 Risposte

  • Re: [C] popolare una struct da tastiera

    E' la "solita" distrazione (ci casco sempre anche io, beninteso): scanf vuole il puntatore alla variabile da leggere e finché è un array di caratteri gli stai passando proprio quello, mentre invece per l'intero... ecco qua:

    scanf("%d",&elenco.eta)

    si deve passare l'indirizzo del campo "eta".
  • Re: [C] popolare una struct da tastiera

    Ovviamente così come sta è un programma pericoloso perché non c'è il controllo di range sul valore indice che si legge dall'input. Se l'utente assegna un valore maggiore o uguale a CONTATTI il programma andrà in crash.
  • Re: [C] popolare una struct da tastiera

    Cavolo, hai ragione! &! grazie

    si si, mandavo in stampa perchè volevo solamennte controllare dove sbagliavo, ora devo scrivere una funzione che trova il contatto con età maggiore e restituisca i suoi dati. ...procedo:)
  • Re: [C] popolare una struct da tastiera

    Perché scrivere una funzione? Puoi farlo al momento dell'immissione; dichiari due variabili intere: eta_max, inizializzata a zero, e ndx, indice corrispondente; poi appena memorizzata l'età fai un confronto con eta_max e se il valore letto è maggiore memorizzi il nuovo valore e l'indice ndx cui corrisponde il record. A fine immissione dati hai già quello che ti serve, ndx avrà l'indice del record con l'età maggiore.
  • Re: [C] popolare una struct da tastiera

    Alan_Reloaded ha scritto:


    Perché scrivere una funzione? Puoi farlo al momento dell'immissione; dichiari due variabili intere: eta_max, inizializzata a zero, e ndx, indice corrispondente; poi appena memorizzata l'età fai un confronto con eta_max e se il valore letto è maggiore memorizzi il nuovo valore e l'indice ndx cui corrisponde il record. A fine immissione dati hai già quello che ti serve, ndx avrà l'indice del record con l'età maggiore.
    scusa ho letto solo ora!
    si è vero ..
    ma volevo provare con la funzione solo per esercizio

    Ora però non so come fare affinchè la funzione mi restituisca l' indice del vettore struct contenente i dati del contatto con età max. Sapresti aiutarmi?
    #include <stdio.h>
    #include <stdlib.h>
    #define MAX_STRINGA 200
    #define CONTATTI 3
    
    typedef char String[MAX_STRINGA];
    typedef struct
    {
        String nome;
        String cognome;
        int eta;
    } Contatto;
    typedef Contatto Elenco[CONTATTI];
    int utentepiuvecchio(Contatto v[],int n);
    
    int main()
    {
        int i,a,N;
        Elenco elenco;
        int eta_vecchio;
    
        for(i=0; i<CONTATTI; i++)
        {
            printf("nome:");
            scanf("%s",elenco[i].nome);
            printf("cognome:");
            scanf("%s",elenco[i].cognome);
            printf("età:");
            scanf("%d",&elenco[i].eta);
    
        }
    
        /*printf("inserisci un numero contatto:\n");
        scanf("%d",&a);
        printf("%s %s %d",elenco[a].nome, elenco[a].cognome, elenco[a].eta);*/
        eta_vecchio=utentepiuvecchio(elenco,CONTATTI);
        printf("il contatto piu anziano e':%s %s %d anni",elenco[eta_vecchio].nome, elenco[eta_vecchio].cognome, elenco[eta_vecchio].eta);
        return 0;
    }
    
    int utentepiuvecchio(Contatto v[],int n)
    {
        int i,indice;
        int max=0;
    
        for(i=0; i<n; i++)
        {
            if(max<v[i].eta)
                max=v[i].eta;}
                while(max==v[i].eta)
            indice=i;
    
        return indice;
    }
  • Re: [C] popolare una struct da tastiera

    ifThisThenThat ha scritto:


    Ora però non so come fare affinchè la funzione mi restituisca l' indice del vettore struct contenente i dati del contatto con età max. Sapresti aiutarmi?
    Cosa tu volessi ottenere col secondo ciclo nella funzione non mi è chiaro ma metto le mani avanti, dato che non sono un grande scrittore di codice. Io farei come nel codice che allego, con le seguenti osservazioni:

    1) Per mia personale scelta, preferisco che le funzioni ritornino un valore che indichi se tutto è a posto oppure c'è stato un errore. Dato che ti interessa anche l'indice, io ho inserito il puntatore al relativo valore come uno degli argomenti. E' ovvio che si poteva fare in modo semplice facendo in modo che la funzione restituisse un indice negativo in caso di errore, ma in generale non è detto che sia sempre una buona soluzione, così ne vedi una alternativa che potrebbe essere utile in certi casi. In questo caso la funzione ritorna sempre uno ma per esempio potresti voler controllare se ci sono valori duplicati dell'età massima e allora un'organizzazione come quella che ti sottopongo potrebbe tornare comoda. In questo caso, come "esercizio" ho messo tra gli argomenti anche il valore dell'età, assolutamente ridondante dato che ci si arriverebbe dalla funzione chiamante tramite l'indice.

    2) [EDIT] Avevo scritto una sciocchezza e l'ho eliminata

    3) E' solo questione di gusti ma personalmente ho una codifica mia per le variabili e le funzioni. Gli argomenti di quello che scrivo io iniziano sempre con "a_" e sempre a titolo personale penso sarebbe meglio non usare mai variabili dal nome corto, peggio mi sento con "i", "n" e così via. Il perché è questo: quando sei alle prese con sorgenti lunghi potresti voler trovare tutte le occorrenze di una variabile e se anche qualsiasi editor ha l'opzione "parola intera" sarà di poco aiuto: l'editor troverà la tua "i" ma si fermerà anche su "/*di notte tutti ***i*** gatti sono grigi */". E' meglio stabilire un proprio codice per denominare gli enti a seconda del loro ruolo e cercare sempre nomi espressivi. Ma questi non sono errori, sono solo questioni di stile. La variabile deve sempre essere riconoscibile a colpo d'occhio e essere quanto più possibile auto esplicativa. Ultima piccola cosa, consiglio di spaziare un po' in modo da rendere il sorgente facilmente leggibile. Io sono un po' ossessivo compulsivo e come vedi dall'elenco argomenti li dispongo incolonnati ma è per un mio limite, altrimenti faccio fatica a leggere quello che ho scritto magari anni prima.

    4) Un altro piccolo accorgimento, quando possibile, può essere quello di inizializzare certe variabili con valori non significativi, io ho usato -1 per indice ed età. In questo modo, uscito dal ciclo puoi fare ulteriori controlli che le variabili siano state assegnate almeno una volta. Potresti ad esempio aggiungere in cima "#include <assert.h>" e dopo il ciclo nella funzione scrivere:

    assert( (*a_ndx) >= 0 ) ;

    La cosa simpatica è che si può fare in modo che in una eventuale versione "release", gli assert vengano esclusi dalla compilazione (cosa pericolosa ma se il codice è ben debuggato e serve la massima ottimizzazione, si fa normalmente).

    
    #include <stdio.h>
    #include <stdlib.h>
    #define MAX_STRINGA 200
    #define CONTATTI 3
    
    typedef char String[MAX_STRINGA];
    typedef struct
    {
        String nome;
        String cognome;
        int eta;
    } Contatto ;
    
    typedef Contatto Elenco[CONTATTI] ;
    
    int   utentepiuvecchio (int*, int*, Contatto v[] ,int n);
    
    // ...................................................................
    
    int   utentepiuvecchio (int        *a_ndx  ,  // indice nel record
                            int        *a_age  ,  // valore corrispondente eta'
                            Contatto   v[]     ,
                            int        n       )
    {
        int   i         ;
        int   max = -1  ;
    
        (*a_ndx) = -1 ;
        (*a_age) = -1 ;
    
        for(  i = 0 ; i < n ; i++  )
        {
            if(  (v[i].eta) > max   )
            {
                max = (v[i].eta) ;
                (*a_ndx) = i ;
            }
        }
    
        if(  (*a_ndx) >= 0  )
        {
            (*a_age) = (v[*a_ndx].eta) ;
        }
    
        return (1) ;
    }
    
    // ...................................................................
    
    int main()
    {
        int       i, a, N ;
        Elenco    elenco ;
        int       eta_vecchio ;
    
        for(  i = 0 ; i < CONTATTI ; i++  )
        {
            printf("nome:");
            scanf("%s",elenco[i].nome);
            printf("cognome:");
            scanf("%s",elenco[i].cognome);
            printf("eta':");
            scanf("%d",&elenco[i].eta);
        }
    
        /*printf("inserisci un numero contatto:\n");
        scanf("%d",&a);
        printf("%s %s %d",elenco[a].nome, elenco[a].cognome, elenco[a].eta);*/
    
        if(  utentepiuvecchio(&i,&eta_vecchio,elenco,CONTATTI)   )
        {
            printf("il contatto piu anziano e': %s %s %d anni",(elenco[i].nome),(elenco[i].cognome),eta_vecchio);
        }
    
        return (0) ;
    }
    
  • Re: [C] popolare una struct da tastiera

    Cosa tu volessi ottenere col secondo ciclo nella funzione non mi è chiaro ma metto le mani avanti, dato che non sono un grande scrittore di codice. Io farei come nel codice che allego, con le seguenti osservazioni:
    Grazie davvero per il tempo speso mr. Turing e per la breve "guida" alla lettura del codice!
    Si, quel secondo ciclo nella funzione era un residuo che avrei dovuto cancellare ma arrivato a quel punto avevo iniziato ad aggrovigliarmi.
    Ho capito che dovrò esercitarmi ancora un po' con i puntatori ma la soluzione mi è chiara, grazie ancora
Devi accedere o registrarti per scrivere nel forum
7 risposte