Facoltà di Ingegneria Industriale Laurea in Ingegneria Energetica, Meccanica e dei Trasporti Corso di Informatica B - Sezione D Esercitazioni Linguaggio C Politecnico di Milano - DEI 1
Facoltà di Ingegneria Industriale Laurea in Ingegneria Energetica, Meccanica e dei Trasporti Linguaggio Iterazioni Array Matrici Controlli input avanzati Politecnico di Milano - DEI 2
Esercizio 1 Scrivere un programma che stampi i primi N numeri primi con N intero inserito da utente. Obiettivi iterazioni istruzioni di controllo Politecnico di Milano - DEI 3
Esercizio 1 - Soluzione Numero primo: un numero primo è un numero naturale maggiore di 1 che sia divisibile solamente per 1 e per se stesso. Nel progetto della soluzione occorre: richiedere l inserimento di N e verificare che sia maggiore o uguale ad 1; verificare quali tra i numeri k da 2 ad N (...1 è primo per definizione...) sono primi; Un numero k sarà primo se per tutti i divisori num = [1...k-1], il resto della divisione k/num è non nullo. Definisco le variabili necessarie: int N, j, k, primo; int num = 1; char scelta; Politecnico di Milano - DEI 4
Esercizio 1 - Soluzione Chiedo in input N controllando che ricada nei vincoli specificati: printf("fino a quanto vuoi calcolare i numeri primi? "); do scanf("%d", &N); while(n < 1); Per controllare quale tra gli interi da 1 a N è un numero primo occorre utilizzare due cicli for annidati. In pseudocodice le operazioni da svolgere saranno: for (tutti gli interi da 1 a N) for (tutti i divisori da 2 a num) if ((num % k) == 0)il num corrente NON è primo if (num è primo)stampo num a video Politecnico di Milano - DEI 5
Esercizio 1 - Soluzione Traducendo lo pseudocodice in codice: for (num = 1; num <= N; num++) primo = 1; for (k = 2; k < num; k++) if ((num % k) == 0) primo = 0; break; if (primo) printf(" %3d", num); Politecnico di Milano - DEI 6
Esercizio 1 - Soluzione Chiedo all utente se vuole ripetere l operazione controllando che la risposta immessa sia unicamente s o n: printf("nuovo calcolo? s/n"); do scanf("%c", &scelta); while(scelta!= 's' && scelta!= 'n'); Se la scelta ricade sul si, rilancio la funzione main() per ripetere tutta la procedura: if (scelta == 's') main(); return 0; Politecnico di Milano - DEI 7
Esercizio 2 Inserire e validare una data in formato DD/MM/YYYY Obiettivi do while scanf più complesse condizioni complesse if ed if else Politecnico di Milano - DEI 8
Esercizio 2 - Soluzione Affinché una data nel formato DD/MM/YYYY sia corretta, è necessario controllare che: YYYY > 0; la parte DD sia sempre >= 1 e <=31; se il il mese è febbraio, DD <= 28; se il il mese è febbraio e l anno è bisestile DD <= 29; se i mesi sono Aprile, Giugno, Settembre, Novembre: DD <= 30; Vediamo come comporre il corpo della funzione principale per implementare questa soluzione. Dichiaro la variabile che conterrà i mesi dell anno. Per i mesi dell anno scelgo una variabile di tipo enum. L enumerazione risulta molto utile quando si ha una lista finita di elementi a cui si vuole associare un numero intero per identificarli: enum GEN = 1, FEB, MAR, APR, MAG, GIU, LUG, AGO, SET, OTT, NOV, DIC; Per ulteriori informazioni su enum consulta: http://www.acm.uiuc.edu/webmonkeys/book/c_guide/1.2.html#variables, Politecnico di Milano - DEI 9
Esercizio 2 - Soluzione Dichiaro le altre variabili: int g, m, a; // Giorno, mese, anno. int datacorretta; int isbisestile; Inizializzo datacorretta al valore corretto 1, il suo valore verrà cambiato se si incontra un errore, e chiedo in input la data. datacorretta = 1; printf("inserisci la data in formato DD/MM/YYYY: "); scanf("\n%d/%d/%d", &g, &m, &a); Si noti il formato della scanf. Tra i tre placeholder %d sono stati inseriti i separatori / (limitatori di record). In questo modo possiamo far leggere alla funzione contemporaneamente più valori memorizzandoli automaticamente nelle variabili g,m,a. iniziando da g, ogni volta che la scanf incontrerà il simbolo / passerà alla memorizzazione nella variabile successiva. Il separatore sarebbe potuto essere anche un carattere diverso come - o *. Politecnico di Milano - DEI 10
Esercizio 2 - Soluzione Cosa succede se utilizziamo un limitatore di record diverso da quello specificato nella scanf? Inizio il controllo della data. Controllo generale su giorno, mese, anno: if ( g < 1 g > 31 m < 1 m > 12 a < 0) datacorretta = 0; continue; Politecnico di Milano - DEI 11
Esercizio 2 - Soluzione E' anno bisestile? se non bisestile, i giorni non osso essere più di 28 altrimenti non possono essere più di 29 isbisestile = (a%4 == 0 && a%100!= 0) a%400 == 0 ; if(m==feb&&((isbisestile&&g>29) (!isbisestile &&g>28))) // datacorretta = 0; Controlliamo i mesi con 30 giorni: else if((m==apr m==giu m==set m==nov) && g>30 ) datacorretta = 0; Politecnico di Milano - DEI 12
Esercizio 2 - Soluzione Se datacorretta ha mantenuto il valore 0, vuol dire che non è nel formato giusto. if (datacorretta == 0) printf("la data immessa non e valida. Riprovare."); Tutto il controllo della data può essere inserito all interno di un ciclo do...while per fare in modo che,a fronte di una data non corretta, il programma non termini ma ne chieda un altra finché la forma DD/MM/YYYY non viene rispettata. do...controllo data... while ( datacorretta == 0 ); printf("la data esiste!"); return 0; Politecnico di Milano - DEI 13
Esercizio 3 Chiedere nome, cognome ed età dell'utente e scrivere frase di benvenuto personalizzata Obiettivi primi passi con array Politecnico di Milano - DEI 14
Esercizio 3 - Soluzione La soluzione dell esercizio è strutturata in pochi semplici passi: chiediamo in ingresso: nome, cognome ed età separatamente; leggiamo i dati e li salviamo in apposite variabili; utilizzando le variabili di salvataggio compongo la stringa di benvenuto. Nell implementazione occorre prestare attenzione al tipo di variabile in cui memorizzare nome e cognome. In C abbiamo la variabile char che ci permette di memorizzare un solo carattere. Per memorizzare una stringa occorre creare una variabile che sia un array di char. Fatta questa premessa, possiamo definire le variabili utili alla souzione: int eta; char nome[max], cognome[max]; dove la dimensione MAX è una costante definita tramite: #define MAX 10 Politecnico di Milano - DEI 15
Esercizio 3 - Soluzione Chiedo in input nome, cognome ed età: printf("inserire nome: "); scanf("%s", nome); printf("inserire cognome: "); scanf("%s", cognome); // Cosa succede con la scanf di stringhe? printf("inserire eta : "); scanf("%d", &eta); Si noti che nella scanf non serve la & davanti al nome della variabile. Nel caso di array, il nome della variabili si riferisce già ad un indirizzo di memoria: l indirizzo in cui è memorizzato il primo elemento. Politecnico di Milano - DEI 16
Esercizio 3 - Soluzione Scrivo la stringa di benvenuto e chiudo la funzione principale. printf("ciao %s %s! Hai %d anni.", cognome, nome, eta); return 0; Politecnico di Milano - DEI 17
Esercizio 4 Chiedere all utente di aggiungere o cercare una persona in un registro di cognomi. L utente può anche visualizzare l intero contenuto del registro Non devono esserci duplicati. Obiettivi C è tutto quello visto finora Comparazione tra stringhe Navigazione in un array Politecnico di Milano - DEI 18
Esercizio 4 - Soluzione Progettiamo la soluzione in modo che l utente abbia a disposizione un menu di comandi nel momento in cui avvia il programma. Il menu sarà composto da: inserimento [i] ricerca [r] visualizzazione [v] quit [q] A seconda della scelta verrà eseguita la porzione di codice corrispondente. In aggiunta sarà bene implementare anche un controllo sulla validità della scelta fatta dall utente per rendere il codice più robusto. Tutta la procedura deve ripetersi finchè l utente non sceglie di uscire dal programma con il comando quit. Politecnico di Milano - DEI 19
Esercizio 4 - Soluzione La soluzione ha una struttura articolata. In questi casi è comodo scriverne la struttura in forma di pseudocodice: do do Visualizzazione menu e inserimento comando... while ( cmd!= 'c' && cmd!= 'q' && cmd!= 'i' && cmd!= 'v'); if (cmd == 'c') Cerca... else if (cmd == 'v') Visualizza... else if (cmd == 'i') Inserisci... while ( cmd!= 'q' ); return 0; Politecnico di Milano - DEI 20
Esercizio 4 - Soluzione Dichiaro le variabili necessarie e analizzo le porzioni dello pseudocodice. char registro[max_reg_size][max_string_size]; char cognome[max_string_size]; char cmd; int elementiregistro = 0; int i; con MAX_REG_SIZE e MAX_STRING_SIZE definite tramite: #define MAX_STRING_SIZE 30 #define MAX_REG_SIZE 10 Politecnico di Milano - DEI 21
Esercizio 4 - Soluzione - Visualizzazione menu e inserimento comando - Finché non viene inserito un comando valido, previsto nel menu, continuo a chiedere all utente di fare una scelta. do printf("scegliere l'operazione da eseguire:[i][c][v][q]"); scanf("%c", &cmd); while ( cmd!='c' && cmd!='q' && cmd!='i' && cmd!='v' ); Politecnico di Milano - DEI 22
Esercizio 4 - Soluzione - Cerca - Per eseguire la ricerca nel registro occorre assicurarci preliminarmente che la rubrica abbia degli elementi memorizzati al suo interno. Se il registro non è vuoto, acquisisco il nome ed effettuo la ricerca. if (cmd == 'c') if ( elementiregistro!= 0 ) printf("inserire cognome da cercare: "); scanf("%s", cognome); getchar(); for ( i=0; i < elementiregistro; i++) if (strcmp(®istro[i][0], cognome) == 0 ) printf("trovato!"); break; Politecnico di Milano - DEI 23
Esercizio 4 - Soluzione Il metodo migliore per confrontare stringhe tra loro è utilizzare la funzione strcmp, contenuta nella libreria <string.h>. strcmp restituisce 0 se le due stringhe sono uguali, 1 altrimenti. Per ulteriori informazioni su #strcmp consulta: http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.14.html#strcmp Se l indice i raggiunge la fine della rubrica, il nome cercato non é presente. if (cmd == 'c') if ( elementiregistro!= 0 )... if ( i == elementiregistro ) printf("nessun riscontro."); else printf("registro vuoto."); Politecnico di Milano - DEI 24
Esercizio 4 - Soluzione - Visualizza - Ciclo sugli elementi della rubrica e li visualizzo. NOTA: il ciclo di visualizzazione va impostato sugli elementi realmente presenti nella rubrica, non sulla sua dimensione massima MAX_REG_SIZE. if (cmd == 'c')... else if (cmd == 'v') // Non ciclo su MAX_STRING_SIZE o MAX_REG_SIZE // Ma solo sul numero di elementi realmente inseriti for ( i=0; i < elementiregistro; i++) printf("%d) %s", i+1, ®istro[i][0]); Politecnico di Milano - DEI 25
Esercizio 4 - Soluzione - Inserisci - Il caso di inserimento è articolato in due parti: else if (cmd == 'i') printf("inserire cognome da aggiungere: "); scanf("%s", cognome); getchar(); i = 0; Verifico che il registro non sia vuoto. In tal caso controllo se il nome inserito è già presente in rubrica. Nel caso in cui non sia presente, procedo all inserimento. Politecnico di Milano - DEI 26
Esercizio 4 - Soluzione - Inserisci - Controllo se il cognome inserito è già presente in rubrica if ( elementiregistro!= 0 ) //Se la rubrica non è vuota for ( i=0; i < elementiregistro; i++) if (strcmp(®istro[i][0], cognome) == 0 ) printf("nome gia presente."); break; Utilizzo l indice i per scorrere tutti gli elementi della rubrica. Confronto ogni elemento registro[i][0] con il cognome inserito cognome. Se la funzione strcmp() mi restituisce 0 vuol dire che registro[i][0] e cognome sono uguali quindi, un cognome uguale è già presente in rubrica. Politecnico di Milano - DEI 27
Esercizio 4 - Soluzione - Inserisci - Nel caso in cui non sia presente, procedo all inserimento. if ( i == elementiregistro ) //Sono alla fine del registro i = 0; salvo il cognome all interno della rubrica facendo attenzione a non superare la dimensione massima memorizzabile MAX_STRING_SIZE while ( cognome[i]!= 0 && i < MAX_STRING_SIZE - 1 ) registro[elementiregistro][i] = cognome[i]; i++; Termino la stringa con 0 registro[elementiregistro][i] = 0; Incremento il numero di elementi elementiregistro++; printf("aggiunto %s.", cognome); Politecnico di Milano - DEI 28
Esercizio 5 Far inserire all utente due matrici. Chiedere poi che operazione svolgere tra: somma, differenza, e moltiplicazione scalare. Calcolare anche il massimo di ogni matrice e la media aritmetica dei suoi valori. Obiettivi Creazione, riempimento e visualizzazione di una matrice Operazioni sulle matrici: - Somma, differenza, prodotto, min, max, media Navigazione all interno di una matrice Politecnico di Milano - DEI 29
Esercizio 5 - Soluzione Articoliamo il progetto della soluzione seguendo questa struttura: Inserimento dimensioni Popolazione Richiesta ed esecuzione del tipo di operazione da effettuare Visualizzazione del risultato #define MAX 20 #define CELL_WIDTH 5 Dichiarazione ed inizializzazione delle variabili necessarie: int rows, cols, i, j; Matrici A, B e matrice dei risultati: int mtrxa[max][max], mtrxb[max][max], res[max][max]; Matrice contenente i max e i min di A e B: int mtrxmaxmin[2][2] = 0, 0, 0, 0 ; MaxA, MinA, MaxB, MinB Matrice contenente la media per le due matrici float mtrxmedia[2] = 0.0, 0.0 ; Carattere che contiene l'operazione richiesta char op; Politecnico di Milano - DEI 30
Esercizio 5 - Soluzione Valore per verificare se il comando era ok. int isbuilt = 1; Inserimento dimensioni matrici Ognuna delle due dimensioni della matrice non può superare MAX. In questo caso un controllo è fondamentale! do printf("il numero di righe delle matrici: "); scanf("%d", &rows); while(rows > MAX); // Se rows > MAX, rifaccio la domanda. do printf("il numero di colonne delle matrici: "); scanf("%d", &cols); while(cols > MAX); // Se cols > MAX, rifaccio la domanda. Politecnico di Milano - DEI 31
Esercizio 5 - Soluzione Valore per verificare se il comando era ok. int isbuilt = 1; - Popolazione matrice 1 - Nella popolazione delle matrici si lavora sugli indici delle celle. indice colonne indice righe 0 1 0 1 2 3 4... N 2 65 87 21 5 65 5 45... 2 3 4... M... 654 Gli indici che identificano gli elementi all interno di array e matrici iniziano sempre da zero! Politecnico di Milano - DEI 32
Esercizio 5 - Soluzione - Popolazione matrice 1 - for( i = 0; i < rows; i++) for(j = 0; j < cols; j++) printf("1 [%d][%d] = ", i+1, j+1); scanf("%d", &mtrxa[i][j]); Memorizzo il valore inserito come massimo se: - è il primo valore che inserisce l'utente (i == 0 && j == 0) - o se il valore inserito è maggiore del massimo: mtrxmaxmin[0][0] = mtrxa[i][j]; if(mtrxa[i][j] > mtrxmaxmin[0][0] (i == 0 && j == 0)) mtrxmaxmin[0][0] = mtrxa[i][j]; Politecnico di Milano - DEI 33
Esercizio 5 - Soluzione - Popolazione matrice 1 - Come sopra ma col minimo if(mtrxa[i][j] < mtrxmaxmin[0][1] ( i == 0 && j == 0 )) mtrxmaxmin[0][1] = mtrxa[i][j]; Incremento la somma dei valori man mano che li acquisisco mtrxmedia[0] += mtrxa[i][j] / (rows * cols); Politecnico di Milano - DEI 34
Esercizio 5 - Soluzione - Visualizzazione matrice 1 - printf("la matrice inserita e : "); for(i = 0; i < rows ; i++) for(j = 0; j < cols; j++) printf(" %3d ", mtrxa[i][j]); printf(" "); Visualizzo massimo, minimo e media printf("max: %d: %d: %.5f", mtrxmaxmin[0][0], mtrxmaxmin[0] [1], mtrxmedia[0]); Analogamente a quanto già fatto, memorizzo e visualizzo la seconda matrice. Per quest ultima non chiedo più in ingresso le dimensioni perché le pongo uguali a quelle della matrice 1. Politecnico di Milano - DEI 35
Esercizio 5 - Soluzione - Richiesta ed esecuzione dell operazione da effettuare - Il blocco di selezione deve prevedere i seguenti casi: differenza somma prodotto Utilizziamo un blocco switch per differenziare i casi: switch (op case 'd': differenza break; case 's': somma break; case 'p': prodotto break; case '' : caso in cui venga dato l invio senza aver effettuato nessuna scelta break; default: printf("%c - Operazione non nota", op); isbuilt = 0; break; Politecnico di Milano - DEI 36
Esercizio 5 - Soluzione - Richiesta ed esecuzione dell operazione da effettuare - Analizziamo i casi nel dettaglio: case 'd': printf("effettuo la DIFFERENZA"); for(i = 0; i < rows ; i++) for(j = 0; j < cols; j++) res[i][j] = mtrxa[i][j] - mtrxb[i][j]; break; Politecnico di Milano - DEI 37
Esercizio 5 - Soluzione case 's': printf("effettuo la SOMMA"); for(i = 0; i < rows ; i++) for(j = 0; j < cols; j++) res[i][j] = mtrxa[i][j] + mtrxb[i][j]; break; case 'p': printf("effettuo il PRODOTTO"); for(i = 0; i < rows ; i++) for(j = 0; j < cols; j++) res[i][j] = mtrxa[i][j] * mtrxb[i][j]; break; case '\n' : /*Non faccio nulla*/ break; Politecnico di Milano - DEI 38
Esercizio 5 - Soluzione - Visualizzazione risultato - Nel blocco switch abbiamo usato la variabile isbuilt che ci avvisa se il risultato res[][] è stato effettivamente calcolato. isbuilt appartiene ad un tipo di variabili, di solito booleane, chiamate flag (bandierine). I flag servono per eseguire porzioni di codice solo se hanno valore vero, in tala caso si dice che il flag è alzato. La visualizzazione del risultato è effettuata solo se il flag è alto, ovvero: isbuilt == 1. if (isbuilt) for(i = 0; i < rows ; i++) for(j = 0; j < cols; j++) printf(" %3d ", res[i][j]); printf("\n"); Politecnico di Milano - DEI 39