Visualizzazione dei risultati da 1 a 8 su 8
  1. #1
    Utente bannato
    Registrato dal
    Oct 2010
    Messaggi
    1,219

    [C]Programma con struct si blocca

    Salve,sto provando a scrivere un programma utilizzando lo struct,che chiede innanzitutto quanti studenti ci sono (lo struct e' un array contenente i dati dei vari studenti),poi per ogni studente chiede nome,cognome,voto di tre materie (per tutti gli studenti),e registra tutti questi dati nei vari elementi dello struct.
    Poi quando l' utente digita un cognome deve cercare quello studente tra i vari elementi dello struct,e stampare la sua media.
    Premetto che non mida nessun errore ne warning,pero' quando passo ad eseguirlo appena digito il primo voto l' esecuzione si blocca.
    Ecco il codice:
    codice:
    #include<stdio.h>
    #include<string.h>
    typedef struct
    {
      char nome[31],cognome[31];
      float inglese,fisica,matematica;
    }studente;
    main()
    {
      char l[31],s[31];
      studente classe[100];
      int m,i,n;
      printf("Quanti studenti ci sono? ");
      scanf("%d",&n);
      for(i=0;i<n;i++)
      {
        printf("Studente %d:\n",(i+1));
        printf("Nome: ");
        scanf("%s",classe[i].nome);
        printf("Cognome: ");
        scanf("%s",classe[i].cognome);
        printf("Voto inglese? ");
        scanf("%f",classe[i].inglese);
        printf("Voto fisica? ");
        scanf("%f",classe[i].fisica);
        printf("Voto matematica? ");
        scanf("%f",classe[i].matematica);
      }
      while(l!="esci")
      {
        printf("Digita cognome studente o esci per terminare: ");
        gets(l);
        for(i=0;i<n;i++)
          {
            if(strcmp(l,classe[i].cognome)==0)
              puts(classe[i].nome);
              puts(classe[i].cognome);
              printf("%d",(classe[i].fisica+classe[i].inglese+classe[i].matematica)/3);
          }
      }
      
      return 0;
    }
    Eppure sembra tutto corretto,perche' si blocca?

  2. #2
    Utente di HTML.it L'avatar di Alex'87
    Registrato dal
    Aug 2001
    residenza
    Verona
    Messaggi
    5,802

    Re: [C]Programma con struct si blocca

    Originariamente inviato da ramy89
    while(l!="esci")
    Per confrontare due stringhe si usa il metodo strcmp E sarebbe meglio trasformare quel while in un do-while. Prova a dirmi il perché...
    SpringSource Certified Spring Professional | Pivotal Certified Enterprise Integration Specialist
    Di questo libro e degli altri (blog personale di recensioni libri) | ​NO M.P. TECNICI

  3. #3
    Utente bannato
    Registrato dal
    Oct 2010
    Messaggi
    1,219
    Gia',perche' non puo' verificare se le due stringhe sono uguali prima che la stringa l venga inizializzata.
    Ho sostituito l' ultima parte con questa:
    codice:
    do
      {
        printf("Digita cognome studente o esci per terminare: ");
        gets(l);
        for(i=0;i<n;i++)
          {
            if(strcmp(l,classe[i].cognome)==0)
              puts(classe[i].nome);
              puts(classe[i].cognome);
              printf("%d",(classe[i].fisica+classe[i].inglese+classe[i].matematica)/3);
          }
      }while((strcmp(l,"esci"))!=0);
    Pero' il problema viene nel blocco precedente: appena digito il voto di inglese (un float) mi si blocca tutto,dice "il programma ha smesso di funzionare".
    Si impalla
    Eppure la prima parte mi sembra corretta.

  4. #4
    Utente di HTML.it
    Registrato dal
    Mar 2010
    Messaggi
    45

    Re: [C]Programma con struct si blocca

    Devi cambiare questa parte :
    codice:
        scanf("%f",classe[i].inglese);
        printf("Voto fisica? ");
        scanf("%f",classe[i].fisica);
        printf("Voto matematica? ");
        scanf("%f",classe[i].matematica);
    con questa:

    codice:
        scanf("%f",&classe[i].inglese);
        printf("Voto fisica? ");
        scanf("%f",&classe[i].fisica);
        printf("Voto matematica? ");
        scanf("%f",&classe[i].matematica);
    devi mettere un & prima della variabile,

    Ciao,
    Doch

  5. #5
    Utente bannato
    Registrato dal
    Oct 2010
    Messaggi
    1,219
    Gia',hai ragione.
    Ho riscritto il codice completo cosi':
    codice:
    #include<stdio.h>
    #include<string.h>
    typedef struct
    {
      char nome[31],cognome[31];
      float inglese,fisica,matematica;
    }studente;
    main()
    {
      char l[31],s[31];
      studente classe[100];
      int m,i,n,k;
      printf("Quanti studenti ci sono? ");
      scanf("%d",&n);
      for(i=0;i<n;i++)
      {
        printf("Studente %d:\n",(i+1));
        printf("Nome: ");
        scanf("%s",classe[i].nome);
        printf("Cognome: ");
        scanf("%s",classe[i].cognome);
        printf("Voto inglese? ");
        scanf("%f",&classe[i].inglese);
        printf("Voto fisica? ");
        scanf("%f",&classe[i].fisica);
        printf("Voto matematica? ");
        scanf("%f",&classe[i].matematica);
      }
      do
      {
        if(k>0)
          printf("\nDigita cognome studente o esci per terminare: ");
        gets(l);
        for(i=0;i<n;i++)
          {
            if(strcmp(l,classe[i].cognome)==0)
            {
              printf("%s %s",classe[i].nome,classe[i].cognome);
              printf(",media voti: %.1f\t",(classe[i].inglese+classe[i].matematica+classe[i].fisica)/3);
            }
          }
        k++;
      }while((strcmp(l,"esci"))!=0);
      
      return 0;
    }
    Cosi' funziona,ma ho ancora un dubbio.
    Focalizzate la vostra attenzione su questa parte del codice:
    codice:
    if(k>0)
          printf("\nDigita cognome studente o esci per terminare: ");
        gets(l);
        for(i=0;i<n;i++)
          {
            if(strcmp(l,classe[i].cognome)==0)
            {
              printf("%s %s",classe[i].nome,classe[i].cognome);
              printf(",media voti: %.1f\t",(classe[i].inglese+classe[i].matematica+classe[i].fisica)/3);
            }
          }
        k++;
    La variabile k l' avevo inizializzata a zero per un semplice motivo:forse per un bug del compilatore (o sono io che sbaglio qualcosa? ),se non metto la condizione di stampare "Digita cognome studente o esci per terminare" solo quando k e' maggiore di 0 (quindi me lo stampa dalla seconda volta in poi),me lo stampa due volte e poi mi chiede di inserire l (con la gets).
    L' ho "corretto" specificando di non stamparmi "Digita cognome studente o esci per terminare" la prima volta,ma di saltarlo.
    Pero' non so bene perche' fa cosi',ma in teoria non dovrebbe chiedermi subito di inserire l gia' dalla prima volta?

  6. #6
    Utente di HTML.it
    Registrato dal
    Mar 2010
    Messaggi
    45
    Devi svuotare il buffer prima del ciclo do while, facendo cosi:
    codice:
      while(getchar() != '\n');
      do
      {
    
        printf("\nDigita cognome studente o esci per terminare: ");
        gets(l);
        for(i=0;i<n;i++)
          {
            if(strcmp(l,classe[i].cognome)==0)
            {
              printf("%s %s",classe[i].nome,classe[i].cognome);
              printf(",media voti: %.1f\t",(classe[i].inglese+classe[i].matematica+classe[i].fisica)/3);
            }
          }
        k++;
      }while((strcmp(l,"esci"))!=0);
      
      return 0;
    }
    comunque ti consiglio di non usare gets che non è sicuro, usa fgets...

    Ciao,
    Doch

  7. #7
    Utente bannato
    Registrato dal
    Oct 2010
    Messaggi
    1,219
    Scusa ma ho ancora un dubbio con la getchar (e in generale le funzioni per ricevere o stampare) che mi fa sempre casini nei cicli.
    In questo caso il pezzo di codice:
    codice:
    while(getchar() != '\n');
    Da un' istruzione vuota nel while,come a dire: fermati finche' non digito accapo.
    Cosi' svuota il buffer che era gia' pieno.Ma se per ipotesi fosse stata la prima volta che usavo la getchar,l' istruzione ha l' effetto di ritardare la partenza del programma,posto un codice come esempio:
    codice:
    do
        {
        while(getchar()!=10)
          ;
        printf("Digita base: ");
        scanf("%f",&base);
        printf("Digita esponente: ");
        scanf("%d",&esp);
        printf("%.0f^%d= %.2f",base,esp,potenza(base,esp));
        printf("\ncontinuare o uscire?");
        gets(terminatore);
        printf("\n");
        }while(strcmp(terminatore,"esci")!=0);
    In questo caso siccome era la prima volta che usavo la getchar,all' inizio del programma non compare nessuna scritta e se digito un qualsiasi tasto mi va avanti con l' esecuzione del programma normale (Mi stampa: digita base,riceve base,ecc...).
    Ma come si fa a svuotare il buffer in un ciclo essendo la prima volta che uso la getchar?
    In questo caso se sposto la parte del codice che dice:
    codice:
    while(getchar()!=10)
          ;
    in fondo al ciclo,se digito esci non mi finisce il ciclo,se lo metto all' inizio come ho fatto nell' esempio non parte finche' non digito un tasto...ma devo per forza usare l' espressione:
    codice:
    if(i>=1)
    while(getchar()!=10)
          ;
    Con i che e' una variaible inizializzata a zero e incrementata a fine ciclo...oppure c'e' un altro metodo?

  8. #8
    Originariamente inviato da Doch88
    comunque ti consiglio di non usare gets che non è sicuro, usa fgets
    Tralasciando la domanda di ramy89 che, sinceramente, non ho capito, approfitto dell’espressione di Dock88 per approfondire tale questione, ribadendo la veridicità di tale affermazione.
    La funzione gets è da evitare e deprecare per un motivo semplice: non consta di controlli interni per cui può accettare in input qualunque stringa si inserisca, indipendentemente dalle dimensioni del buffer dichiarato.
    Tipico esempio:
    codice:
    int main()
    {
        char  c1[] = "ABCD";
        char  c2[] = "LMNO";
        
        puts(c1);
        puts(c2);
        
        puts("Inserisci 4 caratteri:");
        gets(c2);
    
        putchar('\n');
        puts(c1);
        puts(c2);
        
        return(0);
    }
    Tale procedura richiede l’inserimento di 4 caratteri e stampa sia la stringa “ABCD” che il nostro input (ammettiamo per esempio “1234”), memorizzato tramite la gets nella variabile c2: il nostro output sarà quindi “ABCD” e “1234”.
    Se invece inseriamo la stringa “1234567890” anziché “1234” vedremo che il nostro output sarà questo: “90” e “1234567890”
    Come è facilmente intuibile si ha una *sovrascrittura* della memoria, con possibili conseguenze anche gravi per la stabilità del nostro programma (e non solo).
    Al posto di gets si raccomanda quindi l’utilizzo di fgets.

    Un discorso diverso, ma per certi versi simile, è riservato per la chiamata System “PAUSE”: qualora emerga da qualche discussione, provvederò a spiegare come mai è preferibile evitare il suo uso e quali sono i sostituti perfetti.


    Ciao

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.