Oppure

Loading
21/09/10 17:01
GuglielmoS
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:
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:
#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");
		return 1;
	}

	trasformaVocaliInMaiuscole(fp);

	fclose(fp);

	return 0;
}

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.
 */
int vocale(char ch) 
{
	ch = toupper(ch);
	switch (ch) {
		case 'A':
		case 'E':
		case 'I':
		case 'O':
		case 'U':
			return 1;
		default:
			return 0;
	}
}

Grazie,
Saluti GuglielmoS
aaa
21/09/10 23:36
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).
aaa
22/09/10 13:10
GuglielmoS
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!
aaa
22/09/10 13:53
TheKaneB
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: support.microsoft.com/kb/48885/…
dice esplicitamente che viene fatta la conversione al volo tra il sistema windows e il sistema unix.
Ultima modifica effettuata da TheKaneB 22/09/10 13:58
aaa
22/09/10 14:09
GuglielmoS
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
aaa