Trovare e usare la posizione assoluta all'intero di un file

Fino ad ora abbiamo usato la funzione fseek per spostare in avanti e indietro la posizione del file, ma si trattava sempre di spostamenti relativi alla posizione corrente. La funzione fseek può anche venire usata per specificare la posizione assoluta all'interno del file. È per esempio possibile dire alla funzione che vogliamo che la posizione corrente sia sul decimo byte del file, per esempio.

Per dire che la posizione che vogliamo è assoluta invece che relativa, alla funzione fseek passiamo SEEK_SET come terzo argomento. In alternativa, possiamo dire che in questo modo stiamo dando la posizione relativa alla posizione iniziale. Per esempio:

fseek(fd, 0, SEEK_SET);

È equivalente a rewind, ossia ci si sposta all'inizio del file. Nello stesso modo,

fseek(fd, 10, SEEK_SET);

Sposta la posizione corrente di lettura e scrittura al decimo byte del file.

È anche possibile determinare la posizione corrente nel file. Si usa la funzione ftell, che restituisce un intero, che è appunto la posizione corrente. Se per esempio, questa funzione restituisce 20, allora vuol dire che la posizione corrente è sul ventesimo byte del file.

Il seguente programma risolve il seguente problema: dato un file di interi memorizzati in forma binaria, trovare il massimo, e scrive zero al suo posto.

Il programma cancellamax.c memorizza la posizione nel file in cui si è incontrato l'elemento più grande, si sposta in quella posizione e lo mette a 0 (cioè scrive 0 sopra quel numero). L'unica cosa che può essere poco chiara è il perchè facciamo posmax=ftell(fd)-sizeof(int), ossia perchè togliamo sizeof(int) alla posizione corrente del file. Il motivo è semplicemente che la posizione corrente si trova sempre dopo quella in cui il numero x è stato letto. Se x è maggiore del massimo, allora la nuova posizione del massimo (cioè la posizione in cui è stato letto x) è di sizeof(int) indietro rispetto alla posizione corrente.

/*
  Mette a 0 il massimo elemento di un vettore.
*/

#include<stdlib.h>
#include<stdio.h>

int main() {
  FILE *fd;
  int res;

  int x;
  int max;		/* massimo trovato finora */
  int posmax;		/* posizione del massimo nel file */


			/* apre il file */
  fd=fopen("test.dat", "r+");
  if( fd==NULL ) {
    perror("Errore in apertura del file");
    exit(1);
  }


			/* ciclo di lettura */
  max=0;
  while(1) {
    res=fread(&x, sizeof(int), 1, fd);
    if( res!=1 ) 
      break;

    if( x>max ) {
      max=x;
      posmax=ftell(fd)-sizeof(int);
    }
  }


			/* torna nella posizione del massimo
			   e ci scrive sopra 0 */
  fseek(fd, posmax, SEEK_SET);
  x=0;
  fwrite(&x, sizeof(int), 1, fd);


			/* chiude il file */
  fclose(fd);

  return 0;
}