2013-03-18 18 views
5

Sto scrivendo una funzione che esegue alcune azioni di autenticazione. Ho un file con tutti i user_id:password:flag coppie strutturata in questo modo:Raggiungere EOF con fgets

Users.txt

user_123:a1b2:0 user_124:a2b1:1 user_125:a2b2:2

Questo è il codice:

int main(){ 
    /*...*/ 

    /*user_id, password retrieving*/ 
    USRPSW* p = malloc(sizeof(USRPSW)); 
    if(p == NULL){ 
     fprintf(stderr, "Dynamic alloc error\n"); 
     exit(EXIT_FAILURE); 
    } 
    memset((void*)p, 0, sizeof(USRPSW)); 

    if(usr_psw_read(acc_sock_ds, p->user_id, USR_SIZE) <= 0){ 
     printf("Failed read: connection with %s aborted.\n", 
       inet_ntoa(client_addr.sin_addr)); 
     close(acc_sock_ds); 
     continue; 
    } 

    if(usr_psw_read(acc_sock_ds, p->password, PSW_SIZE) <= 0){ 
     printf("Failed read: connection with %s aborted.\n", 
       inet_ntoa(client_addr.sin_addr)); 
     close(acc_sock_ds); 
     continue; 
    } 

    /*Authentication through user_id, password*/ 
    FILE *fd; 
    fd = fopen(USERSFILE, "r"); 
    if(fd == NULL){ 
     fprintf(stderr, "Users file opening error\n"); 
     exit(EXIT_FAILURE); 
    } 

    char *usr_psw_line = malloc(USR_SIZE+PSW_SIZE+3+1); 
    if(usr_psw_line == NULL){ 
     fprintf(stderr, "Dynamic alloc error\n"); 
     exit(EXIT_FAILURE); 
    } 

    while(1){ 

     memset((void*)usr_psw_line, 0, sizeof(USR_SIZE+PSW_SIZE+3+1)); 
     fgets(usr_psw_line, USR_SIZE+PSW_SIZE+3+1, fd); 
     printf("%s\n", usr_psw_line); 
     fseek(fd, 1, SEEK_CUR); 


     /*EOF management*/ 
     /*usr_id - password matching checking */ 

    } 
/*...*/  
} 

Come posso gestire l'EOF raggiungere? Ho visto che quando EOF viene raggiunto, fgets non modifica più la linea usr_psw_line ma non restituisce un puntatore NULL. Se EOF viene raggiunto significa che non viene trovata alcuna corrispondenza nel file degli utenti e che il loop si interrompe.

Qualcuno può darmi qualche consiglio o suggerimento?

+0

Se la fine del file viene raggiunta senza leggere alcun carattere, 'fgets' è obbligato a restituire' NULL'. Ad ogni modo, è possibile controllare 'feof (fd)' dopo che 'fgets' non ha letto nulla. –

+0

Ho paura che EOF non sia impostato. Scrivo solo un file con i record all'interno. Dovrei anche impostare esplicitamente l'EOF? Come fai a fare questo? –

+0

Non si tratta di raggiungere la fine del file durante la lettura? Non si imposta EOF, se si raggiunge la fine del file, il prossimo tentativo di leggere da esso imposterà il flag in '* fd', quindi' feof (fd) 'restituirà true se tutto funziona come dovrebbe . Se tutto non funziona come dovrebbe, hmmm. –

risposta

1

Si potrebbe desiderare di provare qualcosa di simile nel vostro ciclo:

while(1) 
{ 
    memset((void*)usr_psw_line, 0, sizeof(USR_SIZE+PSW_SIZE+3+1)); 
    if(!fgets(usr_psw_line, USR_SIZE+PSW_SIZE+3+1, fd) 
    || ferror(fd) || feof(fd)) 
    { 
     break; 
    } 
    printf("%s\n", usr_psw_line); 
    fseek(fd, 1, SEEK_CUR); 

    /*EOF management*/ 
    /*usr_id - password matching checking */ 

} 

Con il codice in più, il ciclo terminerà se fgets restituisce NULL (nessun altro dato da leggere) o se si sta leggere il Contrassegno EOF o errori nel file. Sono sicuro che sia eccessivo, ma quei test hanno sempre funzionato per me.

+1

Sarebbe meglio (IMO) usare 'while (fgets (usr_psw_line, sizeof (usr_psw_line), fd)! = 0)' per la condizione del ciclo. Non c'è davvero molto bisogno di azzerare la memoria prima della lettura. E non c'è alcun vantaggio nel test con 'ferror()' o 'feof()' lì (dato che valuteranno solo true se il test sul ritorno da 'fgets()' restituisce NULL, quindi, non causano mai il ciclo uscire). –

+0

concordato. Stavo cercando di lasciare intatto quanto più codice originale, in modo che solo le parti che rispondevano direttamente alla domanda fossero chiare. Ma faccio esattamente quello che descrivi in ​​tutti i miei file di lettura. –

+0

@JonathanLeffler "testare con ferror() ... valutare solo su true se il test sul ritorno da fgets() restituisce NULL" -> Non penso in un caso d'angolo. 'ferror()' restituisce lo stato del flag di errore che potrebbe essere stato impostato prima della chiamata 'fgets()'. 'fgets()' non cancella quel flag cosi 'fgets() 'potrebbe restituire non' 'NULL' ancora' ferror() 'restituisce true. – chux

16

fgets() restituisce un puntatore nullo quando raggiunge la fine del file o una condizione di errore.

(EOF è una macro che specifica il valore restituito da alcune altre funzioni in condizioni analoghe; non è solo una sigla per la frase "fine del file".)

Stai ignorando il risultato restituito da fgets() . Non farlo.

Nota che solo il controllo di feof(fd) non farà ciò che desideri. feof() restituisce un risultato vero se hai raggiunto la fine del file. Se invece riscontri un errore, feof() restituisce ancora false e hai un loop infinito se stai utilizzando feof() per decidere quando hai finito. E non restituisce true fino al dopo il non hai letto l'input.

La maggior parte delle funzioni di input C restituisce un valore speciale per indicare che non c'è altro da leggere. Per fgets() è NULL, per fgetc() è EOF e così via. Se lo desideri, puoi chiamare feof() e/o ferror() in seguito per determinare perché non c'è altro da leggere.

+0

(detto con un sorriso) Non l'ho appena detto nella mia precedente risposta? –

+1

@SteveValliere Più o meno, ma ho cercato di essere più esplicito sui concetti sottostanti. –