Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre...

43
Laboratorio di trattamento numerico dei dati sperimentali Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017

Transcript of Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre...

Page 1: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Laboratorio di trattamento numerico deidati sperimentali

Maurizio Tomasi ﴾turno A2﴿

Giovedì 12 Ottobre 2017

Page 2: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Avvertenza generaleNon fare copia‐e‐incolla di codice da slide PDF ﴾come queste﴿! Ilformato PDF usa una rappresentazione interna di alcuni simbolidiversa dall'ASCII, e di conseguenza il GCC si lamenterebbe conerrori del tipo  unexpected symbol… ,  unexpected character…  e cosìvia.

Trascrivere a mano il codice di queste slide è inoltre più utile,perché così vi rendete conto di alcune sottigliezze sintattiche ﴾es.,dove sono usati i punti e virgola﴿.

Page 3: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Compilare programmi C++ a casaSe si vogliono scrivere programmi C++ senza usare i computer dellaboratorio, esistono siti che consentono la scrittura e lacompilazione di codice C++ online.

Il sito TutorialsPoint mette a disposizione la possibilità di compilareed eseguire programmi C++ usando la versione più recente delcompilatore C++. Registrandosi, è anche possibile sviluppare«progetti» ﴾programmi composti da più file sorgente﴿.

Page 4: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

File sorgente multipli

Page 5: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Esempio: somma di due interiPrendiamo questo semplice esempio:

#include <iostream>

int calc(int a, int b) {    return a + b;}

int main() {    std::cout << "Insert two numbers separated by a space: ";

    int a, b;    std::cin >> a >> b;        std::cout << "The result is " << calc(a, b) << "\n";    return 0;}

Page 6: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Esempio: somma di due interiCercate ora di immaginare che  calc  faccia un conto estremamentecomplesso ma molto utile, che ci piacerebbe usare in futuro peraltri progetti.

L'approccio più semplice sarebbe quello di ricordarci che abbiamogià implementato  calc  in questo programma, e che copiamo edincolliamo l'implementazione nel nostro ipotetico nuovo progetto.

Ma se, lavorando nel nuovo progetto, vogliamo migliorare  calc ﴾rendendola più veloce, o correggendo un bug﴿, dovremmoricordarci di aggiornare anche questo nostro vecchio file.

Page 7: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Dividere un file sorgenteUn approccio più gestibile è quello di dividere il codice C++ in piùfile, e dire al compilatore di combinarli insieme:

// First file: calc.ccint calc(int a, int b) {    return a + b;}

// Second file: main.cc#include <iostream>

int main() {    std::cout << "Insert two numbers separated by a space: ";

    int a, b;    std::cin >> a >> b;        std::cout << "The result is " << calc(a, b) << "\n";    return 0;}

Page 8: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

ProblemaC'è però un problema: se proviamo a compilare i due file insieme,otteniamo un errore!

$ g++ main.cc calc.cc ‐o test1main.cc: In function ‘int main()’:main.cc:8:44: error: ‘calc’ was not declared in this scope  std::cout << "The result is " << calc(a, b) << "\n";

Ora il compilatore si lamenta perché non sa più cosa sia  calc .Potremmo ovviare alla cosa inserendo il prototipo di  calc  in main.cc :

// main.cc#include <iostream>

int calc(int a, int b);

int main() { … }

Page 9: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

File headerUna soluzione più elegante è quella di creare un terzo file, chiamatoheader file:

// calc.hhint calc(int a, int b);

Questo file va «copiato» in  main.cc , non manualmente, ma usando #include :

// Second file: main.cc#include <iostream>#include "calc.hh"  // Note the "" here!

int main() {    std::cout << "Insert two numbers separated by a space: ";    // …}

Page 10: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

File headerDi solito si include il file header anche nel file che implementa lafunzione: non è necessario, ma aiuta a garantire la consistenza tra idue file. ﴾Se aggiungessi un giorno un terzo parametro a  calc  mami dimenticassi di aggiornare il file  calc.hh , il compilatore silamenterebbe﴿.

Il file  calc.cc  diventa quindi il seguente:

// calc.cc#include "calc.hh"  // Not required, but strongly suggested

int calc(int a, int b);

Page 11: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Build automatici con Make

Page 12: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Compilare progetti complessiNel momento in cui il codice sorgente di un programma non è piùin un solo file, molte cose si complicano.

Supponiamo che abbiate ricevuto da un conoscente una cartellapiena di programmi C++. C'è un programma, download_mp3_albums.cc , che vorreste compilare ed eseguire:

$ g++ download_mp3_albums.cc ‐o download_mp3_albumsdownload_mp3_albums.cc: In function ‘int main()’:download_mp3_albums.cc:684:4: error: ‘start_download’ ↩                              was not declared in this scope    start_download(&connection, &params);… (many other errors)

Apparentemente serve una funzione,  start_download , che perònon è presente nel file!

Page 13: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

MakeQuesto è un problema che risale ai primordi della storia del C. Èstato quindi inventato un programma,  make , che si occupa di«creare» ﴾appunto, «to make»﴿ files partendo da altri.

Il nostro problema è quello che per creare un file eseguibile ﴾es., download_mp3_albums ﴿ possono essere necessari tanti file sorgente:

 main.cc 

 download.cc ,  download.hh 

 encode_mp3.cc ,  encode_mp3.hh etc.

Make consente di scrivere esplicitamente queste dipendenze: sitratta di un sistema di build automation.

Page 14: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Come funziona MakeIl funzionamento di Make è analogo a quello di un compilatoreC++:

1. Si scrive un file di testo usando una particolare sintassi;2. Si «esegue» il file usando Make;

3. Make produce uno o più file di output.

I file di testo letti da Make non sono scritti in linguaggio C++, ma inun linguaggio specifico che usa solo Make.

Noi mostreremo solo gli aspetti essenziali: Make è un programmaestremamente complesso, consultate il manuale di GNU Make perulteriori informazioni.

Page 15: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Un Makefile per il programma  calc Torniamo al nostro programma  calc , fatto da tre file:  main.cc , calc.cc  e  calc.hh .

Creiamo ora un file chiamato  Makefile  ﴾senza estensione!﴿contenente queste righe:

# Needed for C++ programsLDLIBS = ‐lstdc++

main: main.o calc.o

main.o: main.cc calc.hh

calc.o: calc.cc calc.hh

Page 16: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Esecuzione di un MakefileOra eseguiamo  make :

$ makeg++    ‐c ‐o main.o main.ccg++    ‐c ‐o calc.o calc.cccc   main.o calc.o ‐lstdc++  ‐o main$

Make ha letto automaticamente il file  Makefile , ed ha eseguito icomandi stampati sullo schermo. Ora abbiamo quindi l'eseguibile main  a disposizione:

$ lscalc.cc     maincalc.hh     main.cccalc.o

Page 17: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Esecuzione di un MakefileSe eseguiamo immediatamente  make  una seconda volta, avvieneuna cosa interessante:

$ make$

In questo caso, Make non fa nulla: ha controllato le date dei file diinput e di output, e ha visto che dall'ultima creazione di  main  ﴾filedi output﴿, i tre file di input  main.cc ,  calc.cc  e  calc.hh  non sonostati cambiati, quindi non c'è stato bisogno di fare nulla.

Page 18: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Funzionamento di MakeSe a questo punto modificassimo  main.cc  ed eseguissimo  make ,questo sarebbe l'output:

$ makeg++    ‐c ‐o main.o main.cccc   main.o calc.o ‐lstdc++  ‐o main

Il comando  g++ ‐c ‐o calc.o calc.cc  stavolta non è statoeseguito: Make ha capito che era inutile! Ma se cambiamo il file calc.hh , allora Make deve rifare tutto da capo:

$ makeg++    ‐c ‐o main.o main.ccg++    ‐c ‐o calc.o calc.cccc   main.o calc.o ‐lstdc++  ‐o main

Page 19: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Avvertenza su MakeIl programma Make è stato creato nel 1976, più di 40 anni fa, eoggi mostra tutti i suoi limiti:

Occorre ricordarsi di specificare i file  .h  come dipendenze deifile  .c , e di tenere aggiornata la listaL'uso del  TAB  all'inizio delle righe di comando è stranoPer progetti con molti file, la scrittura del  Makefile  è laboriosaI  Makefile  non sono portabili: il fatto che un  Makefile funzioni su un sistema non significa che necessariamentefunzionerà su un altro ﴾a causa di un diverso compilatore, o diun diverso sistema operativo, etc.﴿

Page 20: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Avvertenza su MakeLinguaggi più moderni forniscono un proprio build system, o non lorichiedono proprio ﴾es., Go, Rust, Nim, D, C#, …﴿. Anche linguaggipiù vecchi del C++ o comunque contemporanei fornivano soluzionipiù eleganti ﴾es., Modula‐2, Turbo Pascal, Oberon, Ada, …﴿

Con gli anni sono stati inventati sistemi più sofisticati per compilareprogrammi C++ ﴾CMake, Scons, Qmake, WAF, QBS, …﴿, e si stadiscutendo della possibilità di introdurne uno in future versionidello standard, legandolo alla possibilità di andare oltre i file header﴾vedi la bozza del Module TS, che purtroppo non ha trovato postonel nuovo standard C++17﴿.

In questo corso useremo comunque i Makefile, visto che i nostriprogrammi saranno sempre molto semplici. Però ricordate che perprogrammi più complessi è meglio cercare altro.

Page 21: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Passaggio di parametri

Page 22: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Passaggio di parametri a funzioniConsideriamo la nostra funzione  calc :

int calc(int a, int b) {  return a + b;}

Per «passaggio di parametri» intendiamo il modo con cui vienespecificato il valore di  a  e di  b  quando si esegue la funzione daun altro punto del codice:

// What happens here?!?          ~~~~~~~~~~std::cout << "The result is " << calc(x, y) << "\n";

Page 23: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Tipi di passaggio di parametriIl C++ offre tre tipi di meccanismi per il passaggio di parametri:

1. Passaggio per valore ﴾detto anche passaggio per copia﴿;2. Passaggio per puntatore3. Passaggio per reference

Rivediamoli brevemente tutti.

int calc(int a, int b) {    return a + b;}

int main() {    int x = 6, y = 7;    std::cout << calc(x, y) << "\n";    return 0;}

Page 24: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Passaggio per valore ﴾o «per copia»﴿int calc(int a, int b) {    return a + b;}

int main() {    int x = 6, y = 7;    std::cout << calc(x, y) << "\n";    return 0;}

Nel momento di eseguire  calc , il compilatore copia il valore dellavariabile  x  ﴾6﴿ ed  y  ﴾7﴿ nei parametri  a  e  b .

Qualsiasi modifica ad  a  e  b  fatta da  calc  non influenza quindi ilcontenuto di  x  ed  y .

Page 25: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Passaggio per puntatoreint calc(int * a, int * b) {    // Note the * here!    return (*a) + (*b);  // !}

int main() {    int x = 6, y = 7;    std::cout << calc(&x, &y) << "\n";  // !    return 0;}

In questo caso i parametri non sono variabili interi, ma «puntatori»a variabili intere. Il valore di  a  è l'indirizzo della variabile checontiene il parametro, ed il valore di  *a  è il valore della variabilepuntata, qualunque essa sia.

Qualsiasi modifica ad  *a  e  *b  fatta da  calc  si riflette quindi su x  ed  y , perché  *a  è a tutti gli effetti sinonimo di  x .

Page 26: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Passaggio per referenceint calc(int & a, int & b) {    // Note the & here!    return a + b;}

int main() {    int x = 6, y = 7;    std::cout << calc(x, y) << "\n";    return 0;}

I reference sono a tutti gli effetti dei «puntatori mascherati». C'è ilvantaggio che per modificare la variabile non si deve usare lascrittura  *a , e quindi il codice è più leggibile.

Page 27: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Uso di  fstream 

Page 28: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

La libreria  fstream Abbiamo usato più volte  std::cin  e  std::cout  per leggere datastiera e scrivere sul video.

La libreria standard C++ offre funzioni molto simili per leggere escrivere da file. Queste funzioni si usano includendo il file  fstream :

#include <fstream>

Page 29: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Scrivere su filePer scrivere su un file, si crea una variabile di tipo  std::ofstream ﴾Output File STREAM﴿ specificando il nome del file, e si usa il solitooperatore  << , come se si usasse  std::cout :

// fstream1.cc#include <fstream>

int main() {    std::ofstream output("test.txt");        output << "Hello!\n";    return 0;}

$ g++ fstream1.cc ‐o fstream1 && ./fstream1$ cat test.txtHello!

Page 30: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Leggere da filePer leggere da un file, il meccanismo è simile: si crea un oggetto ditipo  std::ifstream  e lo si usa come se fosse  std::cin :

// fstream2.cc#include <iostream>#include <fstream>#include <string>

int main() {    std::ifstream input("test.txt");    std::string message;    input >> message;    std::cout << "The file contains this message:\n";    std::cout << message << "\n";    return 0;}

$ g++ fstream2.cc ‐o fstream2 && ./fstream2The file contains this message:Hello!

Page 31: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Controllo di erroriLeggere da file è un'attività che presenta molte possibilità di errore:

1. Si vuole aprire un file che non esiste

2. Si vuole aprire un file per cui non si dispone dei permessinecessari

3. Si vuole aprire un file su un'unità danneggiata4. Si vuole scrivere un file in una directory non esistente5. Etc.

Fortunatamente, è molto semplice implementare un controllo deglierrori con  fstream .

Page 32: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Controllo degli erroriIl seguente codice verifica che un file sia stato effettivamenteaperto prima di provare a leggerlo:

std::ifstream input("test.txt");

if (! input) {    std::cerr << "File test.txt does not exist!\n";    return 1;}

Notare l'uso di  std::cerr  anziché  std::cout : dovrebbe sempreessere usata questa convenzione quando si scrivono messaggi dierrore, perché presenta molti vantaggi pratici.

Il programma ritorna il valore  1  anziché  0 , perché questa è laconvenzione per segnalare un errore.

Page 33: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Controllo degli erroriSe un file è stato aperto, non vuol dire che tutto ora andrà bene: ilfile potrebbe contenere meno dati di quanti ci aspettiamo. Duemetodi di  std::ifstream  sono particolarmente utili:

 eof  ritorna  true  se non c'è più nulla da leggere nel file;

 good  ritorna  true  se lo stream non presenta errori ed èpossibile continuare a leggere dal file.

Esempio d'uso:

std::ifstream input_file("samples.dat");while (input_file.good()) {    double sample;    input_file >> sample;    std::cout << sample << "\n";}

Page 34: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Test automatici

Page 35: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Verifica della correttezza del codiceQuando si scrive un programma, è indispensabile verificare chefunzioni.

Un tempo era prassi eseguire il programma più volte, passandoglidei dati di input e verificando a mano che questi fossero corretti.

Oggi i computer sono abbastanza potenti per chiedere che sianoloro stessi a fare questa verifica!

Page 36: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Un esempio// test1.cc#include <iostream>

int sum(int a, int b) {    return a + b;}

int main() {    std::cout << "Insert two numbers separated by a space: ";

    int a, b;    std::cin >> a >> b;        std::cout << "The sum is " << sum(a, b) << "\n";    return 0;}

Page 37: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Un esempioPer verificare la correttezza del codice, si può eseguire alcune volteil programma, verificando a mano il conto:

$ g++ test1.cc ‐o test1$ ./test1Insert two numbers separated by a space: 4 6The sum is 10

$ ./test1Insert two numbers separated by a space: ‐1 3The sum is 2

$

Page 38: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Test automaticiPer verificare automaticamente la correttezza del codice, si puòusare la funzione  assert , che si trova nel file  cassert :

#include <cassert>

void test_sum() {    // No need to write std::assert, as it is a macro    assert(sum(4, 6) == 10);    assert(sum(‐1, 3) == 2);}

Se c'è un errore, il programma si blocca con un messaggio:

$ ./test2test2.cc:4:void test_sum(): Assertion `sum(‐1,3) == 2' failedAborted (core dumped)$

Page 39: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Test automaticiIl problema è: chi chiama la funzione  test_sum ? Possibilità:

Viene eseguita sempre, prima che il programma inizi la suavera esecuzione:

int main() {    test_sum();    std::cout << "Insert two numbers separated by a space: ";    // ...}

Si modifica il programma in modo che possa funzionare in duemodalità: nella prima funziona regolarmente, nella secondaesegue solo i test.

Page 40: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Test automaticiDi solito si preferisce il secondo approccio: fare in modo che ilprogramma funzioni in due modalità. Questo approccio è infatti piùversatile e potente: in questo caso infatti è possibile ad esempioprodurre un report ﴾in HTML o PDF﴿ che elenca tutti i test eseguiti,indicando quali sono passati e quali sono falliti.

Per questo corso invece vi consiglio di eseguire i test sempre, primache inizi la «vera» esecuzione: è meno complicato e comunquesufficiente per i piccoli programmi che svilupperemo.

Page 41: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Consigli per gli esercizi

Page 42: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Esercizio 1.2 − Scambio di elementi di unvettoreScrivete una funzione che accetti in ingresso un puntatore alvettore:

void swap_pairs(int num_of_elements, double array[]) {    // …}

In questo modo potrete implementare una procedura di test:

void test_swap() {    // N.B. These must be integers!    /// (see the next exercise to understand why)    double my_array[] = { 1.0, 2.0, 3.0, 4.0 };    swap_pairs(4, my_array);    assert(my_array[0] == 2.0 && my_array[1] == 1.0);    assert(my_array[2] == 4.0 && my_array[3] == 3.0);}

Page 43: Maurizio Tomasi ﴾turno A2﴿ Giovedì 12 Ottobre 2017cosmo.fisica.unimi.it/assets/LezioniTNDS/AA2017-2018/2017-10-12-lezione-01.pdf · I Makefile non sono portabili: il fatto che

Lettura del file di dati ﴾esercizio 1.2﴿Per leggere il file, seguite questa logica:

1. Aprite il file con  std::ifstream  e controllate che sia statoaperto senza errori

2. Leggete il primo numero in una variabile intera, es. num_of_samples 

3. Allocate un array con  new double[num_of_samples] 4. Leggete uno per uno tutti i valori con un ciclo  for , salvandoli

nell'array appena creato

La scrittura del file di output è più semplice, perché non doveteallocare altri array.