Problema con input da fgets

di il
12 risposte

Problema con input da fgets

Salve a tutti, da poco programmo il c e perciò mi scuso in anticipo per la mia ignoranza.
Volevo scrivere un programma che prendesse dei dati in input da tastiera e li scrivesse in codice macchina su un file ("utenti").
ecco il codice:

//fwrite(&a,sizeof(a),1,b)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define fil "utenti"
typedef struct {
   char name[25];
   char sur[25];
   int age;
   char desc[500];
   char mail[50];
   char passwd[50];
   char paese[50];
   char ist[50];
} user;
int main() {
   FILE *b;
   user a;
   int i;
   char p[500];
   printf("\n\n\t    #           m           #                         \n");
   printf("\t mmm#   mmm   mm#mm   mmm   #mmm    mmm    mmm    mmm \n");
   printf("\t#\" \"#  \"   #    #    \"   #  #\" \"#  \"   #  #   \"  #\"  #\n");
   printf("\t#   #  m\"\"\"#    #    m\"\"\"#  #   #  m\"\"\"#   \"\"\"m  #\"\"\"\"\n");
   printf("\t\"#m##  \"mm\"#    \"mm  \"mm\"#  ##m#\"  \"mm\"#  \"mmm\"  \"#mm\"\n\n\n");
   if(!(b=fopen(fil,"a"))) {
     printf("ERRORE:non e' stato possibile aprire il file\n");
     exit(64);
   }
   printf("\t**NUOVO UTENTE**\n\n");
   printf("-nome: ");
   scanf(" %25s",&a.name);
   printf("-cognome: ");
   scanf(" %25s",&a.sur);
   printf("-eta': ");
   scanf(" %d",&a.age);
   printf("-descrizione(breve): ");
   fgets(p, 500, stdin);
   p[strlen(p)-1]=0;
   strncmp(a.desc,p,500);
   strcpy(p,"");
   printf("\n-mail: ");
   scanf(" %50s",&a.mail);
   printf("-password mail: ");
   scanf(" %50s",&a.passwd);
   printf("-paese attuale(continente/stato/regione/provincia/citta' se possibile): ");
   scanf(" %50s",&a.paese);
   printf("-istituto di studio o luogo di lavoro: ");
   fgets(p, 50, stdin);
   p[strlen(p)-1]=0;
   strncmp(a.ist,p,50);
   if((fwrite(&a,sizeof(a),1,b))>0) 
     printf("\n\t||SCRITTURA SU DATABASE AVVENUTA CON SUCCESSO||\n");
   else
     printf("\n\t||SCRITTURA SU FILE FALLITA RITENTARE||\n");
   fclose(b);
   return 0;
}
il programma non ha dato problemi fino alla prima fgets(), qui infatti l'input passa direttamente alla scanf() seguente, stessa cosa con il secondo fgets().
ecco l'output:



	    #           m           #                         
	 mmm#   mmm   mm#mm   mmm   #mmm    mmm    mmm    mmm 
	#" "#  "   #    #    "   #  #" "#  "   #  #   "  #"  #
	#   #  m"""#    #    m"""#  #   #  m"""#   """m  #""""
	"#m##  "mm"#    "mm  "mm"#  ##m#"  "mm"#  "mmm"  "#mm"     //da terminale c'è scritto "database"


	**NUOVO UTENTE**

-nome: rocky
-cognome: balboa
-eta': 72
-descrizione(breve): 
-mail: rocketto@gmail.com
-password mail: rocchettobalbo
-paese attuale(continente/stato/regione/provincia/citta' se possibile): america/usa/?/?/?
-istituto di studio o luogo di lavoro: 
	||SCRITTURA SU DATABASE AVVENUTA CON SUCCESSO||
Qualcuno mi sa spiegare il perchè? Inoltre ho provato anche con la gets() anche se è pericolosa per il programma ma il risultato non è cambiato.
(spero che il perchè non sia cosi banale ).

12 Risposte

  • Re: Problema con input da fgets

    Scanf() lascia nello stream di input il '\n', per cui se chiami fgets() subito dopo scanf(), quella rileva un input anche se non c'è stato intenzionalmente.

    Per "aggirare" l'ostacolo io son solito mettere un "while('\n'!=getchar());" dopo l'ultimo scanf() prima di fgets(). L'effetto è rimuovere dallo stream di input qualsiasi carattere "residuo", incluso il primo '\n'. A quel punto l'fgets() successivo ritornerà all'immissione del prossimo '\n'. Tentare non nuoce...
  • Re: Problema con input da fgets

    Grazie mille AldoBaldo, il codice funziona. tuttavia, potresti spiegarmi perchè con la scritta "while('\n'!=getchar());" funziona ?
  • Re: Problema con input da fgets

    "while('\n'!=getchar());" estrae uno ad uno tutti i caratteri eventualmente ancora presenti nello stream di input, fino ad arrivare all'ultimo '\n' immesso (che viene anch'esso estratto).

    Se ci pensi un attimo, quando chiami fgets() chiedi di prelevare tutti i caratteri immessi fino al primo '\n'. Orbene, se scanf() non ha estratto il '\n' precedente, quando chiami fgets() incappi immediatamente nel '\n' residuo, che viene interpretato come "ah, allora ha già finito con l'input!", per cui fgets() ritorna immediatamente. In effetti, fgets() stava semplicemente "vedendo" un residuo dell'input precedente. Dal che l'inganno.
  • Re: Problema con input da fgets

    Mettiti nella prospettiva delle funzioni...
    Immagina che vengano immessi cinque caratteri piu' '\n'...
    
    |3|2| |1|6|\n|
    
    scanf("%d",&intero); estrae il primo numero
    
    resta...
    | |1|6|\n|
    
     scanf("%d",&intero); estrae il secondo numero
    
    resta...
    |\n|
    
    fgets(unBuffer,dimBuffer,stdin); estrae una stringa
    ...e subito incontra '\n', come se fosse gia' stato premuto invio!
    al che in unBuffer ti ritrovi...
    |\n|\0| e una serie di char non significativi
    Questo per come ho capito io la questione, a forza di prove e intuizioni.
    Se ci sono errori, invito chi ne sa più di me a correggermi (così imparo qualcosa) senza fare sarcasmo, polemiche, predicozzi o altre sgradevolezze.
  • Re: Problema con input da fgets

    Grazie AldoBaldo ho capito tutto adesso, però ho riscontrato un problema che penso centri sempre con la fgets(), infatti ho scritto un codice che fosse in grado di leggere i dati in codice macchina e di stamparli come output dal file:
    
    #include <stdio.h>
    #include <stdlib.h>
    #define fil "utenti"
    typedef struct {   
       char name[25];
       char sur[25];
       int age;
       char desc[500];
       char mail[50];
       char passwd[50];
       char paese[50];
       char ist[50];
    } user;
    int main() {
       user a;
       FILE *b;
       int i=0;
       if(!(b=fopen(fil,"r"))) {
         printf("\nERRORE! apertura del file non riuscita!\n");
         exit(64);
       }
       while((fread(&a,sizeof(a),1,b))>0) {
         printf("\n-UTENTE N* %d :\n-nome: %s.\n-cognome: %s.\n-eta': %d.\n-descrizione: %s.\n-mail: %s.\n-password(mail): %s.\n-stato: %s.\n-istituto o impiego lavorativo: %s.\n",i+1,a.name,a.sur,a.age,a.desc,a.mail,a.passwd,a.paese,a.ist);
         i++;
       } 
       printf("\n|UTENTI ANALIZZATI: %d \n",i);
       return 0;
    }
    
    ed ecco l'output:
    
    -UTENTE N* 1 :
    -nome: rocky.
    -cognome: balboa.
    -eta': 72.
    -descrizione: .
    -mail: rocchetto@gmail.com.
    -password(mail): rockyetto72.
    -stato: america/usa/?/?/?.
    -istituto o impiego lavorativo: .
    
    |UTENTI ANALIZZATI: 1
    
    dove in descrizione ci dovrebbe essere scritto che " e' stato un campione" e in istituto o impiego lavorativo ci dovrebbe essere scritto " sconosciuto" ,
    non capisco il perchè ma penso che centri con l'argomento precedente.
  • Re: Problema con input da fgets

    Secondo me l'errore avviene nel momento in cui "raccogli" i dati per poi salvarli su file. In particolare, questo non è ragionevole:

    strncmp(a.desc,p,500);

    Forse ti e' scappato strncmp() ma volevi usare strncpy()? Anche perché appena più avanti "svuoti" il buffer p con strcpy(p,"")...

    Inoltre, ma non so quanto sia rilevante, usi fwrite() e fread() su due file aperti come "a" e "r" (requisiti d'accesso per file di testo), mentre quelle due funzioni credo si debbano usare solo su file aperti come "ab" e "rb" (requisiti d'accesso per file binari). Io ho provato a sostituire le due "stringhette" e il programma ha caricato e visualizzato senza neppure un colpo di tosse i dati precedentemente salvati.
  • Re: Problema con input da fgets

    Grazie, avevi del tutto ragione, si mi era scappato strnmcp() e volevo intendere quello.
  • Re: Problema con input da fgets

  • Re: Problema con input da fgets

    Parecchio fuori strada, ma devo evitare i predicozzi
  • Re: Problema con input da fgets

    Se parli di me premetto che sto studiando il c da poco e nel mio tempo libero, se invece ti riferisci ad AldoBaldo ti posso dire che mi ha aiutato moltissimo perchè avendo solo il mio libro di programmazione se non riesco a capire un argomento non posso chiedere aiuto a nessuno .
  • Re: Problema con input da fgets

    Se parli di me premetto che sto studiando il c da poco e nel mio tempo libero, se invece ti riferisci ad AldoBaldo ti posso dire che mi ha aiutato moltissimo perchè avendo solo il mio libro di programmazione se non riesco a capire un argomento non posso chiedere aiuto a nessuno .
  • Re: Problema con input da fgets

    patone ha scritto:


    Se parli di me premetto che sto studiando il c da poco e nel mio tempo libero, se invece ti riferisci ad AldoBaldo ti posso dire che mi ha aiutato moltissimo perchè avendo solo il mio libro di programmazione se non riesco a capire un argomento non posso chiedere aiuto a nessuno .
    tranquillo, non c'entri.
    mi sono riproposto di non correggere certi marchiani errori sulla falsariga "non datemi consigli, so sbagliare anche da solo"
Devi accedere o registrarti per scrivere nel forum
12 risposte