1
Il main programIl main program• Ogni programma in C++, per essere
eseguibile, deve contenere una funzione main() da cui l’esecuzione comincerà
• main() deve avere un tipo (decidere quale è compito del programmatore). Regola generale è che main() ritorni un intero, a significare il return code dell’applicazioneint main(){
// il piu` semplice programma in C++return 0;
}
int main(){
// il piu` semplice programma in C++return 0;
}
2
I/O: lettura e scritturaI/O: lettura e scrittura• Non esiste nel C++ nativo. Si usa: iostream
– Gli operatori << e >> sono usati per definire la direzione del flusso
– cin, cout e cerr rappresentano lo standard input, output e error del programma
#include <iostream>
using namespace std;int main(){ return 0;}
using namespace std;int main(){ return 0;}
direttiva al preprocessore
end of line
#include <iostream>
cout << “Hello, world !” << endl;
3
CommentiCommenti
• Esistono due tipi di commento in C++– inline:
– multiline (come in C):
– I due tipi possono essere usati indifferentemente, ma si raccomanda di usare l’inline (più semplice e meno ambiguo)
const int Ntries; // questo e` un commento inline// il resto della linea e’ trattato come un commento
const int Ntries; /* questo e` un commento multiline: tutto viene trattato come un commento fino a quando il commento stesso non viene chiuso con uno */
4
Tipi predefiniti in C++Tipi predefiniti in C++• Sono definiti una serie di tipi numerici che
permettono di rappresentare numeri interi, reali e caratteri
– char (un solo byte) viene normalmente usato per rappresentare interi inferiori a 256
– stringhe e numeri complessi sono implementati come tipi derivati
int intero in singola precisionelong intero in doppia precisionefloat reale in singola precisionedouble reale in doppia precisionelong double reale in precisione estesaunsigned int intero senza segnounsigned double reale senza segno in doppia precisionechar carattere singolobool variabili logiche
5
Tipi predefiniti in C++ (2)Tipi predefiniti in C++ (2)
123 123 0x123 interi costanti,decimale, ottale, esadecimale
123l 123u interi, long, unsigned
‘A’ ‘1’ ‘\t’ caratteri, tab3.14f 3.1415 3.1415L float, double,
long double300e-2 .03e2 30e-1 double, notazione
esponenziale“Nome” stringa costantetrue false boolean
Esempi di costanti ‘\a’ alert‘\\’ backslash‘\b’ backspace‘\r’ carriage return‘\”’ double quote‘\f’ form feed‘\t’ tab‘\n’ newline‘\0’ carattere nullo‘\’’ single quote‘\v’ vertical tab‘\101’ 101 ottale, ‘A’‘\x041’ esadecimale, ‘A’
Costanti carattere
“” stringa nulla (‘\0’)“nome” ‘n’ ‘o’ ‘m’ ‘e’ ‘\0’“una \”stringa\”” stampa: una “stringa”“una stringa \ un \ alla fine della linea su piu` linee” per continuare la stringa
Stringhe costanti
6
Tipi predefiniti in C++ (3)Tipi predefiniti in C++ (3)
char[1]
int[1]
bool
short[1]
long[1]
float
double
long double
8
16
16
16
32
32
64
64
8
32
32
16
32
32
64
128
8
32
32
16
64
32
64
128
OS16 bit
OS32 bit
OS64 bit
[1] Può essere unsigned
7
IdentificatoriIdentificatori• Un identificatore è composto da uno o più caratteri• Il primo carattere deve essere una lettera o un
underscore. Caratteri successivi possono essere lettere, numeri o underscore
• Non c’ è un limite in lunghezza, anche se alcuni sistemi si limitano a considerare i primi 31 caratteri
• Gli identificatori che iniziano con un doppio underscore o con un underscore e una lettera maiuscola sono riservati ad usi di sistema
• C++ e` case sensitive!
const int Ntries; double _attempts;double 2A; // errore!
8
KeywordsKeywords• Alcuni identificatori sono esplicitamente riservati al
sistema (hanno un preciso significato in C++) e non possono essere usati
asm else operator throwauto enum private truebool explicit protected trybreak extern public typedefcase false register typeidcatch float reinterpret_cast typenamechar for return unionclass friend short unsignedconst goto signed usingconst_cast if sizeof virtualcontinue inline static voiddefault int static_cast volatiledelete long struct wchar_tdo mutable switch whiledouble namespace templatedynamic_cast new this
keyword
9
constconst• La keyword const viene utilizzata per dichiarare
un oggetto costante
• In C le costanti vengono normalmente dichiarate usando il preprocessore– in questo caso N e` una costante senza tipo ed il
preprocessore sostituisce N ovunque lo trovi nel programma, senza rispettare le regole di scope (da evitare)
const int N=100; N non puo` essere cambiatodouble w[N]; N usato come per dimensionare
un vettoreconst int vect[5]= le componenti di vect non
{10,20,30,40,50}; possono essere cambiate
Esempi di const
#define N 100
10
DichiarazioneDichiarazione• Le dichiarazioni associano un significato ad
un identificatore• in C++ ogni cosa deve essere dichiarata per
poter essere usata
• Una dichiarazione è spesso anche una definizione. Per variabili semplici questo consiste nell’associare un valore alla variabile al momento della dichiarazione
const int i; // la variabile idouble max(double r1,double r2); // la funzione max
const double pi=3.1415926; // definizionedouble max(double r1, double r2) { // dichiarazione
return (r1>r2) ? r1: r2; // definizione di max}
11
typedeftypedef
• L’istruzione typedef viene utilizzata per creare un alias per tipi esistenti
• typedef NON può essere usato per implementare nuovi tipi, ma solo per definire un alias
typedef int INTEGER; // per i nostalgici del fortrantypedef int BOOLEAN; // usato prima che bool venisse
// implementatotypedef void (*ptr_f)(); // ptr_f e` un puntatore ad una
// procedura (subroutine)
typedef mela frutto; // compila soltanto se mela// e` gia` stata definita
12
EnumeratoriEnumeratori
• In C++ sono supportati tipi definiti dall’utente
enum Color{ red, green, blue};
Color screenColor = blue;Color windorColor = red;
int n = blue; // validoColor c = 1; // errore
enum Seme{ cuori, picche, quadri, fiori};
13
ScopeScope• Le variabili possono essere dichiarate e definite
quasi ovunque in un programma in C++• la visibilità (scope) di una variabile dipende da
dove la variabile è stata dichiarataint func(){
…const int n=50; // function scopefor (int i=0;i<100;i++) // i e` locale{
double r; // r e` locale...
}cout<<“n “<< n <<endl; // OKcout<<“i “<< i <<endl; // errore! Ma...cout<<“r “<< r <<endl; // errore!…
}
14
Scope (2)Scope (2)• Attenzione! La stessa variabile può essere ri-
dichiarata (con visibilità diversa). Questo è da evitare (se possibile) per non rendere il programma oscuro e a rischio di errore!
int i; // file (global) scopeint func(){
int i=50; // function scope, nasconde // la i a file scope
for (int i=0;i<100;i++) // block scope. Nasconde// la i a function scope
{int i; // questo e` un errore......
}cout<<“i “<< i <<“ “<< ::i <<endl;...
}Scope resolution operator
15
-i +w piu` e meno unaria*b a/b i%2 moltiplicazione,
divisione, moduloa+b a-b addizione e
sottrazione binariea=3; assegnazione
Espressioni Aritmetiche Commento
OperatoriOperatori
k = ++j; j=j+1; k=j;k = j++; k=j; j=j+1;k = --j; j=j-1; k=j;k = j--; k=j; j=j-1;
Auto-incremento Espressione e decremento
~i; Complemento bit a biti&j; AND bit a biti|j OR bit a biti^j XOR bit a biti<<n shift a sinistra di n pos.i>>n shift a destra di n pos.
bit-wise significato
< minore di .LT.> maggiore di .GT.<= minore o uguale .LE.>= maggiore o uguale .GE.== uguale .EQ.!= diverso .NE.! Negazione unaria .NOT.&& and logico .AND.|| or logico .OR.
Operatori relazionali Fortran
16
Espressioni di assegnazioneEspressioni di assegnazione• Le espressioni di assegnazione sono valutate da
destra a sinistra
• Le assegnazioni multiple sono permesse
• alcuni operatori di assegnazione combinano assegnazione ed altri operatori
• Assegnazioni possono essere fatte all’interno di espressioni aritmetiche
a = j++;j viene incrementato ed il risultato assegnato ad a
a = b = c = d = 100;
a *= b; // equivale ad a = a*b;a -= b; // equivale ad a = a-b;
a = b + ( c = 3 ); // equivale a c=3; a=b+c;
17
StatementsStatements
vuoto ;espressione j=j+k;composto { . . . . } usato in funzioni, if..
Costituisce un bloccogoto goto label; da non usarsiif if (p==0)
cerr<<“error”; un solo branchif-else if (x==y)
cout<<“the same”;else cout<<“different”; due branch
for for (j=0;j<n;j++) le dichiarazioni sonoa[j]=0; permesse
while while (i != j) 0 o piu` iterazioni i++;
do-while do y=y-1; 1 o piu` iterazioniwhile (y>0);
break break; esce dal bloccocontinue continue; prossima iterazione
Statement C++ commenti
18
Statements (2)Statements (2)
switch switch (s) {case 1: si deve usare break per
++i; evitare di cadere nei case 2: casi successivi e
--i; aggiungere un caso didefault: default alla fine della
++j; lista};
dichiarazione int i=7; in un blocco, file onamespace
try try {. . . .} usato per trattare leeccezioni
label error: cerr<<“Error!”; usato con goto
return return x*x*x; valore di ritorno di una funzione
Statement C++ commenti
19
Statement compostiStatement composti• Uno statement composto in è costituito da una
serie di statement contenuti fra parentesi graffe• Usato normalmente per raggruppare istruzioni in
un blocco (if, for, while, do-while, etc.)• Il corpo di una funzione è sempre uno statement
composto• La dichiarazione di una variabile può avvenire
ovunque all’interno di un blocco, in questo caso lo scope della variabile sarà il blocco stesso
• Ovunque si possa usare uno statement singolo si può definire un blocco
20
ifif• Attenzione all’uso di = e ==
• Nel dubbio, usare sempre un blocco…
• Attenzione agli else!
if (i=1) // questo e` sempre vero!!!{. . . .}
if (i != 0) // possibile divisione per 0a++; // mancano delle {}?a/=i;
if (i == 0) // possibile divisione per 0if (a<0)
{cerr<<“a e` negativo!”;
}else b=a/i;
21
while e do-whilewhile e do-while• La forma generale di un while è :
• Lo statement verrà eseguito fino a quando la condizione verrà verificata (true). A seconda del volore della condizione, lo statement verrà eseguito zero o più volte
• la sintassi di un do-while è invece:
• Lo statement verrà quindi eseguito almeno una volta
while (condizione)statement;
dostatement;
while (condizione);
22
break e continuebreak e continue• break e continue sono utilizzati nei loop per saltare
alla fine del loop o fuori dal loop stesso
• break e continue possono solamente essere utilizzati nel corpo di un for, while o do-while. break e` anche usato negli switch
int i,n=0;int a[100];cin>>i; // leggo il valore di iwhile (1) // loop infinito{
if (i<0) break;if (n>=100) continue;a[n]=i;n++;// continue salta qui
}// break salta qui
23
switchswitch• Lo switch è uno statement condizionale che
generalizza lo if-else
• lo statement è generalmente composito e consiste di diversi case e, opzionalmente, di un default
switch (condizione)(statement);
switch (n) {case 0:
cout<<“ n e` nullo”<<endl; break;case 1: case 3: case 5: case 7: case 9:
cout<<“ n e` dispari”<<endl; break;case 2: case 4: case 6: case 8: case 10:
cout<<“ n e` pari”<<endl; break;default:
cout<<“ n non e` compreso tra 0 e 10”<<endl;}
24
switch (2)switch (2)• Non si puo` dichiarare una variabile in uno dei case
• … ma si puo` creare una variabile locale definendo uno statement composto...
switch (k) {case 0:
int j=0; // Illegale! Errore!. . .
case 1: . . .
}
switch (k) {case 0:
{int j=0; // OK, questo compila. . .}
case 1: . . .
}
25
L’operatore ?L’operatore ?• L’operatore ? e` l’unico esempio di operatore
ternario in C++
– Equivale a:
– Esempio:
expr1 ? expr2 : expr3;
double max(double a, double b){
double max = (a>b) ? a : b;return max;
}
if(expr1) expr2;else expr3;
26
int main(){
return 0;}
int main(){
return 0;}
Funzioni matematicheFunzioni matematiche• In C++ non esistono funzioni predefinite
cmath.h definisce sin, cos, ...
{ double r, theta, phi;
#include <iostream>
cin >> r >> theta >> phi ;
#include <cmath>using namespace std;
double x = r * sin( theta ) * sin( phi ); double y = r * sin( theta ) * cos( phi ); double z = r * cos( theta );
cout << x << “, “ << y << “, “ << z << endl;
• Potenze: pow(b,exp) (non si può usare ** )
27
ArrayArray• Sono supportati gli array di dimensione fissaint main(){ int x[10];
for ( int i = 0; i < 10, i++ ) x[i] = 0;
double m[5][5];
for ( int i = 0; i < 5; i++ ) for ( int j = 0; j < 5; j++ ) m[i][j] = i * j;
return 0;}
int main(){ int x[10];
for ( int i = 0; i < 10, i++ ) x[i] = 0;
double m[5][5];
for ( int i = 0; i < 5; i++ ) for ( int j = 0; j < 5; j++ ) m[i][j] = i * j;
return 0;}
• L’indice va da 0 a n-1. Usare un indice maggiore di n-1 può causare un crash.
int x[] = { 1, 2, 3, 4 };
char[] t = { ‘C’, ‘i’, ‘a’, ‘o’, ‘\0’ };
char[] s = “Ciao”;
int m[2][3] = { {11, 12, 13}, {21, 22, 23} };
int x[] = { 1, 2, 3, 4 };
char[] t = { ‘C’, ‘i’, ‘a’, ‘o’, ‘\0’ };
char[] s = “Ciao”;
int m[2][3] = { {11, 12, 13}, {21, 22, 23} };
• Inizializzazione:
28
Esempio con gli arraysEsempio con gli arrays• Moltiplicazione fra matrici:
int main() {
const int DIM=3;
float m[DIM][DIM], m1[DIM][DIM], m2[DIM][DIM]; // Assumiamo che m1 ed m2 vengano riempiti qui...
// Moltiplicazione:
for (int i=0; i<DIM; i++) {
for (int j=0; j<DIM; j++) {
float sum=0;
for (int k=0; k<DIM; k++)
sum += m1[i][k] * m2[k][j];
m[i][j] = sum;
}
}
return 0;}
int main() {
const int DIM=3;
float m[DIM][DIM], m1[DIM][DIM], m2[DIM][DIM]; // Assumiamo che m1 ed m2 vengano riempiti qui...
// Moltiplicazione:
for (int i=0; i<DIM; i++) {
for (int j=0; j<DIM; j++) {
float sum=0;
for (int k=0; k<DIM; k++)
sum += m1[i][k] * m2[k][j];
m[i][j] = sum;
}
}
return 0;}
29
12240x7b03a928
PuntatoriPuntatori• Riferimento ad una locazione di memoria
j
12
ptr
using namespace std;
int main(){ int j = 12;
return 0;}
using namespace std;
int main(){ int j = 12;
return 0;}
int *ptr = &j;
#include <iostream>
cout << *ptr << endl; j = 24; cout << *ptr << endl; cout << ptr << endl;
indirizzo di memoria
24
30
PuntatoriPuntatori
• Puntatore nullo
#include <iostream>
using namespace std;
int main(){ int j = 12; int *ptr = 0;
cout << *ptr << endl; // crash ! return 0;}
#include <iostream>
using namespace std;
int main(){ int j = 12; int *ptr = 0;
cout << *ptr << endl; // crash ! return 0;}
Segmentation violation (core dumped)
j
12
ptr
31
Puntatori e arrayPuntatori e array
• In C gli array sono trattati come puntatori
int main(){ float x[5]; int j; for (j = 0; j < 5; j++) x[j] = 0;
float *ptr = x; *ptr = 1.5; // x[0] = 1.5 *(ptr+1) = 2.5; // x[1] = 2.5 *(ptr+3) = 3.5; // x[3] = 3.5}
int main(){ float x[5]; int j; for (j = 0; j < 5; j++) x[j] = 0;
float *ptr = x; *ptr = 1.5; // x[0] = 1.5 *(ptr+1) = 2.5; // x[1] = 2.5 *(ptr+3) = 3.5; // x[3] = 3.5}
x
X[0]
1.5
X[1] X[2] X[3] X[4]
2.5 0.0 3.5 0.0
X+1 X+3
32
Puntatori: allocazione dinamicaPuntatori: allocazione dinamica• Riferimento ad una locazione di memoria
#include <iostream>
using namespace std;
int main(){ int *ptr = new int;
*ptr = 12; cout << *ptr << endl;
delete ptr; return 0;}
#include <iostream>
using namespace std;
int main(){ int *ptr = new int;
*ptr = 12; cout << *ptr << endl;
delete ptr; return 0;}
12
ptr
• Attenzione:
– Non usare delete fa accumulare locazioni di memoria inutilizzate (memory leak)
– Utilizzare puntatori prima del new o dopo il delete causa il crash del programma
33
Puntatori: allocazione dinamicaPuntatori: allocazione dinamica
• Riferimento a più locazioni di memoria
#include <iostream>
using namespace std;
int main(){ int *ptr = new int[3];
ptr[0] = 10; ptr[1] = 11; ptr[2] = 12
delete [] ptr; return 0;}
#include <iostream>
using namespace std;
int main(){ int *ptr = new int[3];
ptr[0] = 10; ptr[1] = 11; ptr[2] = 12
delete [] ptr; return 0;} 10
ptr
11 12
34
new e deletenew e delete• Gli operatori new and delete vengono utilizzati
per allocazione/deallocazione di memoria dinamica– la memoria dinamica (heap), è un’area di memoria libera
provvista dal sistema per quegli oggetti la cui durata di vita è sotto il controllo del programmatore
• new riserva la quantità necessaria di memoria richiesta e ritorna l’indirizzo di quest’area
int *i=new int; alloca un intero, returna il puntatorechar *c=new char[100]; alloca un array (stringa) di 100
caratteriint *i=new int(99); alloca un intero e lo inizializza a 99char *c=new char(‘c’); alloca un carattere inizializzato a cint *j=new int[n][4]; alloca un array di puntatori ad intero
operatore new commenti
35
new e delete (2)new e delete (2)• L’operatore delete è usato per restituire una
certa area di memoria (allocata con new) allo heap• Ogni oggetto allocato con new deve essere
distrutto con delete se non viene piu` utilizzato, altrimenti l’area di memoria che esso occupata non potra` piu` essere ri-allocata (memory leak)
• L’argomento di delete è tipicamente un puntatore inizializzato preventivamente con new
delete ptr; distrugge un puntatore ad un oggettodelete p[i]; distrugge l’oggetto p[i]delete [] p; distrugge ogni oggetto di tipo p
operatore delete commenti
36
new e delete (3)new e delete (3)
• Attenzione– la dimensione dello heap non e` infinita– l’allocazione con new può fallire, nel qual caso new
restituisce un puntatore nullo o suscita un’eccezione. Nel caso di allocazione di memoria importante bisogna verificare che l’operazione abbia avuto successo prima di usare il puntatore
– ogni oggetto creato con new deve essere distrutto con delete, ogni oggetto creato con new [] deve essere distrutto con delete [] , queste forme NON sono intercambiabili
Top Related