Lettura array con allocazione di memoria

Il seguente programma legge un array da file. Il file ha questo formato: il primo intero è la dimensione dell'array, ossia il numero di elementi dell'array. Seguono gli elementi dell'array.

Si noti che non è in generale possibile memorizzare l'array in un vettore statico, dal momento che il numero di elementi che deve contenere non è noto in fase di compilazione. Infatti, questo numero risulta noto solo quando il file viene aperto e il primo intero viene letto. Si può usare un array statico soltanto quando esiste già, in fase di compilazione, una stima del massimo numero di elementi.

Il programma seguente leggiarray.c legge quindi il primo intero dal file, e lo memorizza nella variabile n. Dal momento che questo numero è la dimensione che l'array deve avere, possiamo ora allocare l'array con la funzione malloc. Dal momento che si tratta di n interi, allochiamo n*sizeof(int) byte. A questo punto, possiamo leggere, uno per volta, gli elementi dell'array da file.

/*
  Legge un array da file.
*/

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

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

		/* apre il file */
  fd=fopen("array.txt", "r"); 

		/* verifica errori in apertura */
  if( fd==NULL ) {
    perror("Errore in apertura del file");
    exit(1);
  }

		/* legge il numero di elementi del vettore */
  fscanf(fd, "%d\n", &n);

  
		/* alloca il vettore */
  vett=malloc(n*sizeof(int));


		/* legge il vettore */
  for(i=0; i<=n-1; i++)
    fscanf(fd, "%d\n", &vett[i]);


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


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

  return 0;
}

Da notare che il programma non controlla se effettivamente sul file ci sono n elementi dopo il primo. Questo potrebbe però accedere se c'è stato un errore nella realizzazione del file. Inoltre, non c'è nessun controllo sulla conversione, ossia il programma non si accorge se in mezzo al file ci sono per esempio dei caratteri alfabetici, che non sono chiaramente interpretabili come interi.

Per rendere il programma robusto (in grado di rilevare errori nei dati di input) occorre fare un controllo sul valore di ritorno della funzione fscanf.

Il programma dovrebbe inoltre fare un controllo sul valore di ritorno della funzione malloc, per controllare se effettivamente siamo riusciti ad allocare gli elementi richiesti (la allocazione fallisce se non c'è più memoria a disposizione). Il programma modificato leggiarrayrob.c è il seguente.

/*
  Legge un array da file.
*/

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

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

		/* apre il file */
  fd=fopen("array.txt", "r"); 

		/* verifica errori in apertura */
  if( fd==NULL ) {
    perror("Errore in apertura del file");
    exit(1);
  }

		/* legge il numero di elementi del vettore */
  res=fscanf(fd, "%d\n", &n);
  if(res!=1) {
    printf("Non riesco a leggere il numero di elementi del vettore\n");
    exit(1);
  }

  
		/* alloca il vettore */
  vett=malloc(n*sizeof(int));
  if(vett==NULL) {
    printf("Non riesco ad allocare memoria\n");
    exit(1);
  }


		/* legge il vettore */
  for(i=0; i<=n-1; i++) {
    res=fscanf(fd, "%d\n", &vett[i]);
    if(res!=1) {
      printf("Non riesco a leggere l'elemento %d-esimo del vettore\n", i);
      exit(1);
    }
  }


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


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

  return 0;
}