Questo sito utilizza cookies solo per scopi di autenticazione sul sito e nient'altro. Nessuna informazione personale viene tracciata. Leggi l'informativa sui cookies.
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
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++
#include <stdio.h>
#include <ctype.h>
void trasformaVocaliInMaiuscole(FILE*fp);
int vocale(char ch);
int main (int argc, char*argv[])
{
FILE*fp;
if(!(fp =fopen("dati.txt", "r+"))){
perror("Errore apertura file");
return1;
}
trasformaVocaliInMaiuscole(fp);
fclose(fp);
return0;
}
void trasformaVocaliInMaiuscole(FILE*fp)
{
char ch;
while(!feof(fp)){
/* leggo il carattere corrente, e verifico che non ci siano
errori durante la lettura */
if(fread(&ch, 1, 1, fp)== 0){
break;
}
/* nel caso in cui il carattere letto sia presente nell'alfabeto,
lo converto e lo sovrascrivo nel file */
ch =toupper(ch);
if(vocale(ch)){
fseek(fp, -1, SEEK_CUR);
fwrite(&ch, 1, 1, fp);
fseek(fp, 0, SEEK_CUR);
}
}
}
/**
* Restituisce 1 se 'ch' è una vocale, 0 altrimenti.
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...
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).
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!
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