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;
}