Lettura da stringa

La funzione fgets è molto utile quando un file di testo va elaborato una linea per volta. Esistono dei casi in cui non è da sola sufficiente. Consideriamo per esempio il caso in cui si vuole leggere da file degli interi, ignorando le linee che iniziano con un carattere '#'. In questo caso, per saltare le linee che iniziano con '#' la funzione fgets risulta comoda, mentre per leggere degli interi la funzione fscanf è la scelta migliore. Il problema è che, una volta letta una linea da file con fgets, se si cerca di fare una lettura con fscanf quello che si legge è il seguito del file, ossia la linea letta da fgets non viene poi scandita di nuovo da fscanf.

Una delle funzioni di libreria del C che risulta utile in questi casi è la funzione di lettura da stringa (esistono molte altre situazioni in cui questa funzione può essere utile). Questa funzione si chiama sscanf, e ha gli stessi argomenti della fscanf tranne il primo, che è una stringa invece che un descrittore di file. Questa funzione legge i dati dalla stringa invece che da file, ma per il resto il comportamento è identico.

Il seguente programma mediacommenti.c è un esempio di uso di questa funzione: si legge un file di testo, in cui le linee che iniziano con il carattere '#' sono commenti, mentre le altre linee contengono due numeri interi ciascuna.

/*
  Calcola la media degli interi su file.
Le linee che iniziano con # sono commenti
e non vengono considerate.
*/

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

int main() {
  FILE *fd;
  char buf[200];
  char *res;
  int x, y;
  int n, somma, media;


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


			/* legge una riga per volta */
  somma=0;
  n=0;
  while(1) {
    res=fgets(buf, 200, fd);
    if( res==NULL )
      break;

    if( buf[0]!='#' ) {
      sscanf(buf, "%d %d", &x, &y);
      somma+=(x+y);
      n+=2;
    }
  }
    

			/* stampa la media */
  printf("La media e' %d\n", somma/n);

  return 0;
}

Un possibile miglioramento di questo programma è il controllo che le linee che non sono commenti contengono effettivamente due interi. Questo controllo si può fare tenendo conto che il valore di ritorno della funzione sscanf è lo stesso valore che avrebbe fscanf se la stringa fosse il contenuto di un file.