Si deve realizzare una semplice calcolatrice in grado di sommare una lista di numeri, secondo le seguenti specifiche:
- La calcolatrice è in un ciclo infinito: continua a prendere input e dare output finché non viene interrotta
- prende l’input da una pipe ‘calcPipeIn’ e manda i risultati su una seconda pipe ‘calcPipeOut’. Le pipe vengono create dalla calcolatrice stessa quando viene eseguita
- le espressioni sono semplici somme, ad esempio 10 + 15 + 280. Vengono inviate su calcPipeIn come sequenze di char terminate da #. Ad esempio 10 + 15 + 280 viene inviata come ’10+15+280#’, ovvero 10 byte senza il terminatore di stringa e senza spazi
- il risultati vengono inviati sempre come sequenze di char separati da ‘#’. Se, ad esempio, inviamo ‘1+2#3+4#’ su calcPipeIn ci aspetteremo ‘3#7#’ su calcPipeOut
Viene fornito un programma di test che invia NT espressioni e controlla i risultati. Per vedere il formato di invio dei dati create le pipe da terminale e stampate il contenuto della pipe di output. Poi eseguite il test da un altro terminale. Ecco un esempio:
$ mkfifo calcPipeIn calcPipeOut
$ cat calcPipeIn
39+23+91+95+60+27+53+56#99+90+85+35#69+21+37+9#89+77+23+14+49+93+16#37#96+21+24+19+13+19+80+40#
$
E questo è il corrispondente ouput del file di test
$ ./calc_test
=== INIZIO TEST ===
Espressione 0 composta da 8 numeri: 39 23 91 95 60 27 53 56
somma: 444
leggo dalla pipe ... :FAIL! timeout
Espressione 1 composta da 4 numeri: 99 90 85 35
somma: 309
leggo dalla pipe ... :FAIL! timeout
Espressione 2 composta da 4 numeri: 69 21 37 9
somma: 136
leggo dalla pipe ... :FAIL! timeout
Espressione 3 composta da 7 numeri: 89 77 23 14 49 93 16
somma: 361
leggo dalla pipe ... :FAIL! timeout
Espressione 4 composta da 1 numeri: 37
somma: 37
leggo dalla pipe ... :FAIL! timeout
Espressione 5 composta da 8 numeri: 96 21 24 19 13 19 80 40
somma: 312
leggo dalla pipe ... :FAIL! timeout
=== TEST FALLITO ===
Il sorgente del programma di test è il seguente
#include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <stdbool.h> #include <stdio.h> #include <string.h> #include <stdarg.h> #include <errno.h> #define PIPE_IN "calcPipeIn" #define PIPE_OUT "calcPipeOut" #define MAXEXP 100 #define NT 6 #define DEBUG 1 die(char * s) { perror(s); exit(1); } // output abilitato se DEBUG == 1 void d_print(char *s, ...) { va_list ap; if (DEBUG) { va_start(ap, s); vprintf(s,ap); va_end(ap); } } main() { int pin,pout,nums,n,i,j,k,r,fail=false,rread; char sn[MAXEXP],ris[MAXEXP]; // apre le pipe if( ( pin=open(PIPE_IN,O_RDWR) ) < 0 || ( pout=open(PIPE_OUT,O_RDWR | O_NONBLOCK) ) < 0 ) die("Errore apertura pipe"); srand(time(NULL)); // inizializza il generatore random d_print("=== INIZIO TEST ===\n"); // genera NT espressioni le invia e controlla il risultato ricevuto for(i=0;i<NT;i++) { r=0; // azzera la somma (per il test) nums = (int) ((float)rand() / RAND_MAX * 9) + 1; // lunghezza espressione d_print("Espressione %i composta da %i numeri: ",i,nums); // genera i nums numeri e li invia come stringhe separati da + // l'ultimo numero e' terminato con # for(j=0;j<nums;j++) { // sceglie un numero a caso n = (int) ((float)rand() / RAND_MAX * 100); d_print("%i ",n); r += n; // aggiorna la somma (per il test successivo) sprintf(sn,"%i",n); // crea la stringa write(pin,sn,strlen(sn)); // la invia sulla pipe if (j==nums-1) // e' l'ultimo numero? write(pin,"#",1); // termina l'espressione else write(pin,"+",1); // aggiunge il simbolo + } d_print("\n somma: %i",r); // controlliamo il risultato dalla pipe d_print("\n leggo dalla pipe ... :"); fflush(stdout); k=0; // leggo un risultato. La lettura e' non bloccante (vedi la open) while(k<MAXEXP-1 && (rread=read(pout,&ris[k],1))>0 && ris[k] != '#') k++; // se per caso non ha letto nulla ritenta dopo un secondo if (rread < 0 && errno ==EAGAIN) { sleep(1); while(k<MAXEXP-1 && (rread=read(pout,&ris[k],1))>0 && ris[k] != '#') k++; } if (rread < 0 && errno ==EAGAIN) { // anche al secondo tentativo non ho letto nulla d_print("FAIL! timeout\n"); fail = true; } else if (atoi(ris) == r) // ho letto la somma corretta d_print("OK\n"); else { // ho letto un valore errato, stampo la stringa letta dalla pipe ris[k+1] ='\0'; d_print("FAIL! Ho letto %s\n",ris); fail = true; } } if (fail) { d_print("=== TEST FALLITO ===\n"); exit(1); }else{ d_print("=== TEST SUPERATO ===\n"); exit(0); } }