Lezione del 11/7/2006¶
-
L’I/O del C++, alcuni esempi
File ex010.cc
1/* 2 * Il sistema di I/O in C++ 3 * 4 */ 5 6#include <iostream> // includo le definizioni per I/O in c++ 7#include <iomanip> // manipolatori per la formattazione 8 9#include <cmath> // sin, cos, tan etc 10 11using namespace std ; 12 13#include <stdio.h> // Input Output del C per fare dei confronti 14 15// le definizioni dell'I/O sono contenute in un namespace di nome std. 16// per estrarre tutto il contenuto del namespace std si usa l'istruzione 17// scritta sopra. 18// In namespace verra' descritto meglio piu' avanti 19 20/* 21 22 con iostream di definiscono 3 oggetti 23 24 cin : oggetto per la gestione dello standard input (lettura terminale) 25 analogo del file descriptor (di tipo FILE *) stdin 26 27 cout : oggetto per la gestione dello standard output (scrittura su terminale) 28 analogo del file descriptor (di tipo FILE *) stdout 29 30 cerr : oggetto per la gestione dello standard output di errore (scrittura su terminale) 31 analogo del file descriptor (di tipo FILE *) stderr 32 33 La differenza tra cout e cerr e' che cerr non e' bufferizzato, 34 cioe' la scrittura sul file e' immediata. 35*/ 36 37/* 38 I "COMANDI" per scrivere e leggere con questi oggetti sono 39 principalemente 2 40 41 operatore << che viene usato negli oggetti cout e cerr per mandare 42 un oggetto (int,doble,stringa etc) in uscita 43 44 operatore >> che viene usato nell oggetto cin per leggere 45 un oggetto (int,doble,stringa etc) da terminale 46*/ 47 48int 49main() { 50 /* esempio di stampa di una stringa */ 51 52 cout << "ciao sono una stringa\n" ; // output con l'I/O del C++ 53 printf( "ciao sono una stringa\n" ) ; // output con l'I/O del C 54 55 /* esempio di stampa di un intero con messaggio */ 56 int i = 234 ; 57 cout << "i = " << i << "\n" ; // output con l'I/O del C++ 58 // Questa linea e' equivalente 59 // cout << "i = " ; 60 // cout << i ; 61 // cout << "\n" ; 62 // 63 // << e' associativo a sinistra, va pensato come +, 64 // ad esempio a+b+c+d e' come scrivere 65 // (((a+b)+c)+d) 66 // ed e' come eseguire 67 // tm1 = a+b ; tmp2 = tmp1 + c ; tmp3 = tmp2 + d 68 // 69 ((cout << "i = ") << i ) << "\n" ; // output con l'I/O del C++ 70 71 printf( "i = %d\n", i ) ; // output con l'I/O del C 72 73 /* vantaggio dell'I/O tipo C++, se ora cambio uscita da int a double 74 devo cambiare il formattatore in C */ 75 double a = 2.45 ; 76 cout << "a = " << a << "\n" ; // output con l'I/O del C++ 77 printf( "a = %g\n", a ) ; // output con l'I/O del C 78 79 /* svantaggi e' piu' logorroico il modo la formattazione in C++ */ 80 //cout . setprecision(5) ; 81 cout << "a = **" << setw(10) << setprecision(5) << left << a << "**\n" ; // output con l'I/O del C++ 82 printf( "a = **%10.5f**\n", a ) ; // output con l'I/O del C 83 84 /* 85 Manipolatori principali 86 87 setw(size) riserva size caratteri per il prossimo output 88 left allinea la prossima stampa a sinistra 89 setprecision(digit) numero massimo di cifre (compreso il punto e il segno) 90 riservate per stampare un numero 91 92 dec stampa l'intero successivo in decimale 93 oct stampa l'intero successivo in ottale 94 hex stampa l'intero successivo in esadecimale 95 uppercase stampa in numero esadecimale in maiuscolo 96 */ 97 98 /* esempio stampa di pigrego a varie precisioni */ 99 double pi = 4*atan(1.0) ; 100 cout << "pi(3cifre) = " << setprecision(3) << pi << "\n" 101 << "pi(5cifre) = " << setprecision(5) << pi << "\n" 102 << "pi(10cifre) = " << setprecision(10) << pi << "\n" 103 << "pi(15cifre) = " << setprecision(15) << pi << "\n" 104 << "pi(20cifre) = " << setprecision(20) << pi << "\n" 105 << "pi(30cifre) = " << setprecision(30) << pi << "\n" 106 << "pi(50cifre) = " << setprecision(50) << pi << "\n" 107 << "pi(100cifre) = " << setprecision(100) << pi << "\n" ; 108 109 cout << "123 in varie basi: " 110 << dec << 123 << " decimale\n" 111 << oct << 123 << " ottale\n" 112 << hex << uppercase << 123 << " esadecimale\n" << dec ; 113 114 /* esempio di lettura da terminale */ 115 cout << "inserisci un intero: " ; 116 cin >> i ; 117 cout << "hai inserito " << i << "\n" ; 118 119 cout << "inserisci un intero e un floating point: " ; 120 cin >> i >> a ; 121 if ( !cin ) { // ! applicato all'oggetto di I/O restuisce un booleano 122 // true se c'e' stato un errore. 123 cerr << "Errore in lettura dei dati\n" ; 124 } 125 cout << "hai inserito " << i << " ed " << a << "\n" ; 126}
-
L’I/O del C++, scrittura su file
File ex011.cc
1/* 2 * Il sistema di I/O su file in C++ 3 * e i tipo bool aggiunti nel C++ 4 */ 5 6#include <iostream> // includo le definizioni per I/O in c++ 7#include <fstream> // includo le definizioni per I/O su FILE in c++ 8#include <iomanip> // manipolatori per la formattazione 9 10#include <cmath> // sin, cos, tan etc 11 12using namespace std ; 13 14int 15main() { 16 /* esempio di lettura da un file in C++ */ 17 // ifstream e' il tipo oggetto di lettura 18 ifstream file ; // definisco file come oggetto (descrittore) di un file in lettura 19 20 file . open("pippo.txt") ; // apro in lettura il file pippo.txt 21 22 bool not_ok = ! file ; // bool e' il tipo booleano 23 // puo assumere sono due valori : true e false 24 // in questo caso not_ok = true se qualcosa e' andato 25 // storto 26 if ( not_ok ) { 27 cerr << "Errore in apertura del file pippo.txt\n" ; 28 } 29 30 // ! applicato all'oggetto file restituisce un booleano. 31 // ! opertore di negazione di un booleano scambia true <-> false 32 // file da solo e' oggetto di I/O NON UN BOOLEANO 33 // !(!file) e' un booleano che vale true se tutto va bene 34 cout << "INIZIO LETTURA (MODO SINGOLA STRINGA)\n" ; 35 while ( ! file . eof() ) { 36 char line[1000] ; 37 file >> line ; // leggo una stringa fino al primo spazio,tab o return etc, 38 if ( !file ) break ; // se c'e' un errore interrompo il ciclo 39 cout << "HO LETTO: " << line << "\n" ; 40 } 41 cout << "FINE LETTURA\n" ; 42 file . clear() ; // resetto tutti i flags di errore 43 file . seekg(ios::beg) ; // mi posisiziono all'inizio del file pippo.txt 44 // vanno resettati i flags altimenti non posso 45 // eseguire nessun comando sul file 46 cout << "INIZIO LETTURA (MODO SINGOLA STRINGA)\n" ; 47 while ( ! file . eof() ) { 48 char line[1000] ; 49 file . getline(line,1000) ; // leggo una stringa fino al primo spazio,tab o return etc, 50 // per un massimo di 1000 caratteri 51 if ( !file ) break ; // se c'e' un errore interrompo il ciclo 52 cout << "HO LETTO: " << line << "\n" ; 53 } 54 cout << "FINE LETTURA\n" ; 55 56 file . close() ; // chiusura del file pippo.txt 57}
-
Allocazione dinamica new e delete
File ex012.cc
1/* 2 * Cosa ha di diverso il C++ a basso livello. 3 * 4 */ 5 6/* 7 * new e delete al posto di malloc/free 8 */ 9 10#include <iostream> // includo le definizioni per I/O in c++ 11#include <iomanip> // manipolatori per la formattazione 12#include <cmath> // sin, cos, tan etc 13 14using namespace std ; 15 16 17/* 18 * Esempio stupido di uso di new e delete 19 * 20 * dato un vettore V di n numeri, costruisco un W 21 * vettore di dimensione n-1 che contiene le differenze 22 * successive del vettore V cioe' 23 * 24 * W[i] = V[i+1]- V[i] 25 */ 26 27int 28main() { 29 int V[] = {1,2,3,1,0,3,5,7,0}; // vettore di partenza 30 int * W ; // puntatore al vettore da allocare 31 32 int n = sizeof(V)/sizeof(V[0]) ; // dimensione del vettore V 33 34 W = new int [ n-1 ] ; 35 /* ^ ^ ^ 36 * | | | 37 * | | +-- quanti elementi alloco 38 * | | 39 * | +---- tipo di elementi da allocare 40 * | 41 * | 42 * +---- operatore di allocazione 43 * 44 * e "equivalente" al codice C 45 * 46 * W = (int*) malloc( (n-1) * sizeof(int) ); 47 * 48 * occhio che non si puo' fare la free(W) perche' il meccanismo 49 * di allocazione e' diverso. 50 * 51 */ 52 53 // eseguo l'algoritmo 54 for ( int i = 0 ; i < n-1 ; ++i ) W[i] = V[i+1] - V[i] ; 55 56 // rilascio la memoria 57 58 delete [] W ; 59 /* ^ ^ ^ 60 * | | | 61 * | | +--- puntatore al vettore da deallocare 62 * | | 63 * | +----- [] indica che si tratta di un vettore e non di un singolo elemento 64 * | 65 * +---------- operatore di rilascio della memoria 66 * 67 * e "equivalente" al codice C se avessi alloocato W con la malloc 68 * 69 * free(W) ; 70 */ 71 72 73 /* 74 * SI possono allocare singoli elementi come segue 75 */ 76 77 double * p ; 78 p = new double ; // allocato spazio per un singolo numero floating point 79 80 *p = 12.23 ; 81 82 double a = 12+*p ; 83 84 cout << "a = " << a << "\n" ; 85 86 delete p ; 87 88 /* nel caso di singoli elementi si omettono le [] */ 89 90}
-
Il blocco try/catch/throw
File ex013.cc
1/* 2 * Cosa ha di diverso il C++ a basso livello. 3 * 4 */ 5 6/* 7 * new e delete al posto di malloc/free 8 */ 9 10#include <iostream> // includo le definizioni per I/O in c++ 11#include <iomanip> // manipolatori per la formattazione 12#include <cmath> // sin, cos, tan etc 13 14using namespace std ; 15 16 17/* 18 * Esempio stupido di uso di new e delete 19 * 20 * dato un vettore V di n numeri, costruisco un W 21 * vettore di dimensione n-1 che contiene le differenze 22 * successive del vettore V cioe' 23 * 24 * W[i] = V[i+1]- V[i] 25 */ 26 27int 28main() { 29 int V[] = {1,2,3,1,0,3,5,7,0}; // vettore di partenza 30 int * W ; // puntatore al vettore da allocare 31 32 int n = sizeof(V)/sizeof(V[0]) ; // dimensione del vettore V 33 34 W = new int [ n-1 ] ; 35 /* ^ ^ ^ 36 * | | | 37 * | | +-- quanti elementi alloco 38 * | | 39 * | +---- tipo di elementi da allocare 40 * | 41 * | 42 * +---- operatore di allocazione 43 * 44 * e "equivalente" al codice C 45 * 46 * W = (int*) malloc( (n-1) * sizeof(int) ); 47 * 48 * occhio che non si puo' fare la free(W) perche' il meccanismo 49 * di allocazione e' diverso. 50 * 51 */ 52 53 // eseguo l'algoritmo 54 for ( int i = 0 ; i < n-1 ; ++i ) W[i] = V[i+1] - V[i] ; 55 56 // rilascio la memoria 57 58 delete [] W ; 59 /* ^ ^ ^ 60 * | | | 61 * | | +--- puntatore al vettore da deallocare 62 * | | 63 * | +----- [] indica che si tratta di un vettore e non di un singolo elemento 64 * | 65 * +---------- operatore di rilascio della memoria 66 * 67 * e "equivalente" al codice C se avessi alloocato W con la malloc 68 * 69 * free(W) ; 70 */ 71 72 73 /* 74 * SI possono allocare singoli elementi come segue 75 */ 76 77 double * p ; 78 p = new double ; // allocato spazio per un singolo numero floating point 79 80 *p = 12.23 ; 81 82 double a = 12+*p ; 83 84 cout << "a = " << a << "\n" ; 85 86 delete p ; 87 88 /* nel caso di singoli elementi si omettono le [] */ 89 90}
File ex014.cc
1/* 2 * Cosa ha di diverso il C++ quasi a basso livello. 3 * 4 */ 5 6/* 7 * blocco try/catch/throw 8 * stesso esempio ma con l'uso di stdexcept per la throw 9 */ 10 11#include <iostream> // includo le definizioni per I/O in c++ 12#include <iomanip> // manipolatori per la formattazione 13#include <cmath> // sin, cos, tan etc 14 15 16#include <stdexcept> // definizione di oggetti standard per le eccezzioni 17 18/* 19 definisce delle strutture/classi 20 21 exception 22 23 da lanciare con la throw. 24 Le classi sono le seguenti 25 26 logic_error 27 domain_error 28 invalid_argument 29 length_error 30 out_of_range 31 runtime_error 32 range_error 33 overflow_error 34 underflow_error 35 36 */ 37 38using namespace std ; 39 40/* 41 * Il blocco try / catch / throw funziona in questo modo 42 * 43 44 try { 45 46 // codice utente 47 // qui posso "lanciare" una eccezzione "throw" 48 // se viene lanciata l'eccezzione in programma "salta" a fine blocco 49 } 50 catch ( tipo di eccessione ) { 51 // codice per gestire l'eccezzione 52 } 53 catch ( tipo di eccessione ) { 54 55 } 56 catch ( tipo di eccessione ) { 57 58 } 59 catch ( ... ) { 60 // questo blocco cattura qualunque tipo di eccezione 61 } 62 */ 63 64#define A(I,J) A[(I)+(J)*lda] 65 66void 67fattorizzazione_LU( double A[], /* matrice da fattorizzare memorizzata per colonne */ 68 int N, /* dimensione della matrice da fattorizzare */ 69 int lda, /* numero di righe usate in allocazione */ 70 int perm[] ) { /* vettori di interi di domensione >= N che conterra' la permutazione */ 71 72 int i, j, k, imax ; 73 double amax, acheck ; 74 75 /* Inizializzo il vettore della permutazione */ 76 for ( i = 0 ; i < N ; ++i ) perm[i] = i ; 77 78 for ( i = 0 ; i < N-1 ; ++i ) { 79 /* ricerca del pivot, cerco elemento di modulo massimo 80 nella colonna i-esima, cioe' A(i,i), A(i+1,i), ..., A(N-1,i) */ 81 imax = i ; 82 amax = fabs( A(i,i) ) ; 83 for ( j=i+1 ; j < N ; j++ ) { 84 acheck = fabs(A(j,i)); 85 if ( acheck > amax ) { 86 acheck = amax ; 87 imax = j ; 88 } 89 } 90 91 /* controllo che acheck > 0, se 0 la matrice e' singolare */ 92 93 /////////////// 94 /////////////// SE LA MATRICE E' SINGOLARE LANCIO UNA ECCEZIONE 95 /////////////// 96 if ( amax == 0 ) throw runtime_error("matrice singolare") ; 97 /* ^ ^ 98 * | | 99 * | +-- arcgomento del costruttore 100 * | 101 * +--- costruttore dell'oggetto runtime_error 102 * 103 */ 104 if ( imax != i ) { /* scambio la riga i con la riga imax */ 105 /* scambio indici sul vettore della permutazione */ 106 k = perm[i] ; 107 perm[i] = perm[imax] ; 108 perm[imax] = k ; 109 /* scambio delle righe nella matrice A */ 110 for ( j=0 ; j < N ; ++j ) { 111 amax = A(i,j) ; 112 A(i,j) = A(imax,j) ; 113 A(imax,j) = amax ; 114 } 115 } 116 117 /* costruisco la parte della matrice Li e la applico alla matrice 118 LU in costruzione */ 119 for ( k = i+1 ; k < N ; ++k ) { 120 amax = A(k,i) / A(i,i) ; 121 A(k,i) = amax ; 122 for ( j= i+1 ; j < N ; ++j ) 123 A(k,j) -= amax * A(i,j) ; 124 } 125 } 126 127 if ( A(N-1,N-1) == 0 ) throw runtime_error("LU eseguita ma matrice singolare") ; 128 129} 130 131void 132stampa_L( ostream & s, // uso l'oggetto s di tipo stream per l'I/O 133 double A[], // matrice da fattorizzare memorizzata per colonne 134 int N, // dimensione della matrice da fattorizzare 135 int lda ) { // numero di righe usate in allocazione 136 for ( int i = 0 ; i < N ; ++i ) { 137 for ( int j = 0 ; j < i ; ++j ) { 138 s << setw(10) << left << A(i,j) ; 139 } 140 s << "1\n" ; 141 } 142} 143 144void 145stampa_U( ostream & s, // uso l'oggetto s di tipo stream per l'I/O 146 double A[], // matrice da fattorizzare memorizzata per colonne 147 int N, // dimensione della matrice da fattorizzare 148 int lda ) { // numero di righe usate in allocazione 149 for ( int i = 0 ; i < N ; ++i ) { 150 for ( int j = 0 ; j < i ; ++j ) { 151 s << " " ; /* 10 spazi bianchi */ 152 } 153 for ( int j = i ; j < N ; ++j ) { 154 s << setw(10) << left << A(i,j) ; 155 } 156 s << "\n" ; /* vado a capo a fine riga */ 157 } 158} 159 160 161#undef A /* elimino la definizione di A(I,I) */ 162 163#define L(I,J) LU[(I)+(J)*lda] 164#define U(I,J) LU[(I)+(J)*lda] 165 166void 167solve_LU( double LU[], /* matrice fattorizzata memorizzata per colonne */ 168 int N, /* dimensione della matrice da fattorizzare */ 169 int lda, /* numero di righe usate in allocazione */ 170 int perm[], /* vettori di interi di domensione >= N che 171 conterra' la permutazione */ 172 double b[], /* temine noto */ 173 double x[] ) { /* soluzione */ 174 175 /* applico la permutazione */ 176 for ( int i = 0 ; i < N ; ++i ) x[perm[i]] = b[i] ; 177 178 /* Risolvo Lz = Pb */ 179 for ( int i = 1 ; i < N ; ++i ) 180 for ( int j = 0 ; j < i ; ++j ) 181 x[i] -= L(i,j)*x[j]; 182 183 /* Risolvo Ux = Lz */ 184 int i=N; 185 do { 186 --i ; 187 for ( int j = i+1 ; j < N ; ++j ) 188 x[i] -= U(i,j)*x[j]; 189 x[i] /= U(i,i) ; 190 } while ( i > 0 ) ; 191} 192 193int 194main() { 195 196 double M[] = { 197 4, 3, 2, 1, /* prima colonna */ 198 1, 2, 3, 4, /* seconda colonna */ 199 1, 0, 0, 1, /* terza colonna */ 200 1, 0, 0, 1, /* terza colonna */ 201 //0, 1, 2, 5 /* quarta colonna */ 202 } ; 203 204 double b[] = { 9, 11, 16, 32 } ; /* termine noto se la solzione e' 1,2,3,4 */ 205 double x[4] ; /* vettore che conterra' la soluzione */ 206 207 int i, perm[4] ; 208 209 int dim ; 210 211 dim = 4 ; 212 213 // usi try/catch per catturare l'eventuale messaggio di errore 214 try { 215 fattorizzazione_LU( M, dim, dim, perm ) ; 216 } 217 catch ( runtime_error const & exc ) { 218 cout << "ERRORE in fattorizzazione_LU:" << exc . what() << "\n" ; 219 exit(1) ; 220 } 221 catch ( ... ) { 222 cout << "ERRORE strano fattorizzazione_LU\n" ; 223 exit(1) ; 224 } 225 226 /* stampa della matrice L ed U e la permutazione */ 227 cout << "MATRICE L\n" ; 228 stampa_L( cout, M, dim, dim ); 229 230 cout << "MATRICE U\n" ; 231 stampa_U( cout, M, dim, dim ); 232 233 cout << "PERMUTAZIONE\n" ; 234 for ( i = 0 ; i < dim ; ++i ) 235 cout << "perm[" << i << "]=" << perm[i] << "\n" ; 236 237 solve_LU( M, dim, dim, perm, b, x ) ; 238 239 cout << "SOLUZIONE\n" ; 240 for ( i = 0 ; i < dim ; ++i ) 241 cout << "x[" << i << "]=" << x[i] << "\n" ; 242 243 return 0 ; 244 245}
-
Il namespace
File ex015.cc
1/* 2 * Cosa ha di diverso il C++ quasi a basso livello. 3 * 4 */ 5 6/* 7 * il namespace 8 * 9 * Il namesapce serve per evitare i conflitti di nomi. 10 * Ad esempio uno potrebbe usare due routione per l'ordinamento 11 * e chiamarla sort. Ma una implmenta in bubble sort e un'altra 12 * l'ordinamento shell sort. 13 * per evitare conlfitti invecie che moltiplicare i nomi 14 * si possono usare i namespace 15 * 16 */ 17 18 19namespace bubble { 20 void 21 sort( int N, int v[] ) { 22 for ( int i = 0 ; i < N-1 ; ++i ) 23 for ( int j = i+1 ; j < N ; ++j ) 24 if ( v[i] > v[j] ) { 25 int bf = v[i] ; v[i] = v[j] ; v[j] = bf ; // scambio 26 } 27 } 28} 29 30namespace shell { 31 // algoritmo tipo shell 32 void 33 sort( int N, int v[] ) { 34 bool fine ; 35 int k = N ; 36 do { 37 k /= 2 ; 38 if ( k == 0 ) k = 1 ; 39 fine = true ; 40 for ( int i = 0 ; i < N-k ; i += k ) { 41 if ( v[i] > v[i+k] ) { 42 fine = false ; 43 int bf = v[i] ; v[i] = v[i+k] ; v[i+k] = bf ; // scambio 44 } 45 } 46 } while ( !fine || k != 1 ) ; 47 } 48} 49 50int 51main() { 52 int v[] = {5,2,3, -1,3, 23,89,-23,4,-6} ; 53 int n = sizeof(v)/sizeof(v[0]) ; 54 55 // ordino in vettore con bubble sort 56 bubble::sort( n, v ); 57 /* ^ ^ ^ 58 * | | | 59 * | | +--- nome della routine di ordinamento 60 * | | 61 * | --- :: operatore di scope 62 * | 63 * +------ nome del namespace 64 * 65 */ 66 67 // ordino in vettore con shell sort 68 shell::sort( n, v ); 69 /* ^ ^ ^ 70 * | | | 71 * | | +--- nome della routine di ordinamento 72 * | | 73 * | --- :: operatore di scope 74 * | 75 * +------ nome del namespace 76 * 77 */ 78 79 // la potenza del namespace e' che il contenuto del 80 // namespace puo essere estratto tutto o in parte 81 82 using shell::sort ; 83 sort( n, v ); 84 85 using bubble::sort ; 86 sort( n, v ); // a questo punto vanno in conflitto 87 // il compilatore non sa quale dei due 88 // sort utilizzare 89 90 91 using namespace shell ; // con questo comando estraggo TUTTO il contenuto 92 // del namespace (in questo caso solo sort) 93 94}
File ex016.cc
1/* 2 * Cosa ha di diverso il C++ quasi a basso livello. 3 * 4 */ 5 6/* 7 * il namespace 8 * 9 * Il namesapce serve per evitare i conflitti di nomi. 10 * Ad esempio uno potrebbe usare due routione per l'ordinamento 11 * e chiamarla sort. Ma una implmenta in bubble sort e un'altra 12 * l'ordinamento shell sort. 13 * per evitare conlfitti invecie che moltiplicare i nomi 14 * si possono usare i namespace 15 * 16 */ 17 18#include <iostream> 19 20int 21main() { 22 // cout e' "dentro" in namespace std, per accederci devo usare 23 // l'operatore di scope :: 24 25 std::cout << "pippo\n" ; 26 27 using std::cout ; // estraggo l'oggetto cout 28 29 cout << "pluto\n" ; 30 31 int cout = 100 ; // int non si puo definire va in conflitto con cout 32}