Lettura array con riallocazione di memoria

Vediamo ora una variante del programma di lettura di array da file, in cui si fa una sola scansione del file.

Dal momento che non sappiamo quanti elementi stanno nel file, facciamo una prima ipotesi, per esempio che ci siano 1024 elementi. Allochiamo quindi un vettore che contiene 1024 interi, e iniziamo la lettura.

Quando si arriva a scrivere l'ultimo elemento allocato del vettore, sappiamo che non c'è più spazio nel vettore per contenere altri elementi. Quello che ci serve è un vettore più grande. Possiamo usare le funzione realloc per ottenere un vettore più grande, senza perdere i dati già letti.

In practica, ci serve sempre sapere quanti elementi sono stati allocati nel vettore. Usiamo una variabile intera dim per memorizzare questo numero. In questo modo, possiamo sempre sapere se abbiamo ancora spazio oppure no. Nel secondo caso, oltre ad allocare nuova memoria, dobbiamo anche aggiornare il valore di dim, dal momento che il numero di elementi a disposizione è cambiato. Questo ci permette di capire quando anche la nuova memoria è finita e ne serve ancora altra.

Il programma completo rialloca.c è qui sotto.

/*
  Legge un array da file, fino all'end-of-file.
Usa la realloc nel caso in cui non ci sia piu'
spazio nel vettore.
*/

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

int main() {
  int n;
  int *vett;
  int dim;
  FILE *fd;
  int res;
  int i;


		/* allocazione iniziale del vettore */
  dim=1024;
  vett=malloc(dim*sizeof(int));


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


		/* legge il vettore */
  n=0;
  while(1) {
    res=fscanf(fd, "%d\n", &vett[n]);
    if( res!=1 ) 
      break;

    n++;
    if( n>dim-1 ) {
      dim+=1024;
      vett=realloc(vett, dim*sizeof(int));
    }
  }
 

		/* stampa l'array */
  for(i=0; i<=n-1; i++)
    printf("%d\n", vett[i]);


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

  return 0;
}

In pratica, gli array con riallocazione funzionano sempre nello stesso modo: abbiamo una variabile intera che rappresenta il numero di elementi allocati, e un puntatore alla zona di memoria in cui sono memorizzati gli elementi. Ogni volta che ci si accorge che lo spazio nel vettore non basta più, si modifica la variabile intera con la nuova dimensione, e si fa la riallocazione. In questo modo, quando anche la nuova memoria non è più sufficiente, possiamo fare una nuova riallocazione, ecc.