Esercitazione 12 Esercizi di Ricapitolazione Esercizio Scrivere un programma che, dato un numero intero positivo, stampa la sua rappresentazione binaria. ALGORITMO Scriviamo una procedura stampa_bin che, dato un numero intero positivo num, ¾ ¾ divide ripetutamente num per 2 e memorizza i resti delle divisioni intere in un vettore resti [ ]; stampa i resti delle divisioni nell’ordine inverso in cui sono stati calcolati in modo tale da visualizzare la rappresentazione binaria del numero decimale num. Soluzione #include <stdio.h> #define DIM_INT 16 void stampa_bin (int); /*dichiarazione della procedura stampa_bin */ main ( ) { int num; printf (“Inserisci un numero intero positivo: ”); scanf (“%d”, &num); printf (“ La sua rappresentazione binaria è: ”); stampa_bin (num); /* invocazione della procedura stampa_bin */ } void stampa_bin (int v) { int i, j; int resti [DIM_INT]; /*definizione della procedura stampa_bin */ if ( v==0 ) printf (“%d”, v); else { for (i=0; v!=0; i++) { resti [i] = v % 2; v /= 2; } for (j = i-1; j>=0; j--) printf (“%d”, resti [j]); } } Un esempio di esecuzione del programma è: Inserisci un numero intero positivo:13 La sua rappresentazione binaria è: 1101 Esercizio Si consideri la chiamata di procedura stampa_bin(13); nel programma precedente. Dire qual’è il valore della variabile i all’uscita del primo ciclo for nel corpo della procedura. Soluzione i=4 Ricerca di un elemento in un array ESERCIZIO Scrivere un programma per determinare se un valore è presente all’interno di un array di caratteri. ¾ ¾ Il programma scorre in maniera sequenziale tutti gli elementi dell’array confrontandoli con il valore cercato. Se tale valore è presente nell’array, la scansione degli elementi dell’array termina e viene restituito l’indice corrispondente a tale elemento all’interno dell’array stesso. Programma */ Ricerca sequenziale di un valore in un array */ #include <stdio.h> #define MAX_ELE 1000 */ massimo numero di elementi */ main ( ) { char arr [MAX_ELE]; int i, n; char c; */ variabile che conterrà il valore da cercare */ (continua) */ immissione della lunghezza della sequenza */ do { printf (“\n Numero elementi: ”); scanf (“%d”, &n); } while (n<1 | | n>MAX_ELE); */ immissione degli elementi della sequenza */ for (i=0; i<n; i++) { printf (“\n Immettere carattere n. %d: ”, i); scanf (“%1s”, &arr [i]); } (continua) */ immissione elemento da cercare */ printf (“\n Elemento da cercare: ”); scanf (“%1s”, &c); */ ricerca sequenziale */ i = 0; while (c != arr [i] && i <= n-1) ++i; if (i<=n-1 && c == arr [i]) printf (“\nElemento %c presente in posizione %d\n”, c, i); else printf (“\nElemento non presente!\n”); } Ricerca di una sottostringa in una stringa ESERCIZIO Scrivere una funzione che date due stringhe s e t restituisca un puntatore alla prima occorrenza della stringa t in s se t è una sottostringa di s altrimenti restituisca un puntatore NULL. s b i o g r t g r a f i a /0 a i a f /0 Funzione str_in_str char *str_in_str (char *s, char *t) { char *v; */ scorri la stringa s finché non incontri l’elemento ‘\0’ */ while (*s != ‘\0’) { */ inizio ciclo while */ if (*s == *t) */ verifica se hai trovato una sottostringa uguale a t in s */ */ scorri la stringa t mediante il puntatore v */ for (v = t; *s == *v;) { */ inizio ciclo for */ if (*++v == ‘\0’) return (s-(v-t-1)); */ v-t-1 è la lunghezza della stringa t */ if (*++s == ‘\0’) return (NULL); } */ fine ciclo for */ else s++; } return (NULL); } Esercizio Scrivere un tipo di dato Bilancio che è un array di record aventi due campi: il campo voce descrive la tipologia di entrata o uscita (ad esempio: alimentari, stipendio, benzina, ...), mentre il campo importo conterrà l’importo relativo a tale voce, che sarà positivo se si tratta di una entrata e negativo se si tratta di una uscita. Il numero di voci del bilancio è dato da una costante simbolica N_VOCI. typedef struct { char *voce; int importo; } Entry; typedef Entry Bilancio [N_VOCI]; Esercizio Scrivere una procedura stampa_bilancio che dato, un valore di tipo Bilancio, stampa a video, uno per riga, gli elementi della tabella passata come parametro attuale, secondo la seguente sintassi: <voce> : <importo> Nell’ ultima riga, viene stampato il saldo (differenza tra entrate e uscite). void stampa_bilancio (Bilancio bilancio) { int i; int saldo = 0; for (i=0; i<N_VOCI; i++) { saldo += bilancio[i].importo; printf (“%s : %d\n”, bilancio[i].voce, bilancio[i].importo); } printf (“\n saldo : %d\n”, saldo); } Esercizio Scrivere una funzione preventivo08 che prende come parametri attuali due tabelle di tipo Bilancio, la prima contenente il bilancio preventivo del 2007 (fatto all’inizio del 2007) e la seconda contenente il bilancio consuntivo del 2007 (fatto alla fine del 2007 e contenete gli importi effettivi relativi ad ogni voce). La funzione deve restituire una nuova tabella, contenente gli importi preventivati per il 2008 relativi a ciascuna voce in accordo con la seguente visione “pessimista”: per ogni voce se si tratta di una entrata prenderemo il minimo tra il valore preventivato e quello effettivo, mentre se si tratta di una uscita, prenderemo il maggiore (in valore assoluto). Utilizzare la memoria dinamica per costruire il bilancio preventivo del 2008. void alloca_entry (Entry* nuova, Entry riferimento) { nuova --> voce = (char*) calloc (strlen(riferimento.voce)+1, sizeof(char)); } Entry *preventivo08 (Bilancio preventivo07, Bilancio consuntivo07) { Entry *bilancio; int i; bilancio = (Entry *) calloc (N_VOCI, sizeof (Entry)); for (i=0; i<N_VOCI; i++) { alloca_entry (&(bilancio [i]), preventivo07[i]); strcpy(bilancio[i].voce, preventivo07[i].voce); if (preventivo07[i].importo < consuntivo07[i].importo) bilancio[i].importo = preventivo07[i].importo; else bilancio[i].importo = consuntivo07[i].importo; } return bilancio; } Esercizio Scrivere una funzione aggiungi_voce che prende come parametri attuali una tabella di tipo Bilancio ed un valore di tipo Entry. La funzione restituisce una nuova tabella (dinamica) che è la copia della tabella passata con una riga in più, contenente la nuova entry (che si vuole aggiungere) passata come secondo parametro. Entry * aggiungi_voce (Bilancio bilancio, Entry entry) { Entry *bilancionuovo; int i; bilancionuovo = (Entry *) calloc ((N_VOCI+1), sizeof(Entry)); for (i=0; i<N_VOCI; i++) { alloca_entry(&(bilancionuovo[i]), bilancio[i]); strcpy (bilancionuovo[i].voce, bilancio[i].voce); bilancionuovo[i].importo = bilancio[i].importo; } alloca_entry (& (bilancionuovo [N_VOCI]), entry); strcpy (bilancionuovo[N_VOCI].voce, entry.voce); bilancionuovo [N_VOCI].importo = entry.importo; return bilancionuovo; } Che cos’è ? int *p; /* p è un puntatore a un intero */ int *p[10]; /* p è un array con 10 elementi di tipo puntatore a un intero */ int *p (void); /* p è una funzione che restituisce un puntatore a un intero */ int p (char *a); /* p è una funzione che accetta come argomento un puntatore a un carattere e restituisce un intero */ int *p (char *a); /* p è una funzione che accetta come argomento un puntatore a un carattere e restituisce un puntatore a un intero */ Che cos’è ? int (*p) (char *a); /* p è un puntatore a una funzione che accetta come argomento un puntatore a un carattere e restituisce un intero */ int (*p) [10]; /* p è un puntatore a un array di 10 elementi di tipo intero */ int p (char *a [ ]); /* p è una funzione che accetta come argomento un array di puntatori a caratteri e restituisce un intero */ int p (char (*a) [ ]); /* p è una funzione che accetta come argomento un puntatore a un array di caratteri e restituisce un intero */ Che cos’è ? int (*p) (char (*a) [ ]); /* p è un puntatore a una funzione che accetta come argomento un puntatore a un array di caratteri e restituisce un intero */ int *p (char (*a) [ ]); /* p è una funzione che accetta come argomento un puntatore a un array di caratteri e restituisce un puntatore a un intero */ int *p (char *a [ ]); /* p è una funzione che accetta come argomento un array di puntatori a caratteri e restituisce un puntatore a un intero */ int *p (char a [ ]); /* p è una funzione che accetta come argomento un array di caratteri e restituisce un puntatore a un intero */ Riordinare un elenco di stringhe Vogliamo inserire una serie di stringhe nel computer, disporle in ordine alfabetico e poi visualizzarle. Registriamo le stringhe in un array di caratteri bidimensionale; ogni stringa sarà registrata in una riga distinta all’interno dell’array. Permettiamo al programma di accettare un numero di stringhe non specificato, finché non incontra la stringa END. Utilizziamo le funzioni di libreria strcmp e strcpy che servono rispettivamente a confrontare due stringhe e a copiare una stringa in un’altra. La funzione strcmp accetta due stringhe come argomenti, le confronta e restituisce un valore intero in questo modo: ) se la prima stringa precede alfabeticamente la seconda, viene restituito un valore negativo; ) se le due stringhe sono identiche (ignorando la differenza tra caratteri maiuscoli e minuscoli), viene restituito un valore zero; ) se la seconda stringa precede alfabeticamente la prima, viene restituito un valore positivo. La funzione strcpy accetta due stringhe come argomenti. In genere il primo argomento string1 è un identificatore che rappresenta una stringa; il secondo argomento string2 può essere una costante di stringa o un identificatore che rappresenta un’altra stringa. La funzione copia il contenuto di string2 in string1: in definitiva, è come se strcpy assegnasse una stringa a un’altra stringa. Algoritmo di ordinamento per selezione Il processo di ordinamento comincia dall’esame dell’intero array alla ricerca della stringa più piccola, quella cioè che precede alfabeticamente tutte le altre. Questa stringa viene scambiata con la prima stringa dell’array: dunque la stringa più piccola diventa la prima dell’array. Si passa quindi a considerare le restanti n-1 stringhe alla ricerca della più piccola, che sarà scambiata con la seconda stringa dell’array. Poi si passa alle restanti n-2 stringhe, in cerca della più piccola, che viene scambiata con la terza stringa dell’array, e così via finché l’array non sarà ordinato. Per trovare la stringa più piccola, ad ogni passaggio, si confronta ciascuna delle stringhe non ancora ordinate con la prima stringa. Se si trova una stringa più piccola della prima le due stringhe vengono scambiate. 1o passo el_1 el_2 el_3 … el_i … el_n sia el_i il più piccolo tra el_1 ... el_n el_i el_2 el_3 scambia … el_1 … el_n 2o passo el_i el_2 el_3 … el_k … el_n sia el_k il più piccolo tra el_2 ... el_n el_i el_k el_3 … el_2 … el_n scambia 3o passo considera gli elementi dell’array compresi tra el_3 e el_n ... */ ordina alfabeticamente un elenco di stringhe utilizzando un array di caratteri bidimensionale */ #include <stdio.h> #include <stdlib.h> #include <string.h> void ordina (char elenco[ ][12], int n); main ( ) { int i, n = 0; char elenco [10] [12]; printf (“Digita ogni stringa su una riga distinta\n\n”); printf (“Digita END per finire\n\n”); */ lettura delle stringhe */ do { printf (“stringa %d: ”, n+1); scanf (“%s”, elenco[n] ); } while (strcmp(elenco[n++], “END”)); n--; ordina (elenco, n); */ visualizzazione dell’elenco ordinato */ printf (“Elenco ordinato delle stringhe:\n”); for (i=0; i < n; i++) printf (“\nstringa %d: %s”, i+1, elenco[i]); } */ procedura per ordinare gli elementi dell’array */ void ordina (char elenco[ ][12], int n) { char temp [12]; int i, j; for (j=0; j < n-1; ++j) for (i=j+1; i < n; ++i) if (strcmp(elenco[j], elenco[i])>0) { */ scambia due stringhe */ strcpy(temp, elenco[j]); strcpy(elenco[j], elenco[i]); strcpy(elenco[i], temp); } return; } Esempio di esecuzione del programma Digita ogni stringa su una riga distinta Digita END per finire stringa 1: Pacifico stringa 2: Atlantico stringa 3: Indiano stringa 4: Caraibi stringa 5: Nero stringa 6: Rosso stringa 7: Nord stringa 8: Baltico stringa 9: Caspio stringa 10: END Elenco ordinato delle stringhe: stringa 1: Atlantico stringa 2: Baltico stringa 3: Caraibi stringa 4: Caspio stringa 5: Indiano stringa 6: Nero stringa 7: Nord stringa 8: Pacifico stringa 9: Rosso Esercizio 1) Definire un tipo enumerazione Indumento che rappresenta gli indumenti venduti in un negozio di abbigliamento maschile: camicia, pantaloni, giacca, cravatta. typedef enum Indumento {camicia, pantaloni, giacca, cravatta} Indumento; 2) Definire un tipo enumerazione Colore che rappresenta i colori: bianco, azzurro, grigio, blu. typedef enum Colore {bianco, azzurro, grigio, blu} Colore; 3) Dichiarare un tipo record Articolo che rappresenta un articolo venduto nel negozio caratterizzato dai seguenti tre campi: indumento, colore, taglia. typedef struct { Indumento indumento; Colore colore; int taglia; } Articolo; 4) Utilizzando il tipo Articolo definito precedentemente, dichiarare il tipo dinamico Scaffale per rappresentare una lista di articoli in cui ciascun elemento ha due campi: articolo, next. typedef struct Elem_scaffale { Articolo articolo; struct Elem_scaffale *next; } Elem_scaffale; typedef Elem_scaffale *Scaffale; /* Scaffale è una lista di articoli */ 5) Inizializzare una variabile completo_casual di tipo Scaffale che è una lista di due articoli: camicia blu, pantaloni grigi, entrambi di taglia 48. Scaffale completo_casual; completo_casual = (Scaffale) malloc (sizeof (Elem_scaffale)); (completo_casual -> articolo).indumento = camicia; (completo_casual -> articolo).colore = blu; (completo_casual -> articolo).taglia = 48; completo_casual -> next = (Scaffale) malloc (sizeof (Elem_scaffale)); (completo_casual -> next -> articolo).indumento = pantaloni; (completo_casual -> next -> articolo).colore = grigio; (completo_casual -> next -> articolo).taglia = 48; completo_casual -> next -> next = NULL; 6) Scrivere una funzione, che prendendo come parametro attuale un valore di tipo Scaffale e verifica se tutti gli articoli presenti nello Scaffale hanno taglia 48. int verifica_taglia (Scaffale s) { int risultato; if (s == NULL) risultato = 0; else risultato = 1; while (s != NULL) { if ((s -> articolo).taglia != 48) { risultato = 0; break; } s = s -> next; } return risultato; } 7) Dichiarare un tipo record Articolo_in_vendita che rappresenta un puntatore ad un articolo in vendita nel negozio e il suo prezzo. typedef struct { Articolo* articolo; int prezzo; } Articolo_in_vendita; 8) Dichiarare un tipo Espositore che è una tabella 10 per 10 di Articoli_in_vendita. typedef Articolo_in_vendita Espositore [10][10]; 9) Inizializzare una variabile di tipo Espositore in modo che rappresenti un espositore vuoto nel quale è presente solo una camicia bianca taglia 48 in una qualunque posizione dell’espositore. Espositore espositore; Articolo* articolo_presente; int i, j; for (i=0; i<10; i++) for (j=0; j<10; j++) { espositore[i][j].articolo = NULL; espositore [i][j].prezzo = 0; } articolo_presente = (Articolo*) malloc (sizeof (Articolo)); articolo_presente -> indumento = camicia; articolo_presente -> colore = bianco; articolo_presente -> taglia = 48; espositore[0][0].articolo = articolo_presente; 10) Scrivere una funzione che prendendo come parametro attuale un Espositore verifica se una camicia bianca taglia 48 è presente nell’espositore. int cercaCamicia (Espositore espositore) { int i, j; for (i=0; i<10; i++) for (j=0; j<10; j++) { if ((espositore[i][j].articolo != NULL) && ((espositore[i][j].articolo) -> indumento == camicia) && ((espositore[i][j].articolo) -> colore == bianco) && ((espositore[i][j].articolo) -> taglia == 48)) return 1; } return 0; }