Corso di Ingegneria Clinica BCLR Domenico Daniele Bloisi
Docente Ing. Domenico Daniele Bloisi, PhD Ricercatore Dipartimento di Ingegneria Informatica, Automatica e Gestionale Antonio Ruberti Via Ariosto 25 (adiacente Piazza Dante, Manzoni Tram 3 fermata via Labicana) email: bloisi@dis.uniroma1.it home page: http://www.dis.uniroma1.it/~bloisi Pagina 2
Ricevimento In aula, subito dopo le lezioni Su appuntamento (tramite invio di una email) presso: Dipartimento di Ingegneria Informatica, Automatica e Gestionale Antonio Ruberti, via Ariosto 25 - II piano, stanza A209 Si invitano gli studenti a controllare regolarmente la bacheca degli avvisi http://www.dis.uniroma1.it/~bloisi/didattica/labinf1415.html#avvisi Pagina 3
Orari Lunedì 12.00 13.30 Aula 4, via del Castro Laurenziano 7A Martedì 14.00 17.15 Aula 15, Laboratorio Didattico via Tiburtina 205 Mercoledì 12.00 13.30 Aula 4, via via del Castro Laurenziano 7A Pagina 4
Sommario Operatori di uguaglianza e relazionali Calcolo booleano Istruzione if-else e istruzione if Condizioni ed espressioni booleane Blocco di istruzioni if annidati Espressione condizionale Istruzione switch Pagina 5
Istruzione if Dati mese e anno correnti, calcolare mese e anno del mese successivo. #include <stdio.h> int main() { int mese, anno, mese_s, anno_s; printf(" Mese: "); scanf("%d", &mese); printf(" Anno: "); scanf("%d", &anno); if (mese == 12){ mese_s = 1; anno_s = anno+1; else { mese_s = mese+1; anno_s = anno; printf("\n Mese: %d, \n Anno %d",mese_s, anno_s); return 0; Pagina 6
if annidati Si hanno quando l istruzione del ramo-then o del ramo-else è un istruzione if-else o if. int giorno, mese, anno, giornosucc, mesesucc, annosucc;... if (mese == 12) { if (giorno == 31) { else {... giornosucc = 1; mesesucc = 1; annosucc = anno + 1; else { giornosucc = giorno + 1; mesesucc = mese; annosucc = anno; Dati giorno, mese e anno correnti, calcolare giorno, mese e anno del mese successivo. Pagina 7
if annidati con condizioni mutuamente esclusive Un caso comune di utilizzo degli if annidati è quello in cui le condizioni degli if annidati si escludono mutuamente. Esempio In base al valore della temperatura (intero), stampare un messaggio secondo la seguente tabella: Pagina 8
Soluzione A #include <stdio.h> int main() { int temp; printf("temperatura: "); scanf("%d", &temp); if (temp > 30) printf("molto caldo\n"); if (temp > 20 && temp <=30) printf("caldo\n"); if (temp > 10 && temp <=20) printf("gradevole\n"); if (temp <= 10 ) printf("freddo\n"); return 0; Pagina 9
Soluzione B if annidati #include <stdio.h> int main() { int temp; printf("temperatura: "); scanf("%d", &temp); if (temp > 30) printf("molto caldo\n"); else if (temp > 20) printf("caldo\n"); else if (temp > 10) printf("gradevole\n"); else printf("freddo\n"); return 0; N.B. I tre livelli di if annidati sono evidenziati con tre colori diversi. Pagina 10
if annidati con condizioni mutuamente esclusive (2/3) Alcune osservazioni: Al livello più esterno abbiamo un unica istruzione if-else L ordine in cui vengono specificate le condizioni è significativo Non serve che la seconda condizione sia composta, ad es. (20 < temp) && (temp <= 30) Ogni else si riferisce all if immediatamente precedente Pagina 11
Esercizio Esercizio 3.3 Scrivere un programma che studi le soluzioni dell equazione di secondo grado Pagina 12
Esercizio 3.3 Specifica: Scrivere un programma che studi le soluzioni dell equazione di secondo grado ax 2 +bx+c=0 Algoritmo: Si hanno tre possibili casi, in base al valore di Δ = b 2 4ac : A. Δ > 0: radici reali e distinte B. Δ = 0: radici reali coincidenti C. Δ < 0: radici immaginarie Pagina 13
Soluzione Esercizio 3.3 #include <stdio.h> #include <stdlib.h> int main() { int int_a, int_b, int_c, delta; printf("programma per la soluzione di ax^2+bx+c\n\n"); printf("inserisci a:\n"); scanf("%d", &int_a); printf("inserisci b:\n"); scanf("%d", &int_b); printf("inserisci c:\n"); scanf("%d", &int_c); delta = int_b*int_b - 4*int_a*int_c; if(delta > 0) printf("le radici sono reali e distinte\n"); else if(delta == 0) printf("le radici sono reali e coincidenti\n"); else printf("le radici sono immaginarie\n"); system("pause"); Pagina 14
Test: output del programma Programma per la soluzione di ax^2+bx+c inserisci a: 3 inserisci b: 4 inserisci c: 6 le radici sono immaginarie Premere un tasto per continuare... Pagina 15
Istruzioni if-else con else ambiguo (1/3) Consideriamo il seguente frammento di codice: if (a > 0) if (b > 0) printf("b positivo\n"); else printf("???\n"); printf("???\n"); potrebbe essere il ramo else Del primo if: quindi andrebbe sostituito con printf("a non positivo\n"); Del secondo if: quindi andrebbe sostituito con printf("b non positivo\n"); Pagina 16
Istruzioni if-else con else ambiguo (2/3) L ambiguità si risolve assumendo come regola: Un else fa sempre riferimento all if più vicino if (a > 0) if (b > 0) printf("b positivo\n"); else printf("b non positivo\n"); Pagina 17
Istruzioni if-else con else ambiguo (3/3) E sempre possibile usare il blocco di istruzioni (cioè { ) per disambiguare istruzioni if-else annidate. In particolare, affinché un else si riferisca ad un if che non sia quello immediatamente precedente, quest ultimo deve essere racchiuso in un blocco. Esempio if (a > 0) { if (b > 0) printf("b positivo\n"); else printf("a non positivo\n"); Pagina 18
Esercizio: tipo di triangolo Esercizio 3.4 Scrivere un programma che acquisisca tre valori a, b, c rappresentanti le lunghezze dei lati di un triangolo e sia in grado di stabilire se si tratti di un triangolo equilatero, isoscele o scaleno. Pagina 19
Tipo di triangolo: possibile algoritmo Un primo algoritmo: si confrontano i lati a coppie, fin quando non si sono raccolte informazioni sufficienti a decidere il tipo del triangolo. Pagina 20
Tipo di triangolo: possibile algoritmo Ciascun lato deve essere minore della somma degli altri due, altrimenti non si ha un triangolo (a + b) > c AND (b + c) > a AND (a + c) > b E: equilatero I: isoscele S: scaleno Pagina 21
Tipo di triangolo: codice #include <stdio.h> int main () { int a,b,c; printf("valore di a:\n"); scanf("%d", &a); printf("valore di b:\n"); scanf("%d", &b); printf("valore di c:\n"); scanf("%d", &c); if (((a + b) > c) && ((b + c) > a) && ((a + c) > b)) { if (a==b) { if (a==c) printf("triangolo equilatero"); else printf("triangolo isoscele"); else if (a==c) printf("triangolo isoscele"); else if (b==c) printf("triangolo isoscele"); else printf("triangolo scaleno"); else printf("non e\' un triangolo!"); return 0; Pagina 22
Condizione Complessa La condizione di un istruzione if-else può essere un espressione booleana complessa, nella quale compaiano gli operatori logici &&,, e!. Si deve tenere presente che le sotto-espressioni relative a tali operatori vengono valutate da sinistra a destra Pagina 23
Valutazione di una condizione complessa Nel valutare (e1 && e2), se la valutazione di e1 restituisce 0 (falso), allora e2 non viene valutata. Nel valutare (e1 e2), se la valutazione di e1 restituisce 1 (vero), allora e2 non viene valutata. Pagina 24
Esempio int i;... if (i > 0 && f(i) > 100) { printf("%d\n", i); Si noti che la funzione f(i) non viene invocata nel caso in cui i abbia valore minore o uguale a 0. Nota: istruzioni if-else che fanno uso di espressioni booleane complesse potrebbero essere riscritte attraverso l uso di if-else annidati. In generale, però, questo comporta la necessità di duplicare codice. Pagina 25
Uso dell operatore di congiunzione && if ((x < y) && (y < z)) printf("y compreso tra x e z\n"); else printf("y non compreso tra x e z\n"); corrisponde a if (x < y) if (y < z) printf("y compreso tra x e z\n"); else printf("y non compreso tra x e z\n"); else printf("y non compreso tra x e z\n"); Pagina 26
Uso dell'operatore di disgiunzione if ((x == 1) (x == 2)) printf("x uguale a 1 o a 2\n"); else printf("x diverso da 1 e da 2\n"); corrisponde a if (x == 1) printf("x uguale a 1 o a 2\n"); else if (x == 2) printf("x uguale a 1 o a 2\n"); else printf("x diverso da 1 e da 2\n"); Pagina 27
Espressione condizionale Il C mette a disposizione un operatore di selezione che permette di costruire un espressione condizionale. L uso di un espressione condizionale può, in alcuni casi, semplificare il codice rispetto all uso di un istruzione if-else. Sintassi condizione? espressione1 : espressione2 condizione è un espressione condizionale espressione1 e espressione2 sono due espressioni qualsiasi che devono essere dello stesso tipo Pagina 28
Semantica Valuta condizione. Se il risultato è diverso da zero (true), allora valuta espressione1 e restituiscine il valore, altrimenti (false) valuta espressione2 e restituiscine il valore. Esempio printf("massimo = %d\n", (a > b)? a : b); Pagina 29
Operatore di selezione ternario (? :) L istruzione printf("massimo = %d\n", (a > b)? a : b); è equivalente a: if (a > b) printf("massimo = %d", a); else printf("massimo = %d", b); L operatore di selezione combina espressioni e restituisce un altra espressione L istruzione if-else raggruppa istruzioni, ottenendo un istruzione composta. Pagina 30
L'istruzione switch Consente di realizzare una selezione a più vie. Sintassi (versione con break) switch (espressione) { case etichetta1 : istruzioni1 break;... case etichettan : istruzionin break; default: istruzioni-default Pagina 31
Sintassi espressione è un espressione intera o di tipo char etichetta1,..., etichettan sono espressioni intere (o carattere) costanti; possono contenere solo letterali interi (o carattere) o costanti inizializzate con espressioni costanti; una espressione non può essere ripetuta come etichetta in più case istruzioni1,..., istruzionin e istruzioni-default sono sequenze di istruzioni qualsiasi La parte default è opzionale Pagina 32
Semantica 1. viene prima valutata espressione 2. viene cercato il primo K per cui il valore di espressione è pari a etichettak 3. se si è trovato tale K, allora vengono eseguite istruzionik, altrimenti vengono eseguite istruzioni-default 4. l esecuzione procede con l istruzione successiva all istruzione switch Pagina 33
Esempio int i;... switch (i) { case 0: printf("zero\n"); break; case 1: printf("uno\n"); break; case 2: printf("due\n"); break; default: printf("minore di zero \n"); printf("o maggiore di due\n"); Pagina 34
Raggruppare i case Se si hanno più valori per cui eseguire le stesse istruzioni, si possono raggruppare i diversi case: case valore1 : case valore2 : istruzioni break; Pagina 35
Esempio: raggruppare i case int mese, giornidelmese;... switch (mese) { case 4: case 6: case 9: case 11: giornidelmese = 30; break; case 1: case 3: case 5: case 7: case 8: case 10: case 12: giornidelmese = 31; break; case 2: giornidelmese = 28; break; default: giornidelmese = 0; printf("mese non valido\n"); printf("giorni: %d\n", giornidelmese); Pagina 36
Osservazioni sull istruzione switch L espressione usata per la selezione può essere una qualsiasi espressione C che restituisce un valore intero o carattere (ma non un valore reale). I valori specificati nei vari case devono invece essere espressioni costanti, cioè il loro valore deve essere noto a tempo di compilazione. Non possono essere usate nei case espressioni che facciano riferimento a variabili. Pagina 37
Errori nell istruzione switch Il seguente frammento di codice è sbagliato: int a;... switch (a) { case a < 0: printf("negativo\n"); // ERRORE: a < 0 non e' una costante case 0: printf("nullo\n"); case a > 0: printf("positivo\n"); // ERRORE: a > 0 non e' una costante Pagina 38
Omissione del break In generale, non è obbligatorio che nei case di un istruzione switch l ultima istruzione sia break. Sintassi (versione generale) switch (espressione) { case etichetta1 : istruzioni1... case etichettan : istruzionin default: istruzioni-default Pagina 39
Sintassi espressione è un espressione intera o di tipo char etichetta1,..., etichettan sono espressioni intere (o carattere) costanti; ovvero, possono contenere solo letterali interi (o carattere) o costanti inizializzate con espressioni costanti; una espressione non può essere ripetuta come etichetta in più case istruzioni1,..., istruzionin e istruzioni-default sono sequenze di istruzioni qualsiasi La parte default è opzionale Pagina 40
Semantica 1. viene prima valutata espressione 2. viene cercato il primo K per cui il valore di espressione è pari a etichettak 3. se si è trovato tale K, allora vengono eseguite in sequenza istruzionik, istruzionik+1,..., fino a quando non si incontra break o è terminata l istruzione switch, altrimenti vengono eseguite istruzioni-default 4. l esecuzione procede con l istruzione successiva all istruzione switch Pagina 41
Esempio int lati; // numero di lati del poligono (al piu' 6)... printf("poligoni con al piu\' %d lati: ", lati); switch (lati) { case 6: printf("esagono, "); case 5: printf("pentagono, "); case 4: printf("rettangolo, "); case 3: printf("triangolo"); break; case 2: case 1: printf("nessuno ); break; default: printf("immetti un valore <= 6.\n"); Pagina 42
Esecuzione Se il valore di lati è pari a 5, allora il precedente codice stampa: pentagono, rettangolo, triangolo Nota: quando si omettono i break, diventa rilevante l ordine in cui vengono scritti i vari case. Questo può essere spesso causa di errori. E buona norma utilizzare break come ultima istruzione di ogni case. Pagina 43
Esercizio Esercizio 3.5 Scrivere un programma che legga da input un codice scelto a piacere per indicare una specifica funzione matematica (es. logaritmo, seno, etc.), quindi legga i relativi operandi e restituisca il risultato della funzione. Gli input devono essere inseriti separati da virgole. Esempio Se il codice scelto è 0 per log, 1 per sin, e 2 per cos, nel caso in cui l utente inserisca 1,3.14, il programma stamperà sin(3.140000) = 0.001593 Pagina 44
Possibile soluzione #include <stdio.h> #include <math.h> int main (){ int codice; double dato; printf("inserisci il codice funzione e l\'operando separati" " da una virgola\n"); scanf("%d,%lf", &codice, &dato); switch(codice) { case 0: printf("log(%f) = %f\n", dato, log(dato)); break; case 1: printf("sin(%f) = %f\n", dato, sin(dato)); break; case 2: printf("cos(%f) = %f\n", dato, cos(dato)); break; default: printf("il codice inserito non corrisponde ad alcuna" " funzione\n"); return 0; Pagina 45