Newsgroup: it.comp.lang.c
Titolo: fgets che non funziona come dovrebbe

Salve a tutti,
qualcuno è in grado di spiegarmi come mai la funzione
/***********************************************************************
*                         Funzione LEGGI_FILE                          *
***********************************************************************/
int leggi_file()
   {
   int conriga=0,end=0,i;     // variabili di controllo
   char *ch, buffer[dim];            // variabile per la lettura dell'input
       filein=fopen(infile,"r");      // e lo storage dell'input
       while (1)
       {                   // ciclo che legge e inserisce nell'array
       ch=fgets(buffer,dim,filein);
       if ( ch==NULL)       // 'buffer' le righe del file di input.
       {
       printf("fine file raggiunta\n");
       break;
       }
       conriga=conriga+1;
       printf("stringa: %s\n",buffer);
       conformita(buffer,dim);
       printf("Responso di conformita'della riga %d :%d\n",conriga,fine);
       }
end=1; //...allora termina
fclose(filein);
//fclose(fileout);
return end;
}
***************************************************************************
con in ingresso un file di quattro righe ("dim" rappresenta la massima 
lunghezza delle righe del file di ingresso) fa cinque cicli invece di 
quattro come dovrebbe? Capita quando la riga più lunga non è l'ultima, 
mi spiego meglio: con righe di differenti lunghezze se quella che 
determina "dim" non è l'ultima del file succede che tra quella e la 
seguente legge una riga storpiata che non dovrebbe esserci (legge parte 
dei caratteri della riga precedente).
Gia che ci sono vi chiedo anche un consiglio su un modo per cancellare 
il contenuto dell'array in modo tale che nei cicli successivi alla riga 
più lunga quelle che non lo occupano tutto non si trovino in "eredità" 
parte dei caratteri memorizzati in precedenza.
Grazie per l'attenzione.
Dan

>    char *ch, buffer[dim];  // variabile per la lettura dell'input
------------> Quanto vale dim?
Mi sembra di capire che, usi questo valore come lunghezza della linea
(altrimenti perche' passarla alla funzione conformita()?) ma potrei
sbagliare. In realtà la lunghezza della linea deve essere strettamente
minore di dim e la fine della linea è segnalata dal solito '\0'. In pratica
non credo che sia la fgets() a non funzionare come dovrebbe, semplicemente
gli stai chiedendo di fare piu' del suo dovere! :)
Quindi da qualche parte devi avere un dim=1024 o simili (non ci preoccupiamo
di buffer overrun) e la fgets() ti risolve l'apparente problema di dover
cancellare il buffer (ci riscrive sopra e mette un '\0' alla fine della
stringa).
In pratica se c'e' una espressione per riga puoi aggiungere al codice
qualcosa del genere (assumendo che poi tu abbia deciso di realizzare la FSM
con dei goto):
START:
    if (*c == '\0')            /* Fine della linea */
        goto SUCCESS;
    else if (isspace(*c)) {
        c++;
        goto START;
    }
    etc, etc ....
INFUNC:
    if (*c == '\0')
        goto FAIL;
    etc, etc ....
Se stai assumendo che le espressioni da riconoscere siano una per riga,
l'uso di fgets() mi sembra ok, altrimenti ti sei complicato un po' la vita!
Se un'espressione puo' proseguire per più righe, il modo con cui hai
strutturato il tutto ti crea un bel problema: quando conformita() termina,
non puo' dire se ha avuto successo o meno, deve aspettare di vedere il resto
dell'espressione; nel tuo codice, invece, fai ricominciare il controllo
dallo stato START che non è detto sia lo stato dal quale sei uscito!
Quindi, se le espressioni da riconoscere sono del tipo:
(set
  (lambda 4))
che è valida rispetto alla grammatica, o leggi tutto il file nel buffer
(senza tener conto delle righe) oppure puoi leggere il file un carattere
alla volta con la fgetc(). Qualcosa del genere (ricordati che in questo caso
c deve essere un int e non un char):
c=fgetc(filein);
START:
    if (c == EOF)            /* Fine del FILE */
        goto SUCCESS;
    else if (isspace(c)) {
        c=fgetc(filein);
        goto START;
    }
    etc, etc ....
INFUNC:
    if (c == EOF)
        goto FAIL;
    etc, etc ....
ora dovrai controllare "setq" e le altre funzioni confrontando un carattere
alla volta ma se usi uno stato per ogni carattere la cosa è abbastanza
semplice (un po' noiosa forse, ma tant'è...).
Ciao,
                R.D
P.S. una piccola nota: // non è una sintassi ANSI C valida, rischiamo di
beccarci un flame per OT! :)

 
Opss sorry ma sono niubbo... perdonatemi :)