CPP - INFN - Sezione di Padova

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