Programmazione Mod A - Cap 2 - prof. Burattini CAPITOLO 2 Programmazione Mod A - Cap 2 - prof. Burattini
L’enunciato di assegnazione La forma sintattica di questo enunciato è la seguente: variabile = espressione In esecuzione il computer valuta l’espressione ed il suo valore è assegnato alla variabile (detta variabile di assegnazione). Il simbolo speciale = è detto operatore di assegnazione. stato del programma: l’insieme dei valori delle variabili del programma L’esecuzione di un enunciato di assegnazione provoca il cambiamento dello stato del programma. Si consideri la sequenza di istruzioni: n = 4; n = n+1; con la seconda istruzione il valore di n cambia da 4 a 5. Si osservi come l’occorrenza di n a sinistra di = si riferisce al suo indirizzo o left value mentre quella a destra di = si riferisce al suo contenuto o right value. Poiché un’assegnazione restituisce il risultato di un’espressione (il valore del calcolo eseguito a destra viene assegnato alla variabile che appare a sinistra) è necessario che il tipo della espressione sia compatibile con il tipo della variabile di assegnazione. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini REGOLA La variabile di assegnazione deve essere dello stesso tipo del valore dell’espressione Se però le variabili presenti nell’espressione sono tutte variabili numeriche è ammessa la conversione implicita dal tipo della espressione al tipo della variabile se quest’ultima è di tipo più generale. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Supponiamo che le variabili r1 e r2 siano state dichiarate di tipo float mentre n1 e n2 siano di tipo int e che non siano state ancora inizializzate. Vediamo come la successione di enunciati di assegnazione varia il loro valore . r1 r2 n1 n2 inizialmente ? n1 = 1 1 n2=3 3 n2 = n1*n2+1 4 r1 = 5.2 5.2 r2 = r1 + 2.2 7.4 r1 = n2*r1 20.8 r2 = 2 +n1 3.0 Nel penultimo caso c’è compatibilità perché nel calcolare il prodotto, n2 è trasformato in float; Nell’ultimo caso 2+n1, che è di tipo int viene trasformato in float per conversione implicita.. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini FUNZIONE MATEMATICA FUNZIONE C++ OSSERVAZIONI x≥0 e restituisce un valore ≥0 double sqrt (double x) ; radice quadrata di x sen x con x numero reale double sin (double x) ; seno di x cos x con x numero reale double cos (double x) ; coseno di x tg x con x numero reale double tan (double x) ; tangente di x arcsen x con x nell’intervallo [-1 ;+1] double asin (double x) ; arcoseno di x arccos x con x nell’intervallo [-1 ;+1] double acos (double x) ; arcocoseno do x arctg x con x numero reale double atan (double x) ; arcotangente di x con x numero reale double exp (double x) ; e elevato ad x double pow10 (double x) ; 10 elevato ad x ln x con x numero reale positivo double log (double x) ; logaritmo naturale di x Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini log x con x numero reale positivo v log10 (double x) ; logaritmo di base 10 di x con x numero reale double fabs (double x) ; valore assoluto di x Calcolo dell’ipotenusa di un triangolo rettangolo double hypot (double x, double y) ; Ipotenusa di un triangolo rettangolo i cui cateti hanno lunghezza x ed y double atan2 (double y, double x) ; Arcotangente di y/x. il valore restituito è compreso fra –pigreco e + pigreco estremi compresi con x , y numeri reali double pow (double x, double y) ; x elevato ad y Calcola mantissa ed esponente double frexp (double x, int* esp) ; Scompone il numero x nella mantissa e nell’esponente Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Tutte le funzioni in C++ restituiscono dei valori double invece che float; il tipo double rappresenta ancora un numero decimale ma con un maggior grado di precisione. Le due espressioni matematiche seguenti sono tradotte in C++ L’espressione si scrive con l’istruzione di assegnazione seguente: y = (a* pow(x,3) - 3*pow(x,5)) /(2*a*b) oppure y = (a* pow(x,3) - 3*pow(x,5)) /2/a/b z = sqrt(pow(x,4) – 3) /fabs(x-1) Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini ESERCIZI A- Tradurre in C++ le seguenti formule. Scrivere in C++ i seguenti programmi. 1) CALCOLO DEL PERIMETRO DI UN TRIANGOLO Calcolare il perimetro di un triangolo qualsiasi supponendo assegnati i tre lati a,b,c . 2) CALCOLO IPOTENUSA DI UN TRIANGOLO RETTANGOLO Calcolare l'ipotenusa di un triangolo rettangolo supponendo assegnati i due cateti b e c . (Ricordiamo che l’ipotenusa si esprime in C++ come hypot(b,c) : si deve includere anche il file <cmath>). 3) CALCOLO MEDIA E SOMMA DEI VALORI ASSOLUTI DEGLI SCARTI Inserire in ingresso tre numeri reali a, b, c e applicare le formule (M=Media, S=scarto medio: Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini 4) SOMMARE DUE NUMERI INTERI Dare in input i numeri interi a e b e far scrivere il risultato. Provare i valori a = 2 000000000 , b= 1 000000000 oppure a = b = 2 000000000. 5) STAMPARE I VALORI DI ALCUNE FUNZIONI Applicare a due numeri reali a e b le due funzioni logaritmo, la funzione esponenziale e la funzione arcotangente e far scrivere il risultato (porre attenzione ai valori da assegnare!). 6) Se n1 ed n2 sono variabili di tipo int , r una variabile di tipo float e c una variabile di tipo char dire cosa stampa il computer allorché esegue le seguenti istruzioni: n1= 11; n2=3 ; cout<<n1*n2; c=’H’; n2=n1%n2 ; cout<<c<<endl<<n2; r=n1/n2 ; n1=n1/n2; cout<<n1<<endl<<r; Scrivere un programma completo che esegua questa sequenza di istruzioni. Programmazione Mod A - Cap 2 - prof. Burattini
Operatori di incremento e decremento Tra gli operatori aritmetici forniti dal C++ ve ne sono alcuni che consentono di scrivere l’operazione in modo molto compatto. Consideriamo lo schema seguente Variabile = Variabile operazione Espressione che traduce esempi come i = i + 1 i = i – 1 somma = somma + i p = p * h questi possono essere scritti in modo compatto, rispettivamente, come i++ i-- somma += i p *= h In particolare i primi due termini i = i + 1 ed i = i – 1, sono detti rispettivamente operatori di incremento e decremento. Tali operatori hanno due forme: una forma postfissa (i++, i--) e la forma prefissa (++i , --i). Programmazione Mod A - Cap 2 - prof. Burattini
Le due forme non sono equivalenti. Il significato di i++ è “usa il valore di i e dopo incrementa la variabile i” mentre il significato di ++i è “incrementa la variabile i e dopo usa il valore di i”. Questa distinzione non è importante quando li utilizziamo singolarmente. La distinzione è particolarmente significativa quando gli operatori di incremento e decremento sono usati in espressioni che coinvolgono altri operatori. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Consideriamo l’espressione somma += i++ poiché la forma è postfissa, i passi che vengono eseguiti sono: si prende il valore di i e si calcola somma +=i, cioè somma = somma + i; si incrementa il valore di i. L’espressione somma += ++i scritta nella forma prefissa produce i seguenti risultati si incrementa il valore di i; Le stesse considerazioni valgono per l’operatore di decremento. Teniamo presente che gli operatori di incremento e decremento hanno la precedenza sugli altri operatori. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini ESERCIZIO a) k = 8 e i = ++k quanto valgono k ed i ? k = 8 e i = k++ quanto valgono k ed i ? eser2.0a Programmazione Mod A - Cap 2 - prof. Burattini
ISTRUZIONI DI CONTROLLO O SELEZIONE IF E IF……… ELSE Un’istruzione può essere semplice o composta. Le istruzioni di scrittura e lettura, le dichiarazioni di costanti e di variabili, l’enunciato di assegnazione sono istruzioni semplici. Una istruzione composta è una successione di istruzioni semplici racchiusa tra parentesi graffe. Un’istruzione di selezione consente di deviare il flusso dei comandi. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Il programma sul calcolo dell’area del cerchio è un flusso di istruzioni eseguite sequenzialmente; come dovremmo modificare il programma che calcola l’area del cerchio se qualcuno inserisse un raggio negativo? Potremmo dire qualcosa del genere SE raggio>0 ALLORA esegui i calcoli ALTRIMENTI Stampa(“il raggio non può essere negativo”) In C++ possiamo adoperare l’istruzione if …. else: //Calcola la circonferenza #include <iostream> #include <cstdlib> using namespace std; int main () { const float pi=3.1415; float circonf,raggio; cout << "Inserisci Raggio="; cin >> raggio; circonf=2*pi*raggio; cout << "circonferenza =" <<circonf<<endl; system("pause"); } if (espressione booleana) istruzione1 else istruzione2 altre istruzioni L’espressione booleana viene valutata: se risulta vera viene eseguita istruzione1; se invece risulta falsa viene eseguita istruzione2. In ogni caso, dopo aver eseguito la istruzione1 oppure la istruzione2, il programma esegue le “altre istruzioni”. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Esempio 1: Massimo tra due numeri a e b Se a è minore di b allora il massimo è b, altrimenti è a. Scrittura dell’algoritmo in C++: if (a<b) cout<<”MASSIMO=”<<b; else cout<<”MASSIMO=”<<a ; Supponiamo che a=15 e b=20; quando il computer esegue questa istruzione scriverà “Massimo=20”; se invece a=30 e b=10 scriverà “Massimo=30”. Una forma semplificata della istruzione if else è l’istruzione if: if (espressione booleana) istruzione altre istruzioni In questo caso se l’espressione booleana risulta vera allora l’istruzione viene eseguita, se invece risulta falsa non viene eseguita. In ogni caso successivamente saranno eseguite le “altre istruzioni”. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Esempio: Dati due numeri qualsiasi a, b risolvere l’equazione di primo grado: ax +b = 0. L’algoritmo: leggi(a,b) stampa(-b/a) non è corretto. Infatti il problema dice che a può essere un numero qualsiasi e, se a fosse zero, si avrebbe un errore a run time poiché la divisione non è definita quando il divisore è zero. In questo caso occorrerà dunque inviare un opportuno messaggio. Un algoritmo corretto è: { float x,a,b; cout<<’inserire i coefficienti di una equazione di primo grado’; cout<<”a(!0)= “; cin>>a; cout<”’b”=’; cin>>b if (a!=0) // parentesi graffa necessaria perché l’istruzione è composta { x= -b/a; cout<<”soluzione x =”<<x<<endl; } // fine istruzione composta relative alla condizione (a!=0) else cout<<”l’equazione non è risolvibile essendo a=0”; } leggi(a,b) if (a0) x -b/a stampa(x) else stampa(messaggio) //La condizione va posta tra parentesi tonde. Programmazione Mod A - Cap 2 - prof. Burattini eser2.1
Programmazione Mod A - Cap 2 - prof. Burattini Esempio: programma per il calcolo dell’area del cerchio che accetta solo input di numeri positivi. // Calcola Area del cerchio #include <iostream> #include <cstdlib> using namespace std; int main () { const float pi=3.1415; float area, raggio; cout << "Inserisci Raggio="; cin>>raggio; if (raggio>0) { area=raggio*raggio*pi; cout << "Area ="<<area <<endl; } else cout<< “Il raggio non può essere negativo “<<endl; system(“pause”); eser2.2 Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Vediamo cosa accade quando non conosciamo bene la matematica a=1 b=a b*a=a*a b*a - b*b = a*a - b*b b*(a – b) = a2 – b2 b*(a – b) =(a+b)*(a – b) b = (a+b) 1=2 assurdo Programmazione Mod A - Cap 2 - prof. Burattini
if (N>0); S = A + N; if (N>0) else ; S = A * N; ERRORI tipici su IF ……. ELSE ……… Se scriviamo if (N>0); S = A + N; l’istruzione S = A + N verrà eseguita in qualsiasi caso in quanto il simbolo ‘;’ chiude l’ if. Analogamente si ha nel caso seguente: if (N>0) else ; S = A * N; Un altro errore tipico è dato dalla mancanza dei delimitatori dell’istruzione composta, ‘{‘ e ‘}’; ad esempio: ERRATA CORRETTA if (N>0) S = A + N; Cout<<”è un’addizione”; else S = A * N; if (N>0) { S = A + N; Cout<<”è un’addizione”; } else S = A * N; Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini L’errore più comune è quello di confondere l’assegnazione con il confronto. Se scriviamo if (N=0) S = A + N; l’istruzione S = A + N verrà sempre eseguita perché il computer porrà il valore 0 nella variabile N. Ricordiamo che per eseguire il confronto tra due termini è necessario il simbolo ‘= =’. Per evitare questo errore si può scrivere prima l’espressione e poi la variabile (cosa non consentita con l’assegnazione): NON si può scrivere if (0=N) perché il computer segnala un errore, mentre è consentito scrivere if (0==N) Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini ESERCIZI 1) DETERMINARE SE UN NUMERO E' INTERO. Per risolvere il problema pensiamo di confrontare il numero letto con la sua parte intera: se i due valori sono uguali allora il numero e' intero, altrimenti non lo e'. (La parte intera si calcola con floor(N): si deve includere anche il file <cmath>); 2) DETERMINARE SE UN NUMERO INTERO E' PARI. Per risolvere il problema pensiamo di calcolare il resto modulo 2; se tale resto è zero allora il numero e' pari altrimenti non lo e'. Programmazione Mod A - Cap 2 - prof. Burattini
Le istruzioni cicliche o iterative: for e while Ciclo o iterazione: un gruppo di istruzioni che può essere ripetuto più volte. Supponiamo di avere a disposizione 10 raggi e di voler calcolare 10 circonferenze. L’algoritmo sarà allora: ripeti 10 volte: leggi(raggio) circonferenza 2* 3.1415*raggio stampa(circonferenza) In via del tutto generale l’utente dice al programma quante circonferenze deve calcolare come segue: leggi(n) ripeti n volte: Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Per codificare questo algoritmo si usa l’istruzione for Esempio in C++ //Calcola n volte la circonferenza di un cerchio #include <iostream> #include <cstdlib> using namespace std; int main () { const float pi=3.1415; float circonf, raggio; int n; cout<<”Dimmi quanti raggi hai: “; cin>>n; for (int i=1;i<=n;++i) { cout << endl<< “Inserisci il raggio: "; cin >> raggio; circonf=2*pi*raggio cout << "circonferenza ="<<circonf<<endl; } system("pause"); } Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Forma sintattica del ciclo for: for (inizializzazione;espressione booleana;espressione di incremento) istruzione altre istruzioni L’ istruzione che segue la parentesi destra ‘) ‘ può essere una istruzione semplice o composta e rappresenta il corpo del ciclo for. Nella inizializzazione, alla variabile del ciclo for si assegna un valore iniziale. Nel nostro caso la variabile di ciclo i viene contemporaneamente definita e inizializzata ad 1. L’ espressione booleana controlla il ciclo: solo se è vera il corpo del ciclo può essere eseguito, prende perciò il nome di condizione di ingresso al ciclo, la sua negata prende il nome di condizione di uscita. Nell’esempio la condizione di uscita è i>n. La terza componente espressione è usata per modificare il valore della variabile di ciclo. Nel nostro esempio semplicemente si incrementa i di 1. L’ordine di valutazione è il seguente: 1. inizializzazione della variabile di ciclo 2. si valuta l’espressione booleana e, se vera, si esegue espressione, cioè il corpo del ciclo, altrimenti il ciclo si interrompe e si passa alle “altre istruzioni”. 3. si valuta l’espressione di incremento, la variabile di ciclo si modifica, e si ripete il passo 2. for (int i=1;i<=n;++i) { …………… } Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Esempio. Assegnato un numero n compreso tra 1 e 10, stampare la tabellina relativa a un numero preassegnato. Per es. se n=4 deve stampare 4x1=4 4x2=8 4x3=12 ……………………………..4x10=40 L’algoritmo relativo diventa: leggi(numero) for (i1;i<=10;++i) stampa(numero*i) Il corrispondente codice C++ è dato da: cin>>numero for (int i=1;i<=10;i++) cout<<numero<<”x”<<i<<” =”<<numero*i; Si noti che la variabile i viene dichiarata all’interno dello stesso for. Il ciclo for può essere utilizzato solo se si conosce a priori quante volte il corpo del ciclo deve essere ripetuto. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Tornando al problema del calcolo della circonferenza si vuole consentire all’utente di calcolare un numero imprecisato cinconferenze fino a quando non si dà un raggio uguale a zero. Un possibile algoritmo è il seguente: leggi (raggio) finchè raggio<>0 ripeti: circonferenza 2* 3.14*raggio stampa(circonferenza) leggi(raggio) Qui sappiamo che il corpo del ciclo deve essere eseguito ogni volta che il numero letto è diverso da zero. In questi casi possiamo ricorrere al ciclo while. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini La traduzione dell’algoritmo in un programma C++ è: #include <iostream>; #include <cstdlib>; using namespace std; int main() { const float pi=3.1415; float circonf,raggio; int n; cout<<”Dammi il raggio: “; cin>>raggio; while (raggio != 0) circonf=2*pi*raggio; cout << “circonferenza =” <<circonf<<endl; } system("pause"); Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini La sintassi del while è molto semplice così come la sua semantica while (espressione booleana) istruzione finchè l’espressone booleana è vera ripeti istruzione. Il corpo del loop può essere un’istruzione semplice o composta. Supponiamo di dover ripetere un gruppo di istruzioni soltanto nel caso che a sia minore di b, con a e b numeri interi Scriveremo qualcosa del tipo: while (a<b) { (gruppo di istruzioni da ripetere) } Il gruppo di istruzioni all’interno del ciclo è il corpo del ciclo, l’espressione booleana (a<b) viene chiamata condizione di ingresso; la sua negata rappresenta la condizione di uscita dal ciclo. Una singola esecuzione della sequenza di istruzioni che formano il corpo del ciclo è detta passo del ciclo. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Siano a e b due numeri interi (tipo integer) i cui valori iniziali sono: a=5; b=10; (rappresentano le inizializzazioni delle variabili del ciclo necessarie per poter valutare l’espressione booleana; se fosse b=10 e a=12 il ciclo non verrebbe proprio eseguito). Quale sarà il valore di a che verrà stampato alla fine del ciclo? Dopo l’inizializzazione con a=5 e b=10 entriamo nel ciclo while perché la condizione (a<b) è vera; al primo passo otteniamo a=6 e b=9 in quanto a è incrementato di 1 e b è decrementato di 1. Si ritorna alla condizione di controllo del ciclo, (a<b), e poiché 6<9, si esegue un altro ciclo, all’uscita del quale a=7 e b=8. Si ritorna ancora al controllo (a <b), si verifica che, essendo 7<8, si deve eseguire ancora il corpo del ciclo; dopo questo terzo passaggio la condizione (a <b) è falsa per cui si salta il ciclo e si esegue l’istruzione subito dopo, cout<<”a =”<<a<<endl, per cui il computer scriverà sul video a=8 a=5; b=10; while (a<b) { a++; b--; } cout<<”a=”<<a<<endl; passo a b inizio 5 10 N. 1 6 9 N. 2 7 8 N. 3 8 7 eser2.3 Programmazione Mod A - Cap 2 - prof. Burattini
somma=somma+contatore; o anche somma+=contatore; Esempio. Assegnato un numero intero N, sommare tutti gli interi compresi tra 1 ed N. Se N=4 allora la somma è 1+2+3+4=10. Analizziamo il problema: abbiamo bisogno di una variabile contatore che contenga volta per volta i valori 1, 2, 3, ……., N e di una variabile somma che contenga le somme parziali; cioè contatore=1 somma = 1 contatore=2 somma = (1) + 2 contatore=3 somma = (1+2) + 3 contatore=4 somma = (1+2+3) + 4 e così via I valori che abbiamo posto tra parentesi rappresentano la somma ottenuta al passo precedente; questa situazione può essere descritta con la formula somma=somma+contatore; o anche somma+=contatore; La condizione di ingresso può essere espressa con (contatore<=N). Dobbiamo solo controllare cosa accade quando si entra la prima volta nel ciclo; all’ingresso del ciclo il contatore è inizializzato ad 1 e la somma a zero. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini ALGORITMO 1 – SOMMA DEI PRIMI N INTERI inizializza contatore a 1 e somma a 0 while contatore <= N ripeti: incrementa il valore della variabile somma con il contenuto di contatore incrementa il contatore di 1 Altra possibilità è di inzializzare sia contatore che somma a zero; in tal caso l’algoritmo si modifica come segue: ALGORITMO 2 – SOMMA DEI PRIMI N INTERI inizializza contatore e somma a 0 while contatore < N ripeti incrementa il contatore di 1 incrementa il valore della variabile somma con il contenuto di contatore Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Programma in C++ #include <iostream> #include <cstdlib> using namespace std; // calcola la somma dei primi N numeri int main () { int somma, contatore, N; cout << “Calcola la somma dei primi N numeri”<<endl; cout << “Inserisci N=”; cin >> N; contatore=0; somma=0; while (contatore<N) contatore++; somma+=contatore } cout << "Somma =" << somma <<endl; system("pause"); Programmazione Mod A - Cap 2 - prof. Burattini eser2.4
Programmazione Mod A - Cap 2 - prof. Burattini Karl Friedrich Gauss, nato nel 1777 a Brunswick in Germania, ad appena 10 anni, quando un suo insegnante di matematica, per levarselo dai piedi, gli impose di fare la somma dei numeri interi da 1 a 100, dopo pochi minuti gli diede la soluzione ragionando come segue. 1 2 3 4 5 6 7 8 9 10 + 1 2 3 4 5 10 9 8 7 6 11 11 11 11 11 =11*10/2=55 + (n+1)*n/2 1 2 3 4 5 6 7 1 2 3 7 6 5 4 7 7 7 7 =8*7/2=28 (n+1)*n/2 + Programmazione Mod A - Cap 2 - prof. Burattini
ALGORITMO PER IL MASSIMO COMUN DIVISORE Si trovi il MCD tra i numeri 93217 e 1843 Si cercano i fattori primi del primo numero Si cercano i fattori primi del secondo numero Si cercano i fattori primi comuni a entrambi i numeri Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Ricerca Fattori Primi 93217=31 x 31 x 97 Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Ricerca Fattori Primi 1843=19 x 97 Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Massimo Comune Divisore Fattori Primi di 93217 = 31*31*97 Fattori Primi di 1843 = 19*97 Il MCD tra 93217 e 1843 è 97 Numero di passi totale = 27+26 = 53 Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini ALGORITMO DI EUCLIDE N R R R’ R’ R’ MCD= Programmazione Mod A - Cap 2 - prof. Burattini
(300 A.C.) Siano m ed n due numeri naturali e supponiamo sia m>n ALGORITMO DI EUCLIDE PER IL MASSIMO COMUN DIVISORE (300 A.C.) Siano m ed n due numeri naturali e supponiamo sia m>n 1 Si divide m per n 2 Se il resto è zero allora n è il MCD tra m e n. 3 Se il resto è diverso da zero torna al primo passo scambiando m con n e n con r (cioè dividi n per r) Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini ESEMPIO MCD tra 93217 e 1843 97 Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Analizziamo il Massimo Comun Divisore tra due interi con l’algoritmo di Euclide. Riscriviamo l’algoritmo in pseudo-codice. INPUT a,b Finché il resto della divisione tra a e b è diverso da ZERO esegui le istruzioni: Calcola il resto dei due numeri interi a e b Poni b in a (poni il divisore nel dividendo) Poni il resto della divisione in b Quando il resto è ZERO allora il MCD è il numero intero contenuto in b Scrivi il MCD b Notiamo che, poiché il ciclo termina quando il resto della divisione è zero, non è perfettamente determinato il numero di passi da eseguire: in tal caso non è possibile utilizzare il ciclo for ma è necessario servirsi del while. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Il programma in C++ è dato da: #include <iostream> #include <cstdlib> using namespace std; main () { int a,b,r; cout << “Calcolo del M C D”<<endl; cout << “Assegnare a e b :”; cin >> a>>b; r=a % b; cout<<”MCD di “<<a<<” e “<<b<<” = “; while (r>0) a=b; b=r; r= a % b; } cout << b <<endl; system(“pause”); Programmazione Mod A - Cap 2 - prof. Burattini eser2.5
Programmazione Mod A - Cap 2 - prof. Burattini ESERCIZI 1- Tenendo presente il programma che calcola la somma dei primi N numeri interi scrivere un programma che determini: la somma di tutti i numeri pari e la somma di tutti i numeri dispari inclusi tra 1 ed N; la differenza tra i due valori ottenuti la somma di tutti gli inversi tra 1 ed N, cioè: 1 + 1/2+1/3 +…+1/n 2- Dato il programma che calcola il Massimo Comun Divisore: verificare cosa accade se i valori immessi sono entrambi negativi, uno negativo e l’altro positivo, uno positivo ed uno nullo. Apportare al programma le modifiche necessarie affinché dia sempre risposte coerenti. Programmazione Mod A - Cap 2 - prof. Burattini
Conversione di tipo (casting implicito). Durante l’esecuzione di un programma esistono delle situazioni in cui viene cambiato il tipo di dato: quando un valore di un tipo viene assegnato alla variabile di un altro; quando un’operazione contiene due elementi di tipo diverso (per esempio la somma di un intero con un reale); Questo fatto può provocare degli errori difficilmente individuabili. Ad esempio: variabile= espressione Il compilatore forza il tipo del valore dell’espressione in modo da fargli assumere il tipo della variabile che appare a sinistra. Se il tipo dell’espressione ha una precisione minore del tipo della variabile, come in Variabile-double = espressione-float allora non c’è alcun problema; se, invece, accade il contrario, come in Variabile-float = espressione-double potrebbero nascere due tipi di problemi: 1 - il risultato dell’espressione-double contiene un numero di cifre che il tipo float non gestisce, con una grave perdita di precisione; 2 - il risultato dell’espressione-double supera il massimo valore rappresentabile come float: in tal caso non è prevedibile in generale il comportamento del programma. Programmazione Mod A - Cap 2 - prof. Burattini
x1 = static_cast <T1>(x2) Casting esplicito Nel caso di operazioni tra tipi differenti, la prima regola generale è che tutti i tipi che sono immagazzinati con pochi byte, sono “promossi” al tipo più ampio che appare nell’espressione. Le altre regole sono piuttosto complicate ma, comunque, possono essere superate con il casting esplicito. Supponiamo di avere due variabili di tipo T1 e T2: T1 x1; // x1 è di tipo T1 T2 x2; // x2 è di tipo T2 possiamo convertire la variabile x2 al tipo T1 scrivendo x1 = (T1) x2 o x1 = T1 (x2) Tale notazione, presa totalmente dal linguaggio C, è detta conversione esplicita o casting esplicito, in quanto si “costringe” la variabile a cambiare tipo. La conversione esplicita è comunque un operatore: è come se applicassimo l’operatore (T1) alla variabile x2. Essa è soggetta alle regole di precedenza degli operatori. Nel C++ si consiglia, per la conversione esplicita, di usare l’operatore di conversione static_cast mediante la notazione x1 = static_cast <T1>(x2) Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Esempio A titolo esemplificativo stampiamo i caratteri ASCII visibili (compresi tra 32 e 127) int i=32; while (i<=127) { cout<< (char) i << “ ha codice “<< i<<endl; i++; } dove notiamo che l’intero i viene convertito in modo esplicito a carattere. eser casting Programmazione Mod A - Cap 2 - prof. Burattini
Array monodimensionali Supponiamo di voler scrivere un programma che, ricevuto in input un intero n ed n interi positivi, li stampi in ordine inverso. Ci troviamo di fronte al problema di non sapere a priori quante variabili dobbiamo definire. Un modo di aggirare questo problema consiste nel dichiarare un numero m di variabli x1,x2,…xm con m sufficientemente grande. Il seguente algoritmo allora, risolve il problema per ogni n<=m: leggi(n) conta=0 if conta<n leggi(x1) else x1=0 conta=conta+1 if conta<n leggi(x2)else x2=0 … conta=conta +1 if conta<n leggi(xm) else xm=0 if xm<>0 stampa(xm) if x1<>0 stampa(x1) Per risolvere un problema molto semplice occorrerebbe scrivere un programma lunghissimo anche nel caso che n fosse dell’ordine delle centinaia. Programmazione Mod A - Cap 2 - prof. Burattini
Tipo-componente identificatore[espressione ] Quando si devono manipolare molti elementi dello stesso tipo, tutti i linguaggi imperativi permettono l’uso della struttura dati array. Un array è un insieme ordinato di elementi dello stesso tipo. Gli elementi di un array sono detti componenti ed il loro tipo è chiamato componente-tipo dell’array. Essi sono immagazzinati in posizioni consecutive di memoria. Nel caso di array monodimensionali la dichiarazione di una variabile di tipo array è la seguente: Tipo-componente identificatore[espressione ] Dove Tipo-componente è il tipo dei componenti, identificatore è il nome dell’array e il valore dell’espressione racchiusa tra parentesi quadre ne rappresenta la dimensione cioè il numero massimo di componenti che può essere contenuto in un array. Un array (o vettore) può anche essere inizializzato, nel qual caso la dimensione può essere calcolata implicitamente dal compilatore. Si noti che la dimensione dell’array deve essere calcolata durante la fase di compilazione e pertanto in espressione possono essere presenti solo valori letterali o costanti. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini ESEMPI float b[]={1.5,0.4,15}; dove b è un array di dimensione 3 contenente i 3 numeri reali racchiusi tra parentesi tonde; la dimensione del vettore b è calcolata implicitamente durante la inizializzazione e b[0], b[1] e b[2] sono tre variabili reali, il loro indirizzo (left value) è dato dalla somma dell’indirizzo corrispondente alla variabile b che identifica l’array, sommato all’indice posto tra parentesi quadre; i loro valori (right value) sono rispettivamente 1.5, 0.4 e 15.0. const int max=30; int Vet[10], vet[max]; Vet è un array che può contenere al massimo 10 interi, vet al massimo 30 interi float a[12]; a è un array composto al massimo da 12 numeri reali. Per poter accedere ai vari elementi dell’array si adopera l’operatore di subscript []. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Gli array dell’esempio sono detti monodimensionali perché un solo operatore di subscript, (un solo indice) permette di individuare i suoi componenti. Supponiamo che ad un certo istante durante l’esecuzione di un programma il vettore Vet dell’esempio contenga esattamente i 10 elementi sotto rappresentati: Vet In generale con Vet[espressione] si accede all’elemento del vettore il cui indice è il valore dell’espressione. Pertanto il contenuto di Vet [2] è 8, quello di Vet [6] è 12, mentre se il contenuto di i è 4 allora il contenuto di Vet [i* 2] è 0, quello di Vet [i + 1] è 15. In generale dunque se la variabile A è stata definita come un array, A[espressione] è a tutti gli effetti una variabile il cui tipo è quello dei componenti dell’array. Se il valore dell’espressione è maggiore o uguale alla dimensione dell’array si ha un errore logico. 0 1 2 3 4 5 6 7 8 9 4 -2 8 5 -6 15 12 -4 0 23 Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini L’istruzione Vet[10]=2 non ha senso poiché si attribuisce un valore ad una variabile che non rappresenta una componente dell’array Vet. Lo stesso può accadere se l’espressione risulta maggiore o uguale al numero di elementi effettivamente presenti nell’array. E’ pertanto compito del programmatore assicurarsi che situazioni di questo genere non si verifichino perché esse possono dar luogo ad errori difficilmente rintracciabili. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini //Esempio riempimento e stampa inversa di un array #include <iostream> #include <cstdlib> using namespace std; int main () { int const m=300; int a[m],i, n; cout<<"Quanti elementi? "; cin>>n; cout<<"Dammi "<<n<<" elementi di seguito separati da uno spazio "<<endl; for (i=0;i<n;i++) cin>>a[i]; cout<<"Lista inversa "<<endl; for (i=n-1; i>=0;i--) cout<<a[i]<<endl; } eser2.6 Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Si osservi inoltre che se A e B sono due array è errato scrivere A=B. Per copiare un array in un altro occorre scrivere un for che copi ogni elemento di B in A. Cioè: for(int i=1;i<n;i++) A[I]=B[I]; Una variabile di tipo array non può comparire da sola in un enunciato di assegnazione o in una espressione booleana. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini ESERCIZI Assegnato un vettore a di n interi, verificare che tutti i suoi elementi sono positivi. Assegnato un vettore a di n interi, verificare che tutti i suoi elementi sono nulli Scrivere un programma che scriva tutti i numeri interi multipli di 3 e non di 7 inclusi tra 15 e 100. Utilizzare il ciclo while Scrivere un programma che calcoli la somma di tutti i numeri interi pari inclusi tra 5 e 100 escludendo i multipli di 3 e 5. Scrivere un programma che esegua la somma di tutti i numeri interi inseriti da tastiera finché tale somma non superi il valore di 150; dalla somma vanno esclusi i numeri che contengono la cifra 1. Scrivere un programma che esegua il prodotto di tutti i numeri interi inseriti da tastiera finché tale prodotto non superi il valore di 15000; dal prodotto vanno esclusi i numeri che sono multipli di 3. eser2.7b Programmazione Mod A - Cap 2 - prof. Burattini
Array di caratteri e stringhe Il tipo char ha dimensione di un byte e contiene il numero di codice ASCII che gli corrisponde. Un letterale di tipo carattere deve essere sempre racchiuso tra virgolette semplici, ad esempio: ‘a’. Oltre agli array di numeri interi o reali, possiamo definire anche gli array di caratteri; per esempio char s[]={‘c’, ‘i’, ‘a’, ‘o’} dove s è un array di caratteri formato da 4 elementi s[0]=’c’; s[1]=’i’; s[2]=’a’; s[3]=’o’ Una stringa è un insieme di caratteri. Anche un array può essere visto come una stringa, purché all’array di caratteri venga aggiunto il carattere nullo ‘\0’, cioè l’elemento che ha codice ASCII uguale a 0. Quindi, char s[]={‘c’, ‘i’, ‘a’, ‘o’, ‘\0’} per cui s è un array di caratteri costituito da 5 elementi. Per gestire un array di caratteri come stringa non è necessario conoscere a priori la sua lunghezza in quanto è sufficiente scandire la stringa fino al simbolo ‘\0’. Programmazione Mod A - Cap 2 - prof. Burattini
In questo modo si crea una stringa di 5 caratteri È possibile inizializzare una stringa anche in un altro modo. Scrivendo char s[]=”ciao”; In questo modo si crea una stringa di 5 caratteri s[0]=’c’; s[1]=’i’; s[2]=’a’; s[3]=’o’; s[4]=’\0’; che viene vista come un array di caratteri il cui ultimo elemento è ’\0’. Se poniamo Str=”Nel mezzo del cammin”’, essa è una stringa lunga 20 caratteri, dove Str[0] contiene il carattere ‘N’, Str[1] il carattere ‘e’, ……, Str[19] il carattere ‘n’, Str[20] contiene il carattere nullo ‘\0’ per cui la variabile Str dovrà essere dichiarata come un array di 21 caratteri char Str[21]=”Nel mezzo del cammin”’. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Usando cin per la gestione dell’input, abbiamo che la lettura di ciascuna variabile termina quando incontra o il carattere spazio (la barra spaziatrice) o la tabulazione (tasto Tab) o il fine linea (tasto Invio). Quindi non è possibile digitare una frase completa come stringa perché quando incontra uno spazio il computer non accetta altri caratteri. Per ovviare a questo inconveniente esiste l’istruzione cin.getline(s, n) dove s è una variabile stringa ed n è un numero intero che rappresenta il numero massimo di caratteri che possono essere letti; in tal caso s può contenere anche spazi in quanto l’input termina solo digitando il tasto Invio. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini ESEMPIO Scrivere un programma che, dato un nome in input, costruisca una stringa contenente il testo ciao, nome Esempio: se l’utente digita il nome Antonio, il programma deve restituire la stringa str contenente il testo ciao, Antonio I passi da seguire sono i seguenti: Poni la scritta “ciao,” nella variabile str; Leggi(nome); Aggiungi tutti i carattere del nome Alla fine aggiungi il carattere nullo Stampa la stringa str; Ci serviamo di un indice j che scorre tutti i caratteri della stringa nome assegnata in input finché non raggiunge il carattere nullo; ognuno di questi caratteri deve essere aggiunto alla stringa str dopo “ciao,”, cioè dall’indice 5 in poi. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini #include <iostream> #include <cstdlib> using namespace std; int main() { char nome[20]; char str[30]="ciao,";// str contiene 5 caratteri + ‘\0’ int j=0; cout<<"nome: "; cin>>nome; while (nome[j]!='\0') // finché la stringa non termina str[j+5]=nome[j++];// aggiungi il carattere dalla quinta posizione str[j+5]='\0'; // aggiungi il carattere di fine stringa cout<<str<<endl; system("pause"); } eser2.8 Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini ESERCIZI Assegnata una stringa s, scrivere un programma che conteggi i caratteri ‘a’ in essa contenuti. Assegnata una stringa s, ed un intero n minore della lunghezza della stringa, scrivere un programma che stampi tutti i caratteri compresi tra n e la lunghezza della stringa. Assegnata una stringa s, e due interi m<n minori della lunghezza della stringa, scrivere un programma che stampi la sottostringa che va da m ad n. Esempio: s=’ciao mamma’ ed m=3, n=4 il programma deve stampare la stringa ao ma Scrivere un programma che, assegnata in input una stringa s del tipo aaa@bbb stampi su video nome: aaa indirizzo: bbb eser2.81 eser2.82 Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini /*QUESTO PROGRAMMA ESEGUE LA SOMMA DEI NUMERI PARI E DISPARI CON DIVERSI ALGORITMI*/ #include <iostream> #include <cstdlib> #include <math.h> using namespace std; int main () { double N,Q; double Sp,Sd,pari=0,dispari=0,contatore=0,j=0; cout<<" DAMMI IL NUMERO N "; cin>>N; cout<<" La somma totale dei numeri vale "<<(N+1)*(N)/2<<endl; Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini // PROCESSO LENTO cout<<" PROCESSO LENTO "<<endl; for (int i=0; i<=N; i+=2) { contatore+=i; } cout<<" Dato il numero "<<N<<endl; cout<<" La somma dei numeri pari da 1 a "<<N<<" vale "<<contatore<<endl; for (int i=1; i<=N; i+=2) j+=i; cout<<" La somma dei numeri dispari da 1 a "<<N<<" vale "<<j<<endl; cout<<" Somma totale= "<<contatore+j<<endl; system("pause"); Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini // PROCESSO MEDIO cout<<" PROCESSO MEDIO "<<endl; for (int i=1; i<=N; ++i) { if (i%2==0) { pari+=i; } else { dispari+=i; cout<<" Dato il numero "<<N<<endl; cout<<" La somma dei numeri pari da 1 a "<<N<<" vale "<<pari<<endl; cout<<" La somma dei numeri dispari da 1 a "<<N<<" vale "<<dispari<<endl; cout<<" Somma totale= "<<pari+dispari<<endl; system("pause"); Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Numero pari Np= N *(N+4) Numero dispari Np= N2-1 4 4 Nd= N *(N-2) Nd= (N+1)2 4 4 Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini // PROCESSO VELOCE cout<<" PROCESSO VELOCE "<<endl; Q=floor(N/2); if (N==2*Q) { Sp=(N)*(N+4)/4; Sd=(N)*(N-2)/4; } else {Sp=(N*N)/4; Sd=(N+1)*(N+1)/4; cout<<" Dato il numero "<<N<<endl; cout<<" La somma dei numeri pari da 1 a "<<N<<" vale "<<Sp<<endl; cout<<" La somma dei numeri dispari da 1 a "<<N<<" vale "<<Sd<<endl; cout<<" Somma totale= "<<Sp+Sd<<endl; system("pause"); Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Tipi enumerativi Introduciamo un nuovo tipo detto tipo enumerativo. Esso viene introdotto con la parola chiave enum secondo lo schema seguente: enum Nome-Tipo { lista dei valori accettabili } Esempi: enum giorno {lunedi, martedi, mercoledi, giovedi,venerdi,sabato,domenica} enum risposta {si, no, nonso} I due tipi nuovi, giorno e risposta, possono essere utilizzati nella dichiarazione delle variabili: giorno oggi, domani; risposta ris; Programmazione Mod A - Cap 2 - prof. Burattini
Il tipo enumerativo è caratterizzato da tre aspetti essenziali: 1 - è un tipo definito dal programmatore che può essere utilizzato nella dichiarazione di una variabile; 2 – la lista dei valori accettabili è un insieme di identificatori: tali identificatori rappresentano i soli valori che le variabili di quel tipo possono assumere; non è possibile assegnare alle variabili di quel tipo altri valori diversi da quelli prescritti: domani=riposo; // l’identificatore riposo non essendo nella lista è errato, domani=ris; // è un’uguaglianza tra due tipi diversi e quindi è errato 3 – è un tipo ordinale nel senso che si può parlare di un precedente (tranne il primo) e di un successivo (tranne l’ultimo); 4 – all’interno della macchina il dato viene trattato come un intero. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Il C++ associa ad ogni identificatore definito nella lista un numero intero che parte da zero; perciò, lunedì corrisponde a 0, martedì ad 1, e così via (non sono accettate le vocali accentate). Ha sicuramente senso scrivere oggi <= domani il compilatore interpreterà il risultato sostituendo i rispettivi valori alle variabili e restituirà un valore vero o falso. Supponiamo invece di scrivere domani < = ris In fase di compilazione il compilatore dovrebbe dare un errore. Invece, il migliore dei compilatori fornisce un errore di avvertimento (warning)! Programmazione Mod A - Cap 2 - prof. Burattini
for (oggi=lunedì; oggi <= domenica; oggi++) { …….istruzioni….. } Consideriamo ancora la possibilità di utilizzare un costrutto iterativo per evidenziare tutti i giorni della settimana: for (oggi=lunedì; oggi <= domenica; oggi++) { …….istruzioni….. } il compilatore evidenzia un errore! Infatti, poiché oggi ++ è equivalente a oggi = oggi+1 il compilatore forza il valore oggi a destra dell’uguaglianza a diventare un intero, per poi assegnare alla variabile oggi (che appare alla sinistra) ancora un intero; in questo modo la variabile oggi perde il suo significato iniziale per diventare un intero. Si può ovviare a questo inconveniente forzando con un casting al tipo giorno il risultato. for (oggi=lunedì; oggi <= domenica; oggi=giorno(oggi+1)) il valore di oggi+1 è forzato ad assumere un valore di tipo giorno. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini ESEMPIO #include <iostream> #include <stdlib.h> using namespace std; int main() { enum giorno {lunedi=1, martedi, mercoledi, giovedi, venerdi, sabato, domenica}; giorno oggi; cout<<"Giorni della settimana"<<endl; for (oggi=lunedi; oggi<=domenica; oggi=giorno(oggi+1)) { cout<<oggi<<" "; if (oggi<=venerdi) cout<<" giorno lavorativo"<<endl; else if (oggi==sabato) cout<<" giorno semifestivo"<<endl; else cout<<" giorno festivo"<<endl; } system("pause"); eser2.9 Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Esercizio. Assegnata una stringa s contenente anche delle cifre, sommare tutte le cifre e fornire il valore totale di tale somma. Esempio, : s=”abc3x casa2 y34zq” il programma deve restituire 3+2+3+4=12. Pseudo codice: assegnare la stringa s; scandire ogni carattere c delle stringa finché non termina; (while) verificare se è compreso tra 0 e 9 se lo è incrementare la somma con il valore corrispondente della cifra; passare al carattere successivo; stampare la somma totale. Nel ciclo while dobbiamo specificare inizializzazione: contatore di ciclo inizializzato a zero, i = 0, e somma = 0; condizione di uscita: l’ultimo carattere letto è la sequenza di escape \0 c == ‘\0’; la condizione di esecuzione del ciclo è la sua negazione, c != ‘\0’; corpo del ciclo: se il carattere è una cifra aggiungerla a somma; incrementare in ogni caso il contatore i; Osserviamo che l’istruzione (int) c effettua un casting esplicito da carattere a numero: ciò che si ottiene è il codice ASCII di c; se sottraiamo tale valore al codice ASCII del carattere che rappresenta lo zero, otteniamo proprio il valore numerico della cifra. In altre parole, (int) ‘3’ – (int) ‘0’ restituisce l’intero 3, mentre (int) c – (int) ‘0’ restituisce l’intero rappresentato dal carattere c, se c è compreso tra 0 e 9. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini #include <iostream> #include <cstdlib> using namespace std; int main() { char s[100]; int i, somma; cout<<"Stringa="; cin.get(s,100); i=0; somma=0; while (s[i]!= '\0') if ((s[i]>='0') && (s[i]<='9')) somma+=(int)s[i]-(int)'0'; i++; } cout<<"somma="<<somma<<endl; system("pause"); eser2.10 Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Esercizio Assegnata una stringa s contenente anche delle cifre, sommare tutte le cifre e fornire il valore totale di tale somma. Trasformare le cifre in un numero e sommarlo al valore precedente Se, per esempio, : s="abc3x casa2 y34zq" il programma deve restituire somma=3+2+3+4=12 numero=3234+12=3246. */ eser2.10bis Programmazione Mod A - Cap 2 - prof. Burattini
typedef unsigned int Uint; typedef long double reale; L’istruzione typedef serve a dare un nuovo nome ad un tipo già esistente. Per esempio typedef unsigned int Uint; crea il tipo Uint che corrisponde all’intero senza segno, mentre la definizione typedef int Integer; crea un altro tipo con le stesse caratteristiche del tipo int. La ragione più importante per cui si utilizza typedef è la portabilità del software: può accadere che una macchina utilizzi in modo particolare le variabili reali, per cui i tipi float, double e long double sono gestiti in modalità diversa dallo standard. In tal caso è sufficiente definire con typedef nuovi tipi di reali in corrispondenza alle esigenze. Per esempio, supponiamo di dover eseguire dei calcoli su due diverse macchine; sulla prima è implementata la versione standard del tipo double, mentre sulla seconda macchina, supportando un tipo double che non ci soddisfa, riteniamo necessario utilizzare il tipo long double. Per scrivere un solo programma per le due macchine definiamo un tipo reale con typedef double reale; che utilizzeremo nelle dichiarazioni del programma. Per rendere funzionale il programma anche sulla seconda macchina è sufficiente cambiare soltanto la definizione di typedef typedef long double reale; Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Debug con Dev-Cpp Il debug del compilatore ci aiuta a seguire passo-passo una variabile per esaminarne il valore. Analizziamo passo-passo il programma che calcola la somma dei primi N numeri, descritto precedentemente servendoci del debug gdb inserito nel compilatore. Per assicurarci che il debugger gdb sia attivo andiamo su strumenti→Opzioni di compilazione→ Generazioni di codice/ Ottimizzazione →Linker→Genera le informazioni di debug, scegliamo yes e compiliamo il programma per assicurarci che vada tutto bene (il file exe ottenuto è almeno raddoppiato in ampiezza). Clicchiamo col mouse alla sinistra del while (il rigo cambierà colore): ciò sta ad indicare che in quel punto il programma si fermerà per consentirci di eseguirlo passo-passo; Clicchiamo sulla icona Debug (in basso); apparirà la situazione in figura. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Il programma è in esecuzione e noi vogliamo analizzare il valore delle due variabili i e Somma che variano durante il calcolo; clicchiamo su Nuova Osservazione ed inseriamo la variabile i alla richiesta Stampa Nome Variabile; vedremo apparire il suo valore nella finestra di sinistra (dove avremo scelto ancora la modalità di Debug). Ripetiamo la stessa operazione con la variabile somma; anche somma andrà nella stessa finestra. Premendo più volte il tasto Step Succ possiamo vedere passo-passo sia le istruzioni eseguite (in genere di colore blu) che i valori assunti dalle variabili. Per poter rintracciare gli errori (i bug) nei programmi è fondamentale appropriarsi di questa metodologia; il consiglio è di utilizzare inizialmente il debug anche quando i programmi funzionano verificando che le variabili assumano i valori che ci aspettiamo. Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini Esercizi. Calcolare il prodotto dei primi N interi. Viene spontaneo sostituire il simbolo del prodotto al posto di quello della somma. Se provate a farlo otterrete uno strano risultato: utilizzate il debug (o, ancora meglio, ragionateci sopra). Quali modifiche devono essere apportate nel programma per eseguire la somma di tutti gli interi inclusi tra due numeri N1 ed N2 prefissati (con N1< N2) ? Programmazione Mod A - Cap 2 - prof. Burattini
Programmazione Mod A - Cap 2 - prof. Burattini /*QUESTO PROGRAMMA INSERITO DA TASTIERA UN NUMERO INTERO IN BASE 10 LO TRASFORMA IN BASE 2 (BINARIO) e poi in base 10*/ #include <iostream> #include <cstdlib> #include <cmath> using namespace std; int main () { int A,B,i=0; int const N=16; float R[N],bas=2; float decimale; cout<<endl<<"Inserire il numero in base 10 da trasformare in base 2."<<endl<<endl; cin>>A; cout<<endl; cout<<"Il numero in binario e' "<<endl; for (int j=0;j<=(N-1);j++) R[j]=0; // Ciclo WHILE per il calcolo e la stampa delle cifre del binario. while (A>0) { B=(A%2); A=(A/2); ++i; R[N-i]=B; } for (int j=1;j<=(N-1);j++) cout<<R[j]; cout<<" "<<endl; cout<<"Il numero in decimale e' "<<endl; decimale=0; for (int j=0;j<=(N-1);j++) { decimale+=(R[N-j-1]*pow(bas,j)); } cout<<decimale<<endl; system("pause"); Programmazione Mod A - Cap 2 - prof. Burattini