/* campionamento di un file 
 * carica il campione su array
 * versione "con reimbussolamento", ovvero un record puo' essere preso piu' volte
 * Il caricamento del campione su array  giustificato soltanto se:
 * 1. il campione che si vuole estrarre non e' troppo grande
 * 2. l'elaborazione che si intende svolgere sul campione richiede pi accessi 
 *    a ogni dato
 *
 * - acquisisce nome e apre file da campionare in modalità lettura binaria
 * - acquisisce origine sequenza random
 * - si posiziona in coda al file per calcolarne la dimensione N
 * - input della frazione da campionare n e verifica di capienza dell'array
 * - ripeti n volte la generazione di un numero fra 0 e N e leggi 
 *    il record corrispondente nell'array
 * - elabora il campione
 */

#define dimCAMPIONE 10000
#define DIMBUF 80
#include <stdio.h>
#include <stdlib.h>
#include "random.h" /* procedura esterna per la generazione di numeri random */

typedef long r; /* a titolo di esempio si considera un file di interi lunghi */

void elabora(r *campione,long n);

int main(){
 r camp[dimCAMPIONE]; /* array di campioni */
 long N, /* numero di r nel file */
      n, /* dimensione campione corrente */
      i, /* indice */
      seme, /* seme per rand */
      p; /* posizione di campionamento corrente */
 float f; /* frazione da estrarre */
 FILE *fd;
 char nomeF[64], linea[DIMBUF];
 /* intro e' un array di 4 stringhe di 64 caratteri ciascuna, utilizzato per mandare
  * all'utente un messaggio introduttivo
  */
 char intro[4][64]={"Programma per il campionamento di record da un file\n",
                " Richiede il nome del file, il seme della sequenza random e\n",
                " la frazione di record da campionare.\n",
                " Versione con caricamento del campione in memoria\n"};
 
 for (i=0;i<4;i++) /* visualizza intro */
  printf("%s",intro[i]);
 /* inizializzazione */
 printf("\nNome file da campionare\n");
 fgets(linea,DIMBUF,stdin);
 sscanf(linea,"%s",nomeF);
 if ((fd=fopen(nomeF,"rb"))==NULL){
  printf("File %s non trovato\n",nomeF);
  return 1;
 }
 printf("Inserire origine sequenza random \n");
 fgets(linea,DIMBUF,stdin);
 sscanf(linea,"%ld",&seme);
 srand(seme);
 fseek(fd,0,SEEK_END);
 N=ftell(fd)/sizeof(r);
 printf("Inserire frazione da campionare (da 0 a 0.5) \n");
 fgets(linea,DIMBUF,stdin);
 sscanf(linea,"%f",&f);
 n=f*N;
 printf("Nel file ci sono %ld records, ne campiono %ld\n",N,n);
 if (n>dimCAMPIONE){
  printf("Campione troppo grande\n");
  return 1;
 }
 /* fine inizializzazione */
 for (i=0;i<n;i++){         /* ripete n volte il campionamento */
  p=randN(N);                        /* genera la posizione del record da campionare */
  fseek(fd,p*sizeof(r),SEEK_SET);         /* si posiziona per la lettura */
  fread(&(camp[i]),sizeof(r),1,fd);        /* legge il record nell'array */
 }
 fclose(fd);
 elabora(camp,n); /* elabora l'array con il campione */
 return 0;
} /* fine main */

/*
 * elabora: esempio di elaborazione dell'array con il campione
 */
void elabora(r *campione, long n){ /* a titolo di esempio si calcola la media */
 float media;
 long i;
 media=campione[0];
 
 for (i=1;i<n;i++)
  media = (media*(i)+campione[i])/(i+1);
  
 printf("valore medio %f\n",media);
} /* fine elabora */