Indice Introduzione al C++ (CAP 1) • Scrittura del primo programma in C++ Alberto Garfagnini e Marco Mazzocco Università degli studi di Padova • elementi costitutivi del programma • compilazione ed esecuzione • La gestione di INPUT e OUTPUT • le streams (istream/ostream) A.A. 2014/2015 • I commenti al codice • La gestione del flusso di controllo • while • for • if • Le classi Materiale di riferimento • Libri di testo consigliati : 3 Lippman, Lajoie, Moo, “C++ Primer”, Addison-Wesley, ISBN: 978-0321714114 3 S. Prata, “C++ Primer Plus”, Addison-Wesley, ISBN: 978-0321776402 • eventuali libri di consultazione avanzata : Struttura di un programma in C++ • Ogni programma in C++ è costituito da una o più funzioni • La funzione principale (e irrinunciabile) è chiamata main • Programma minimale 1 3 B. Stroustrup, “The C++ Programming Language”, Addison-Wesley, ISBN: 978-0321563842 3 Brandolese, Giuliani, “C++2011, Programmazione e caratteristiche dello standard 2011”, Pearson, ISBN:978-88-7192-645-2 2 3 int main () { return 0; 4 } • Per definire una funzione bisogna specificare 4 elementi chiave : 1. 2. 3. 4. un tipo di ritorno il nome della funzione una lista di parametri (può essere vuota) il corpo della funzione La funzione main() • È l’elemento fondamentale, irrinunciabile Compilazione/Esecuzione di un programma Punto di partenza per ogni programma 1. Salvare il programma in un file con estensione .cc, .cxx, .cpp, .cp, oppure .C • Il tipo di ritorno è int (intero) built-in type del C++ • La lista dei parametri può essere vuota $ g++ program0.cxx nelle parentesi ( ) , dopo il nome int main() { ... return 0; } int main(int argc, int main(int argc, char * argv[]) char ** argv) { { ... ... return 0; return 0; } } no parameters C-style format 2. Invocare il compilatore da linea di comando (dalla shell) C++ format 3. Viene creato un file eseguibile di nome a.out 4. Eseguire il programma $ ./a.out 5. Verificare il valore di ritorno dalla shell $ echo $? 0 iostream INPUT/OUTPUT in C++ • Il C++ non definisce nessuna istruzione specifica di I/O • Viene fornita una intera libreria (Standard Library) con classi e oggetti • La libreria definisce 4 oggetti (con relative classi): 3 istream + cin : lettura da standard input stdin specifiche per I/O iostream 3 ostream + cout : scrittura sullo standard output stdout istream (INPUT) ostream (OUTPUT) + cerr : scrittura su standard error stderr + clog : scrittura su log (standard logging stream), di default sincronizzato su cerr • Stream: sequenza di caratteri letti o scritti da dispositivi di I/O (tastiera, terminale, file su disco, file in rete) i caratteri vengono generati/acquisiti sequenzialmente nel tempo • in UNIX (LINUX et al.), e WINDOWS vengono gestiti dal sistema operativo iostream: esempio d’uso iostream: header file • scriviamo un programma per il calcolo della somma di due numeri int main() #include <iostream> int main() { std::cout << "Inserire due interi: "; 3 Include un header file per poter usare le librerie di I/O std::cout << "Inserire due interi: "; • compiliamo ed eseguiamo il int v1 = 0, v2 = 0; std::cin >> v1 >> v2; programma std::cout << "La somma di " << v1; std::cout << " + " << v2 << " = " << v1+v2 << std::endl; $ g++ sum_int.cxx $ $ ./a.out Inserire due interi: 3 4 La somma di 3 + 4 = 7 $ $ echo $? 0 return 0; } int v1 = 0, v2 = 0; std::cin >> v1 >> v2; std::cout << "La somma di " << v1; std::cout << " + " << v2 << " = " << v1+v2 << std::endl; istream: std::cin #include <iostream> #include <iostream> 3 std::cout è un oggetto della classe ostream int main() std::cout << "Inserire due interi: "; int v1 = 0, v2 = 0; std::cin >> v1 >> v2; std::cout << "La somma di " << v1; std::cout << " + " << v2 << " = " << v1+v2 << std::endl; È un manipolatore: invia un carattere newline 3 ogni programma che voglia usare delle librerie (STL o altre) deve includere gli header files corrispondenti 3 Normalmente tutti gli header file sono inclusi in testa al programma, fuori dalle funzioni return 0; ostream: std::cout return 0; direttiva del preprocessore #include <iostream> interi int main() 3 Definiamo due variabli v1 e v2 di tipo intero per poter immazzinare i dati di input std::cout << "Inserire due interi: "; 3 L’operatore << è binario: 3 a sx: oggetto ostream 3 a dx: operando del quale stampare il valore int v1 = 0, v2 = 0; std::cin >> v1 >> v2; std::cout << "La somma di " << v1; std::cout << " + " << v2 << " = " << v1+v2 << std::endl; 3 L’operatore >> è binario: 3 a sx: oggetto istream 3 a dx: oggetto nel quale immagazzinare l’input 3 nell’esempio manda una stringa costante allo standard output equivalente a (std::cout << "La somma di") << v1; 3 std::cin è un oggetto della classe istream return 0; Il primo stampa una stringa, il secondo un intero equivalente a (std::cin >> v1) >> v2; 3 Come nell’esempio precedente è possibile combinare una sequenza di input I commenti nel codice Utilizzo delle classi della Standard Library • I commenti migliorano leggibilità e comprensione del codice • Nel programma abbiamo scritto std::cout e std::cin per utilizzare due oggetti delle classi iostream • Sono ignorati dal compilatore e non hanno quindi nessun effetto sulle prestazioni dei programmi • Il prefisso std:: indica che cout e cin sono definiti nel namespace chiamato std • Due sintassi possibili: 3 Tutti i nomi definiti dalla Standard Library sono nel namespace std 3 single-line : iniziano con due caratteri ’slash’ (//) e terminano a fine riga. tutti i caratteri dalla destra dei due caratteri // sono ignorati dal compilatore • I namespace permettono di evitare collisioni tra nomi definiti dall’utilizzatore e nomi di libreria 3 paired : sono racchiusi dai marcatori /* e */ operatore di scope std::cout standard library namespace oggetto della libreria // Commento int main() { return 0; } /* Un commento su piu’ righe */ int main(int argc, char ** argv) { return 0; } int main(int argc, char * argv[]) { int v = 1; // Un commento return 0; } Il ciclo while Il controllo del flusso del programma • l’istruzione while esegue ripetutamente una blocco di codice fintanto che una condizione fissata è vera • Le istruzioni di un programma sono eseguite sequenzialmente • a volte è necessario alterare il normale flusso di esecuzione #include <iostream> 3 eseguendo porzioni di codice soltanto se determinate condizioni sono verificate 3 eseguendo blocchi di istruzioni in maniera ripetitiva int main() { int sum = 0, val = 1; while (val <= 10) { sum += val; ++val; } std::cout << "Somma da 1 a 10 => " << sum << std::endl; return 0; } 3 compiliamo ed eseguiamo il programma: $ g++ sum10_while.cxx $ $ ./a.out Somma da 1 a 10 => 55 Il ciclo while • la sintassi del comando è: Il ciclo for • il ciclo for permette di esegire ripetutamente una blocco di codice un Prima del ciclo numero fissato (o variabile) di volte while (condition) statement false • la condizione viene controllata test ad ogni ciclo, fino a quando è falsa esce dal ciclo int main() { int sum = 0; true • blocco = sequenza di zero o più body istruzioni. Può essere usato dove è richiesto uno statement 3 sum += val; #include <iostream> for (int val=0; val <= 10; ++val) { sum += val; } std::cout << "Somma da 1 a 10 => " << sum << std::endl; return 0; operatore (binario) += composto di assegnazione equivalente 3 compiliamo ed eseguiamo il programma: $ g++ sum10_for.cxx $ $ ./a.out Somma da 1 a 10 => 55 } 3 sum = sum + val; 3 ++val; operatore (unario) di incremento → val = val + 1; Il ciclo for • la sintassi del comando è: Esempio: lettura di un numero arbitrario di valori inizializzazione for (init; test; update) statement #include <iostream> programma false • Il ciclo for è composto di due test parti: 1. un header 2. un body esce dal ciclo int main() { int sum = 0, value = 0; while (std::cin >> value) { sum += value; } std::cout << "The sum is: " << sum << std::endl; return 0; true body • l’header controlla quante volte viene eseguito il body. • compiliamo ed eseguiamo il update_expr È composto di tre parti: 1. inizializzazione 2. condizione da verificare per l’esecuzione del ciclo 3. espressione di aggiornamento di fine ciclo $ g++ read_many.cxx $ $ ./a.out 3 4 5 6 <ctrl-d> The sum is: 18 } • i dati sono letti nel while dall’istruzione std::cin >>value • il valore di ritorno viene verificato dal while : se il valore di ritorno è valido, il risultato è true; in caso contrario (es: valore non intero, end-of-file) il risultato è false end-of-file: UNIX <ctrl-d>, WINDOWS <ctrl-z> Lo statement condizionale if Lo statement condizionale if • permette di eseguire pezzi di codice condizionatamente • Il primo if 3 compiliamo ed eseguiamo il programma: 42 42 42 42 55 55 62 100 100 100 if (std::cin >> currVal) { 42 inserito 4 volte int cnt = 1; 55 inserito 2 volte while (std::cin >> val) { 62 inserito 1 volte if (val == currVal) { 100 inserito 3 volte ++cnt; } else { std::cout << currVal << " inserito " << cnt << " volte" << std::endl; currVal = val; cnt = 1; } } std::cout << currVal << " inserito " << cnt << " volte" << std::endl; } return 0; } Formattazione del codice (1) assicura che l’input non sia vuoto: se c’è un valore valido viene immagazzinato in currVal • usiamo un variabile cnt per contare le occorrenze dello stesso numero • il corpo del while contiene un secondo if if (val == currVal) { // se stesso valore cnt++; // incrementa cnt di 1 } else { // altrimenti stampa il valore std::cout << currVal << " inserito " << cnt << " volte" << std::endl; currVal = val; // ricordati del nuovo valore cnt = 1; // e resetta il contatore } A : In C++ ’=’ indica assegnazioni e ’==’ uguaglianze Formattazione del codice (2) Il codice seguente è valido ma difficile da leggere . . . Alcuni linguaggi sono line-oriented (es. FORTRAN) • C, C++: il punto-e-virgola, ’;’ marca la fine di una istruzione • L’utilizzo di spaziatori (<tab>, <space>) e ’\n’ è libera • Unica regola: le parole chiave (tokens) non posso essere separate Codice ben formattato // myfirst.cpp - stampa dei messaggi sullo schermo #include <iostream> int main( ) { using namespace std; cout << "Il nostro primo programma."; cout << endl; cout << "Impariamo il C++" << endl; return 0; } if (std::cin >> currVal) { ... } // myfirst.cpp - stampa dei messaggi sullo schermo #include <iostream> int main ( ) { using namespace std ; cout << "Il nostro primo programma." ; cout << endl; cout << "Impariamo il C++" << endl; return 0 ; } Codice mal formattato #include <iostream> int main() { int currVal = 0, val = 0; Introduzione alle classi Ancora sulla formattazione • C++ is a free-format language, → dove mettiamo le parentesi graffe, • Le classi del C++ sono lo strumento per estendere il linguaggio: l’indentazione, commenti, dove andiamo a capo non hanno effetti sul programma 3 permettono di definire una nuova struttura di dati 3 e un insieme di operazioni sui dati • le scelte che facciamo hanno una ripercussione sulla leggibilità del codice • non esiste un unico stile corretto, ma una volta scelto, siate coerenti e • lo scopo è definire delle classi che si comportino naturalmente come i consistenti durante la scrittura del codice tipi propri del C++ (esempio: numeri complessi come estensione naturale dei numeri reali) • Alcuni suggerimenti: 1. Mantenere una sola istruzione per linea 2. Le parentesi di apertura e chiusura del blocco di una funzione vanno posti su righe separate 3. Tutte le istruzioni all’interno di un blocco vanno indentate rispetto alle parentesi • per definire una classe è necessario specificare 1. il suo nome 2. dove è definita 3. quali operazioni supporta • Alcune referenze alla letteratura sugli standard di codifica in rete: • Esercizio: definire una classe che permetta di scrivere un programma • GOOGLE C++ style guide : http://goo.gl/iFKPU8 che tenga conto dei libri venduti in una libreria • Linux kernel coding style : http://goo.gl/kyCGtj • Ogni vendita ha: codice ISBN del libro, numero di copie vendute, • Wikipedia indent style : http://goo.gl/jPLr prezzo al quale sono state vendute es: ISBN: 0-321-71411-3, copie vendute: 1, prezzo: 32.18 e Ogni classe definisce un nuovo tipo I/O con oggetti Sales_item Sales_item libro 4 libro è un oggetto della classe Sales_item 4 deve immagazzinare: codice ISBN insieme di caratteri copie vendute numero intero prezzo unitario numero reale #include <iostream> #include "Sales_item.h" int main() { Sales_item book; std::cin >> book; std::cout << book << std::endl; 3 operazioni richieste: 4 fornire codice ISBN dell’oggeto della classe 4 usare gli operatori di I/O (>> e <<) per leggere e scrivere oggetti della classe 4 usare l’operatore = per copiare un oggetto Sales_item in un altro 4 usare l’operatore + per sommare due oggetti con lo stesso codice ISBN ⇒ il risultato è un oggetto con stesso ISBN, somma delle copie vendute e prezzo come media pesata dei prezzi dei libri 4 usare l’operatore composto ++ per sommare oggetti con stesso ISBN 3 compiliamo ed eseguiamo il programma: $ g++ -std=c++11 io.C $ $ ./a.out 0-321-71411-3 2 32.18 0-321-71411-3 2 64.36 32.18 return 0; } ISBN copie vendute prezzo unitario totale • La classe Sales_item rispecchia le caratteristiche dello standard C++11 → compiliamo richiedendo la compatibilità (opzione del g++: -std=c++1) Operazioni su oggetti Sales_item Le funzioni membro di una classe 3 Nel programma precedente incontriamo lo statement #include <iostream> #include "Sales_item.h" int main() { Sales_item book1, book2; std::cin >> book1 >> book2; if (book1.isbn() == book2.isbn()) { std::cout << book1 + book2 << std::endl; return 0; } else { std::cerr << "I libri devono avere" << " lo stesso ISBN" << std::endl; return 1; } 3 compiliamo ed eseguiamo il programma: $ g++ -std=c++11 add.C $ $ ./a.out 0-321-71411-3 2 32.18 0-321-71411-3 1 32.18 0-321-71411-3 3 96.54 32.18 $ $ ./a.out 0-321-71411-3 2 32.18 0-321-56384-0 1 42.49 I libri devono avere lo stesso ISBN if (book1.isbn() == book2.isbn()) { 3 L’istruzione book1.isbn() invoca la funzione isbn() che è definita come parte della classe Sales_item 3 Le funzioni membro di una classe sono anche chiamate metodi operatore di chiamata book1.isbn() nome dell’oggetto nome della funzione operatore di appartenenza 3 l’invocazione restituisce il codice ISBN immagazzinato nell’oggetto book1 } Il programma finale #include <iostream> #include "Sales_item.h" int main() { Sales_item total; // - Leggiamo la prima transazione if (std::cin >> total) { Sales_item next; while (std::cin >> next) { if (total.isbn() == next.isbn()) { total += next; } else { //print the result std::cout << "-> " << total << std::endl; total = next; } } // Stampa l’ultima transazione std::cout << "-> " << total << std::endl; } else { std::cerr << "No valid data" << std::endl; return -1; } return 0; } 3 compiliamo ed eseguiamo il programma: $ g++ -std=c++11 libreria.C $ ./a.out 0321714113 7 32.18 0321714113 3 30.00 0321563840 2 37.49 -> 0321714113 10 315.26 31.526 0321958322 1 50.56 -> 0321563840 2 74.98 37.49 0321958322 1 48.75 0321776402 8 34.66 -> 0321958322 2 99.31 49.655 0321776402 3 35.00 <ctrl-d> -> 0321776402 11 382.28 34.7527 3 è possibile ridirigere l’input, leggendo i dati da un file $ ./a.out < lista_libri.txt -> 0321714113 10 315.26 31.526 -> 0321563840 2 74.98 37.49 -> 0321958322 2 99.31 49.655 -> 0321776402 11 382.28 34.7527
© Copyright 2024 Paperzz