Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Chiarimento funzionamento FILE pointer
Forum - C/C++ - Chiarimento funzionamento FILE pointer

Avatar
GuglielmoS (Ex-Member)
Pro


Messaggi: 114
Iscritto: 27/11/2009

Segnala al moderatore
Postato alle 19:01
Martedì, 21/09/2010
Salve a tutti!
A scuola ci hanno chiesto di risolvere un esercizio teoricamente banale che consiste nel trasformare le vocali presenti in un file in maiuscole (tutto questo nello stesso file).
Il problema si presenta però al momento della sovrascrittura delle vocali, infatti sembra che il file pointer si "sballi" e il programma entri in un ciclo infinito. Per far funzionare il tutto bisogna aggiungere questa riga dopo la fwrite del carattere modificato:
Codice sorgente - presumibilmente Plain Text

  1. fseek(fp, 0, SEEK_CUR);


Ora teoricamente questa linea di codice non dovrebbe fare niente, e quindi mi chiedo perchè la devo inserire?
Ecco il resto del codice:
Codice sorgente - presumibilmente C++

  1. #include <stdio.h>
  2. #include <ctype.h>
  3.  
  4. void trasformaVocaliInMaiuscole(FILE *fp);
  5. int  vocale(char ch);
  6.  
  7. int main (int argc, char *argv[])
  8. {
  9.         FILE *fp;
  10.  
  11.         if (!(fp = fopen("dati.txt", "r+"))) {
  12.                 perror("Errore apertura file");
  13.                 return 1;
  14.         }
  15.  
  16.         trasformaVocaliInMaiuscole(fp);
  17.  
  18.         fclose(fp);
  19.  
  20.         return 0;
  21. }
  22.  
  23. void trasformaVocaliInMaiuscole(FILE *fp)
  24. {
  25.         char ch;
  26.  
  27.         while (!feof(fp)) {
  28.                 /* leggo il carattere corrente, e verifico che non ci siano
  29.                    errori durante la lettura */
  30.                 if (fread(&ch, 1, 1, fp) == 0) {
  31.                         break;
  32.                 }
  33.  
  34.                 /* nel caso in cui il carattere letto sia presente nell'alfabeto,
  35.                    lo converto e lo sovrascrivo nel file */
  36.                 ch = toupper(ch);
  37.                 if (vocale(ch)) {
  38.                         fseek(fp, -1, SEEK_CUR);
  39.                         fwrite(&ch, 1, 1, fp);
  40.                         fseek(fp, 0, SEEK_CUR);
  41.                 }
  42.         }
  43. }
  44.  
  45. /**
  46.  * Restituisce 1 se 'ch' è una vocale, 0 altrimenti.
  47.  */
  48. int vocale(char ch)
  49. {
  50.         ch = toupper(ch);
  51.         switch (ch) {
  52.                 case 'A':
  53.                 case 'E':
  54.                 case 'I':
  55.                 case 'O':
  56.                 case 'U':
  57.                         return 1;
  58.                 default:
  59.                         return 0;
  60.         }
  61. }


Grazie,
Saluti GuglielmoS

PM
Avatar
TheKaneB (Member)
Guru^2


Messaggi: 1792
Iscritto: 26/06/2009

Up
1
Down
V
Segnala al moderatore
Postato alle 15:53
Mercoledì, 22/09/2010
ah, un'altra cosa... apri il file con il modo "r+b", altrimenti windows ti converte al volo i terminatori di riga, e questo potrebbe portare comportamenti imprevisti. Usando la modalità binaria hai la garanzia che i dati letti combaciano esattamente con i dati del file (tanto alla fine stai leggendo un byte per volta, quindi ti conviene trattarlo come file binario).

NB: su windows il terminatore di riga è 2 byte (0x0A0D), ma leggendo in modalità non binaria, te lo converte in formato Unix/Posix (0x0A, un solo byte). Forse è questo che ti fa sballare i seek e le read...

ne parla qui: http://support.microsoft.com/kb/48885/it
dice esplicitamente che viene fatta la conversione al volo tra il sistema windows e il sistema unix.

Ultima modifica effettuata da TheKaneB il 22/09/2010 alle 15:58
PM
Avatar
TheKaneB (Member)
Guru^2


Messaggi: 1792
Iscritto: 26/06/2009

Up
0
Down
V
Segnala al moderatore
Postato alle 1:36
Mercoledì, 22/09/2010
in effetti non ha senso... probabilmente il problema è altrove, e l'aggiunta di quella riga per qualche strano motivo va a coincidere con qualcos'altro. Azzarderei l'ipotesi di caching troppo aggressivo del VFS del sistema operativo, ma ci sono delle precise policies che "in teoria" dovrebbero rendere del tutto trasparente questa cache (in sostanza, una read dopo una write, dovrebbe SEMPRE causare il flush, con relativo write-back, della cache del FS).

PM
Avatar
GuglielmoS (Ex-Member)
Pro


Messaggi: 114
Iscritto: 27/11/2009

Up
0
Down
V
Segnala al moderatore
Postato alle 15:10
Mercoledì, 22/09/2010
Testo quotato

Postato originariamente da TheKaneB:

in effetti non ha senso... probabilmente il problema è altrove, e l'aggiunta di quella riga per qualche strano motivo va a coincidere con qualcos'altro. Azzarderei l'ipotesi di caching troppo aggressivo del VFS del sistema operativo, ma ci sono delle precise policies che "in teoria" dovrebbero rendere del tutto trasparente questa cache (in sostanza, una read dopo una write, dovrebbe SEMPRE causare il flush, con relativo write-back, della cache del FS).


Ah ok perchè un'altra cosa strana che ho visto dopo debuggando con il Visual C++, è che il puntatore del file torna indietro di 2 con la fseek e poi con la fwrite avanza solo di 1. Grazie per la risposta!

PM
Avatar
GuglielmoS (Ex-Member)
Pro


Messaggi: 114
Iscritto: 27/11/2009

Up
0
Down
V
Segnala al moderatore
Postato alle 16:09
Mercoledì, 22/09/2010
Grazie per il chiarimento, in effetti a quello non ci avevo pensato. Comunque il problema purtroppo, per chissà quali oscuri motivi, rimane invariato.
Ciao GuglielmoS

PM