Informazioni sul corso. Cenni sull'architettura
di un calcolatore: CPU, memoria primaria e secondaria, input/output. Struttura logica
della memoria. Linguaggio macchina, linguaggio assembly. Linguaggi ad alto livello
e compilatori. Cenni storici sul linguaggio C. Primo programma in C: stampa di una
stringa di testo. Programma che stampa la somma di due numeri:
specifica di conversione della printf
per gli interi.
Memoria, locazioni di memoria, indirizzi e variabili. Dichiarazioni di variabili di tipoint
. Lettura dallo standard input tramite la funzionescanf()
. L'operatore di indirizzo&
. Assegnamenti. Operatori aritmetici:+
,-
,*
,/
,%
. Esempi:Instruzioni di selezione:
- Programmi che leggono un intero
n
e stampano il quadrato e la sedicesima potenza din
- Programma che legge due interi
n
em
e stampa il quoziente e il resto della divisione din
perm
- Programma che legge un intero
s
che rappresenta un numero di secondi e stampa l'equivalente in giorni, ore, minuti e secondi (ad es. ses = 100000
allora l'output è1 giorni 3 ore 46 minuti e 40 secondi
).if () - else
. Operatori relazionali:<
,>
,<=
,>=
,==
,!=
. Esempi: Programmi che leggono due o tre numeri e ne stampano il massimo.
Esercizio 1 Scrivere un programma che prende in input tre numeri e li stampa in ordine crescente.
Esercizio 2 Scrivere un programma legge due date nel formatog/m/a
(ad es.17/4/2009
) e le confronta stampando se la prima data è anteriore, posteriore o uguale alla seconda. Ad esempio, se le date sono12/5/2009
e10/7/2009
, il programma deve stamparela prima data è anteriore alla seconda
.
Discussione degli esercizi 1 e 2. Operatori logici||
(OR)&&
(AND). Istruzioni iterative:for ( ; ; )
. Esempi:Operatori di postincremento
- Programma che stampa 50 volte una stringa (
"Repetita iuvant"
).- Programma che prende in input un intero
n
e stampa le primen
potenze di 2.- Programma che stampa il massimo di
n
numeri.- Programma che legge
n
e stampa un quadrato din
righe en
colonne riempito con il carattere'*'
.++
, postdecremento--
e gli operatori+=
,-=
,*=
,/=
,%=
.
Tipi primitivi. Tipi per valori interi:short
,int
,long
,long long
e versioniunsigned
. Tipi per valori in virgola mobile:float
,double
,long double
. Il tipo caratterechar
: codici ASCII. Le corrispondenti specifiche di conversione per le funzioniprintf()
escanf()
:%hd
,%d
,%ld
,%lld
,%hu
,%u
,%lu
,%llu
,%f
,%c
.
Esercizio 3 Scrivere un programma che prende in inputn
numeri in virgola mobile (float
) e stampa la media di tali numeri.
Esercizio 4 Scrivere un programma che legge un interon
e un caratterec
e stampa un triangolo di altezzan
fatto con caratteric
. Ad esempio, sen = 5
ec = 'a'
allora il programma stampa:a aa aaa aaaa aaaaa
Discussione degli esercizi 3 e 4. Comportamento dell'operatore di divisione/
in funzione del tipo degli operandi. Istruzioni iterative:while ()
. Equivalenza con ilfor ( ; ; )
. Esempi:Istruzioni iterative:
- Programma che determina se un numero intero è un numero primo (diverse versioni).
- Programma che prende in input un intero
n
e stampa il numero di cifre din
.do - while ()
. Equivalenza con ilwhile ()
. Esempi:Esercizio 5 Scrivere un programma che prende in input un intero
- Programma che legge una linea di testo (una sequenza di caratteri terminata dal carattere
'\n'
) e conta il numero di vocali e di consonanti.- Programma che legge una linea di testo e conta il numero di parole. Per parola si intende una sequenza di caratteri alfabetici di lunghezza massimale.
n
e stampa la somma delle cifre din
. Ad esempio, sen = 1205
allora il programma stampa8
.
Esercizio 6 Scrivere un programma che legge una linea di testo e stampa la lunghezza della più lunga parola contenuta nella linea di testo. Ad esempio, se la linea di testo è"Qual'e' la parola piu' lunga?
allora il programma stampa6
se invece la linea di testo è"Una parola lunghissima"
, stampa11
.
Discussione degli esercizi 5 e 6. Dichiarazione e inizializzazione di vettori (arrays) (di dimensione costante). Rappresentazione in memoria dei vettori. Esempi:Alcune funzione in
- Programma che legge una linea di testo e stampa la parola più lunga contenuta nella linea.
- Programma che legge una linea di testo e calcola e poi stampa le frequenze dei caratteri stampabili contenuti nella linea di testo. Ad esempio, se la linea di testo è
"Questa frase contiene 48 (quarantotto) caratteri"
, il programma stampa:5 ( 1 ) 1 4 1 8 1 Q 1 a 6 c 2 e 5 f 1 i 2 n 3 o 3 q 1 r 4 s 2 t 7 u 2ctype.h
:isalpha()
,isprint()
.
Esercizio 7 Scrivere un programma che legge una linea di testo e per ogni carattere che è l'iniziale di una parola stampa il numero di parole che iniziano con quel carattere. Ad esempio, se la linea di testo è"Una parola, due parole, tre parole"
, il programma stampa:U 1 p 3 d 1 t 1Esercizio 8 Scrivere un programma che legge un interon
(si può assumere che sia minore di 100) e poi leggen
numeri in virgola mobile (float
) e se ci sono due numeri la cui differenza (in valore assoluto) è minore di0.001
stampa"Ci sono numeri vicini"
, altrimenti stampa"NON ci sono numeri vicini"
. Ad esempio, se i numeri letti sono1.03, 0.056, 1.0305
, allora il programma stampa"Ci sono numeri vicini"
.
Discussione degli esercizi 7 e 8. Discussione sullo stile e la buona struttura del codice: evitare l'uscita "brutale" da un ciclo iterativo. Definizione di funzioni: tipo del valore ritornato, lista dei parametri. Chiamata di una funzione. Il tipovoid
. Esempi: funzione che ritorna la terza potenza di un numero in virgola mobile, funzione che ritorna il massimo di due interi. Passaggio dei parametri per valore e il caso dei vettori. Esempi: funzione che ritorna la somma dei valori di un vettore difloat
, funzione che imposta gli elementi di un vettore ad un valore dato. Discussione sull'importanza di una adeguata decomposizione del codice di un programma in moduli (o funzioni). Principali vantaggi: migliora la leggibilità; riduce la duplicazione del codice; facilita l'individuazione degli errori; facilita le eventuali modifiche e estensioni; rende possibile la riusabilità del codice (librerie). Cenni sulla possibilità di scrivere programmi su più files, prototipo di una funzione. Esempio di una funzione che può essere utile in più programmi: funzione con prototipoint input_linea(char chA[], int maxchars)
che legge dallo standard input una sequenza di caratteri e li scrive nel vettorechA
fino a che non leggeEOF
, il carattere'\n'
o sono stati lettimaxchars
caratteri, ritorna il numero di caratteri letti. Uso della funzionegetchar()
.
Esercizio 9 Scrivere una funzionevoid ruota(char C[], int n, int k)
che ruota i caratteri del vettoreC
dik
posizioni a destra. Ad esempio, se i caratteri nel vettoreC
sono"programma"
(n = 9
) ek = 3
, allora la funzione modifica il vettore in modo che contenga"mmaprogra"
. Scrivere anche un programma che provi la funzione.
Esercizio 10 Scrivere una funzioneint incluso(int A[], int n, int B[], int m)
che ritorna1
se tutti i valori nel vettoreA
(di dimensionen
) sono anche contenuti nel vettoreB
(di dimensionem
), altrimenti ritorna0
. Ad esempio, seA = [2, 1, 3, 2, 1]
eB = [5, 1, 3, 2]
allora la funzione ritorna1
, se inveceB = [5, 3, 2, 0]
allora la funzione ritorna0
. Scrivere anche un programma che provi la funzione.
Discussione degli esercizi 9 e 10. Esempio di un programma che può essere convenientemente decomposto in funzioni: programma che legge dall'input due frazioni positive (nel formatonumeratore/denominatore
) e stampa la somma delle due frazioni, sempre nello stesso formato. Ad esempio, se il programma legge le frazioni8/15
e3/10
, stampa5/6
. Funzioni per il calcolo del massimo comun divisore e per il calcolo del minimo comune multiplo di due interi positivi. Passaggio di parametri per valore e per indirizzo. Tipi puntatore. L'operatore di indirezione*
. Esempio: funzione che prende in input il numeratore e il denominatore di una frazione e la riduce ai minimi termini. Test di correttezza di una funzione tramite la generazione di input pseudo-casuali. Le funzioniint rand()
evoid srand(unsigned seed)
instdlib.h
.
Esercizio 11 Scrivere una funzione,int parola(char chA[], int n, int k, int *plung)
, che ritorna la posizione dellak
-esima parola contenuta nell'arraychA
(di dimensionen
) e restituisce in*plung
la lunghezza di tale parola. Se il numero di parole contenute nell'arraychA
è minore dik
, la funzione ritorna-1
e*plung
è lasciato invariato. Ad esempio, sechA
contiene la sequenza di caratteri"La seconda parola"
(quindin = 17
) ek = 2
, allora la funzione ritorna3
e in*plung
restituisce il valore7
.
Esercizio 12 Scrivere un programma (usando la funzione dell'esercizio precedente ed eventualmente altre funzioni) che legge dall'input due linee di testo e stampa tutte le parole della prima linea che appaiono anche nella seconda. Ad esempio, se le due linee di testo sono"Le cose non sono solo cose"
e"sono tante cose"
, allora il programma stampa:cose sono cose
Discussione degli esercizi 11 e 12. Le stringhe: carattere di terminazione'\0'
, inizializzazione. Principali funzioni della libreria standard (string.h
) per le stringhe:strcpy()
,strlen()
,strcmp()
. Specifica di conversione%s
perscanf()
eprintf()
. Esempi:Esercizio 13 Scrivere una funzione,
- programma che legge
n
stringhe e stampa la minima, rispetto all'ordine lessicografico dato dalla funzionestrcmp()
.- programma che legge due stringhe e determina se sono l'una un anagramma dell'altra (ad es.
"lavagna"
e"valanga"
). Definizione di una funzioneint anagramma(char *s1, char *s2)
che ritornatrue
ofalse
a seconda che le stringhes1
es2
siano l'una un anagramma dell'altra. Uso di una funzioneint occorrenze(char *s, char c)
che ritorna il numero di volte che il caratterec
occorre nella stringas
.char *strpar(char *s, int k, char *par)
, che copia lak
-esima parola contenuta nella stringas
inpar
, come stringa, e ritorna il puntatorepar
. Ses
contiene meno dik
parole, allora la funzione ritornaNULL
. Sostanzialmente,strpar()
è una versione per stringhe della funzioneparola()
dell'esercizio 11.
Esercizio 14 Scrivere un programma (usando le funzionianagramma()
estrpar()
) che prende in input una linea di testo e poi una stringa e stampa tutte le parole contenute nella linea di testo che sono anagrammi della stringa. Ad esempio, se la linea di testo è"Il ratto ha mangiato la torta"
e la stringa è"trota"
, allora il programma stampa:ratto torta
Discussione degli esercizi 13 e 14. Semplici algoritmi di ordinamento: selection-sort e bubble-sort. Iniziata la spiegazione dell'algoritmo della ricerca binaria.
Esercizio 15 Scrivere una funzionevoid ordinastr(char *str)
che ordina i caratteri della stringastr
. Ad esempio, sestr = "ordina char"
allora la funzione modifica la stringastr
così" aacdhinorr"
.
Esercizio 16 Scrivere un programma che mette a confronto le funzioniselectionsort()
ebubblesort()
per ordinare vettori di interi. Misurare i rispettivi tempi di esecuzione variando i vettori da ordinare. Ad esempio, vettori già ordinati, vettori con ordinamento inverso, vettori quasi ordinati (ottenuti facendo qualche scambio in vettori ordinati) e vettori disordinati (ottenuti generando interi pseudo-casuali con la funzionerand()
). Il tempo di esecuzione può essere misurato usando la funzione della libreria standardclock()
intime.h
che ritorna il numero corrente di clocks. Un clock è una unità di misura del tempo che è dipendente dalla piattaforma. La costanteCLOCKS_PER_SEC
(sempre intime.h
) fornisce il numero di clocks per secondo. Così se si vuole misurare il numero di millisecondi dell'esecuzione diselectionsort()
si può scrivere:clock_t start, end; start = clock(); // numero di clocks subito prima della chiamata selectionsort(V, n); end = clock(); // numero di clocks subito dopo la chiamata // tempo di esecuzione in millisecondi double tempoEsecuzione = 1000*(((double)(end - start))/CLOCKS_PER_SEC);Il tipoclock_t
è un tipo intero senza segno definito intime.h
.
Discussione degli esercizi 15 e 16. L'algoritmo della ricerca binaria: implementazione iterativa. Definizione ricorsiva di funzioni: fattoriale e ricerca binaria. Cenni sulla esecuzione di chiamate (ricorsive) di funzioni e sullo stack.
Allocazione dinamica della memoria: confronto con allocazione statica. Principali funzioni della libreria standard (stdlib.h
):malloc()
,free()
erealloc()
. Il tipovoid *
. L'operatoresizeof
. Esempi:Esercizio 17 Scrivere una funzione
- funzione
char *duplicastr(char *str)
che ritorna una copia (allocata dinamicamente) della stringastr
.- funzione
char *inputlinestr()
che ritorna in una stringa allocata dinamicamente la sequenza di caratteri letti dall'input (fino aEOF
o'\n'
). Uso direalloc()
.long long mcd(long long a, long long b)
che ritorna il M.C.D. dia
eb
. La funzione deve implementare in modo ricorsivo l'algoritmo di Euclide per il calcolo del M.C.D.
Esercizio 18 Scrivere una funzionechar *concat(char *s1, char *s2)
che ritorna una nuova stringa che contiene la concatenazione delle stringhes1
es2
. Ad esempio, ses1 = "Prima parte"
es2 = "Seconda parte"
allora la funzione ritorna la stringa"Prima parteSeconda parte"
.
Discussione degli esercizi 17 e 18. Array multidimensionali: inizializzazione e rappresentazione in memoria. Esempi:Array di stringhe: funzione
- funzione
void maxrighe(int nr, int nc, float M[nr][nc], float maxR[])
che ritorna nell'arraymaxR
i valori massimi delle righe della matriceM
(che hanr
righe enc
colonne).- funzione
void magicsquare(int n, int Q[n][n])
che riempe la matricenxn
Q
con un quadrato magico di ordinen
(solo nel caso in cuin
è dispari). La semplice regola per la costruzione di quadrati magici di ordine dispari è descritta qui.
char **wordarray(char *text, int *pwords)
che ritorna un array di stringhe, allocato dinamicamente, che contiene le parole contenute nella stringatext
.
Esercizio 19 Scrivere una funzioneint ismagicsquare(int n, int Q[n][n])
che verifica seQ
è un quadrato magico. Se lo è ritorna la somma magica, altrimenti ritorna0
. La funzione non deve solamente verificare che le somme di tutte le righe, colonne e diagonali coincidono ma anche che tutti gli interi da1
an2
appaiono inQ
.
Esercizio 20 Scrivere una funzioneint *duparray(int V[], int n)
che ritorna una copia dell'arrayV
.
Esercizio 21 Scrivere una funzionevoid sortstrings(char *sA[], int n)
che ordina (tramitestrcmp()
) l'array di stringhesA
.
Simulazione di prova intermedia: esercizi con soluzioni.
Prova intermedia: esercizi con soluzioni.
Aritmetica dei puntatori. Somma puntatore + intero: rappresentazione nella memoria. Sintassi delle parentesi quadre ed espressione equivalente nell'aritmetica dei puntatori. Tipi array e tipi puntatori. Conversione automatica del tipo array nel corrispondente tipo puntatore: le eccezioni dell'operatore di indirizzo & e dell'operatoresizeof
. Array multidimensionali e interpretazione nell'aritmetica dei puntatori delle espressioni con parentesi quadre: puntatori ad array. I tipiT [n]
(array din
elementi di tipoT
),T [n][m]
(array din
array ognuno dim
int
) eT (*)[n]
(puntatore ad array din
int
). Allocazione dinamica di matrici. Esempio,Come si disalloca la matrice allocata tramite la funzione
- funzione
int **allocmatrix(int nr, int nc)
che ritorna l'indirizzo di una matrice di interi, allocata dinamicamente, connr
righe enc
colonne.allocmatrix()
.
Esercizio 22 Scrivere una funzioneint **alloctrimatrix(int n, int val)
che ritorna una matrice triangolare di interi, allocata dinamicamente, riempita con il valoreval
. Ad esempio, sen = 5
eval = 2
la matrice allocata deve essere:2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
Esercizio 23 Scrivere una funzionevoid freetrimatrix(int n, int **M)
che disalloca la matriceM
, precedentemente allocata tramite la funzionealloctrimatrix()
.
Discussione esercizi 22 e 23. Aritmetica dei puntatori: sottrazione puntatore - intero, differenza di puntatori e confronto di puntatori. Esempio: implementazione della funzionevoid *memmove(void *dst, void *src, int count)
che copia il blocco dicount
bytes puntato dasrc
nel blocco puntato dadst
e ritornadst
.
Tipi aggregati:struct
. Inizializzazione distruct
, accesso ai campi (o membri). Rinominare tipi tramitetypedef
. Esempi,struct Carta { char seme; int valore; }
:Esercizio 24 Scrivere una funzione
- funzione
void inizmazzo(Mazzo M)
che inizializza il mazzo di carteM
, doveMazzo
è il tipo dato datypedef Carta Mazzo[52];
- funzione
void stampamazzo(Mazzo M)
che stampa il mazzo di carteM
.void mescolamazzo(Mazzo M, int ns)
che mescola il mazzoM
effettuandons
scambi di coppie di carte (scelte in modo pseudo-casuale tramite la funzionerand()
).
Esercizio 25 Definire unastruct Studente
con campi: matricola, nome, cognome, num_esami. Scrivere una funzioneint cerca(Studente stu[], int n, char *cog)
che ritorna l'indice dello studente con cognome dato dalla stringacog
nell'array diStudente
di dimensionen
. Se non c'è nessun studente con quel cognome, ritorna-1
.
Discussione esercizi 24 e 25. Esempi di struct che contengono altre struct. Assegnamento di struct. L'operatoresizeof
applicato a struct. Puntatori a struct e la sintassi "freccia" per accedere ai campi. Le unioni (union
): definizione e inizializzazione. Ilsizeof
di una union e rappresentazione in memoria. Enumerazioni (enum
). L'istruzione di selezioneswitch - case
e l'operatore condizionale( ? : )
. Esempio: funzione che stampa il valore e il seme di una structCarta
usando enumerazioni eswitch - case
.
Iniziata la discussione di un programma che gestisce (in memoria primaria) un piccolo archivio relativo ai dipendenti di una ipotetica azienda. Il programma dovrà permettere di effettuare almeno le seguenti operazioni: inserimento dei dati di un nuovo dipendente, stampa dei dati relativi a tutti i dipendenti e ricerca di un dipendente in base al cognome. Definizione della struct che rappresenta i dati relativi ad un dipendente:typedef struct { int g, m, a; } Data; typedef enum { IMP, // impiegato DIR, // dirigente DIRSUP // dirigente superiore } Ruolo; // ogni dipendente appartiene ad uno dei ruoli sopra specificati #define MAXL_NOM 20 // massima lunghezza del nome #define MAXL_COG 40 // massima lunghezza del cognome #define MAXL_SEZ 20 // massima lunghezza del nome di una sezione #define MAXL_DIP 30 // massima lunghezza del nome di un dipartimento typedef struct { char nome[MAXL_NOM + 1]; // stringa char cognome[MAXL_COG + 1]; // stringa Data nascita; Ruolo ruolo; union { int livello; // solo per impiegati char sezione[MAXL_SEZ + 1]; // solo per dirigenti (nome della sezione diretta) char dipart[MAXL_DIP + 1]; // solo per dirigenti superiori (nome del dipartimento diretto) } info; } Dipendente;Esercizio 26 Scrivere una funzioneDipendente inputDipendente()
che legge dallo standard input i valori dei campi di una structDipendente
e la ritorna.
Struttura del programma per gestire l'archivio dei dipendenti. Decomposizione del programma in due moduli:Vi è anche un modulo che contiene alcune funzioni di utilità (
- modulo che gestisce la memorizzazione dell'archivio (funzioni:
void open_archivio(), void add_dipendente(Dipendente d), int num_dipendenti(), Dipendente get_dipendente(int i), void close_archivio()
)- modulo che gestisce l'interazione con l'utente (funzioni:
int main(), void inizio(), void aggiungi(), void stampa(), void ricerca(), void fine()
)int input_line(char line[], int maxlen), int input_int(), char input_char()
). Discussione dei vantaggi offerti da una tale decomposizione in moduli. Cenni sulla separazione interfaccia-implementazione. Uso delle direttive#ifndef - #endif
per evitare che il contenuto di un file header (file.h
) possa essere incluso più di una volta nello stesso file. Implementazione del modulo di memorizzazione (tramite un array, allocato dinamicamente). Implementazione dell'operazione che aggiunge un nuovo dipendente all'archivio (funzioneaggiungi()
) e di una funzione che stampa i dati di un singolo dipendente (void stampadip(Dipendente d)
). Uso di puntatori ai campi di una struct.
Esercizio 27 Implementare la funzionevoid stampa()
, usando la funzionestampadip()
e le funzioni del modulo di memorizzazione. La funzione deve stampare i dati di tutti dipendenti presenti nell'archivio.
Esercizio 28 Implementare la funzionevoid ricerca()
, usando la funzionestampadip()
e le funzioni del modulo di memorizzazione. La funzione deve leggere un cognome dallo standard input e cercare nell'archivio un dipendente con quel cognome. Se è presente stampa tutti i dati di quel dipendente, altrimenti stampa"Non trovato"
.
Discussione degli esercizi 27 e 28. Le liste: rappresentazione in memoria, vantaggi e svantaggi rispetto agli array. Operazioni fondamentali sulle liste relativamente a liste di interi:typedef struct Elem { int val; struct Elem *next; } Elem, *List;Implementazione delle funzioni:Implementazione del modulo di memorizzazione del programma che gestisce l'archivio dei dipendenti tramite una lista.
List add_head(List L, int val)
aggiunge un nuovo elemento con valoreval
in testa alla listaL
(L
è il puntatore al primo elemento della lista) e ritorna il puntatore alla lista così modificata.List add_tail(List L, int val)
aggiunge un nuovo elemento con valoreval
in coda alla listaL
e ritorna il puntatore alla lista così modificata.Elem *find(List L, int val)
cerca nella listaL
il primo elemento con valoreval
, se lo trova ritorna il puntatore all'elemento, altrimenti ritornaNULL
.List delete(List L, int val)
elimina dalla listaL
, se presente, il primo elemento con valoreval
e ritorna il puntatore alla lista così modificata.
Esercizio 29 Scrivere una funzioneList insord(List L, int val)
che inserisce un nuovo elemento con valoreval
nella lista ordinata (in senso crescente)L
, mantenendo l'ordinamento. Ritorna il puntatore alla lista dopo l'inserimento. Ad es., seL
è la lista1 -> 3 -> 6 -> 8
eval = 5
allora la funzione modifica la lista così1 -> 3 -> 5 -> 6 -> 8
.
Esercizio 30 Scrivere una funzioneList inverti(List L)
che inverte la listaL
e ritorna il puntatore alla lista invertita. Ad es., seL
è la lista1 -> 2 -> 3 -> 4
allora la funzione la trasforma così4 -> 3 -> 2 -> 1
.
Discussione degli esercizi 29 e 30: versione iterativa e ricorsiva della funzioneList inverti(List L)
. Algoritmo insertion-sort per ordinare una lista di interi. Funzione che disalloca una lista.
Esempio di uso di liste: programma che conta le parole distinte lette dallo standard input. Possibilità di usare la redirezione (operatore di redirezione<
da terminale) per ridirigere lo standard input da file. Il programma usa una lista per mantenere le parole distinte finora trovate durante la lettura dell'input. Per migliorare l'efficienza le parole lette dall'input sono preliminarmente mantenute in un buffer (un array di stringhe) non troppo grande. Quando il buffer diventa pieno, le parole in esso contenute sono riversate nella lista. Per rendere efficiente quest'ultima operazione (che comporta, per ogni parola del buffer, il controllo che non sia già presente nella lista), la lista e il buffer sono mantenuti ordinati. In questo modo, l'operazione di riversamento è eseguita tramite una fusione delle stringhe del buffer con quelle della lista. Decomposizione del programma in funzioni:#define WORDMAXLEN 100 // Massima lunghezza ammessa per le parole #define BUFFERSIZE 150 // Dimensione del buffer delle parole typedef struct WordElem { char * word; // Una stringa (parola) struct WordElem *next; } WordElem, *WordList; /* Legge una parola dallo standard input, la scrive nell'array word e ne ritorna * la lunghezza. Se la parola e' piu' lunga di maxlen, solamente i primi * maxlen caratteri sono scritti nell'array word, gli altri caratteri sono letti * ed ignorati. I caratteri scritti in word sono sempre terminati dal carattere * '\0', percio' l'array word deve avere dimensione almeno maxlen + 1. */ int input_word(char word[], int maxlen); /* Inserisce nel array di stringhe wordBuf, ordinato e contenente n stringhe * (distinte), la stringa w, se non e' gia' presente. L'inserimento mantiene * l'ordinamemnto. Ritorna il numero di stringhe dopo l'inserimento. */ int insert(char *wordBuf[], int n, char *w); /* Fonde le stringhe dell'array wordBuf, contenente n stringhe (parole) ordinate * e distinte, nella lista ordinata di stringhe (parole) L e ritorna il puntatore * alla lista dopo la fusione. La fusione mantiene la lista ordinata. */ WordList merge(WordList L, char *wordBuf[], int n); /* Conta il numero di parole contenute nella list L */ int count(WordList L);Implementazione del main del programma usando le funzioni sopra descritte.
Esercizio 31 Scrivere una funzioneint uguali(WordList L1, WordList L2)
che ritorna1
o0
a seconda che le due listeL1
eL2
siano uguali o meno. Uguali significa che le due liste hanno la stessa lunghezza e elementi in posizioni corrispondenti contengono stringhe uguali.
Esercizio 32 Scrivere una funzioneWordList mergeList(WordList L1, WordList L2)
che ritorna la fusione delle due liste ordinateL1
eL2
. La funzione non deve né creare nuovi elementi né cancellare elementi esistenti. Ad esempio, seL1 = "a" -> "c" -> "hh"
eL2 = "bb" -> "c" -> "m" -> "z"
allora la lista ritornata è"a" -> "bb" -> "c" -> "c" -> "hh" -> "m" -> "z"
.
Discussione degli esercizi 31 e 32. Completata l'implementazione del programma che conta le parole distinte lette dallo standard input: implementazione delle funzioniint input_word(char word[], int maxlen)
,int insert(char *wordBuf[], int n, char *w)
,WordList merge(WordList L, char *wordBuf[], int n)
eint count(WordList L)
. Dai siti Progetto Manuzio e Project Gutenberg si possono scaricare tantissimi libri, italiani e stranieri, in file di testo che possono essere dati in input al programma.
Il main con argomenti:int main(int argc, char *argv[])
. Esempio: programma che prende come parametri una sequenza di numeri interi e ne stampa la somma. La funzionesscanf()
.
Puntatori a funzioni: definizione e spiegazione iniziale.
Esercizio 33 Modificare il programma che conta le parole distinte in modo tale che prenda come parametro (tramite il main) un interok
e stampi lek
parole (distinte) più frequenti del testo letto dallo standard input.
Discussione esercizio 33. Puntatori a funzioni: definizione e uso (operatore&
). Esempi:Esercizio 34 Considerando il tipo:
- La funzione
qsort()
(instdlib.h
) e suo uso per ordinare array diint
e array di stringhe.- Funzione
void apply(List L, void (*op)(Elem *))
che applica la funzioneop()
ad ogni elemento della lista di interiL
.- Uso dei puntatori a funzioni per la gestione di un menu testuale:
typedef void (*OpFunc)(); void menu(char *m[], OpFunc op[], int n)typedef struct { char cognome[40]; //stringa char nome[20]; } Persona;scrivere una funzionevoid sort_pers(Persona P[], int n)
che ordina l'arrayP
(din
elementi) tramite la funzioneqsort()
.
Esercizio 35 Scrivere una funzioneList filtro(List L, int (*f)(Elem *))
che elimina dalla lista di interiL
gli elementip
tali chef(p) ≠ 0
e ritorna il puntatore alla lista modificata.
Discussione esercizi 34 e 35. File ad accesso sequenziale (file di testo) e file ad accesso casuale (file binari). Rappresentazione, da un punto di vista logico, di un file: il cursore e l'effetto delle operazioni di lettura/scrittura su di esso. Il riferimento ad un file aperto: la structFILE
. Le principali funzioni, della libreria standard (stdio.h
), per la manipolazione dei files:fopen()
(modalità di apertura),fclose()
,rewind()
,fgetc()
,fputc()
,fscanf()
,fprintf()
,fgets()
. I riferimenti allo standard input (stdin
) e allo standard output (stdout
). Esempio: programma che prende come argomento del main il nome di un file (di testo) e permette all'utente di stampare a video le linee del file pagina per pagina (uso difopen()
,fgets()
efclose()
).
Esercizio 36 Scrivere un porogramma che prende come argomenti i nomi di due file (di testo), legge tutte le parole contenute nel primo file memorizzandole in un array di stringhe, ordina l'array tramiteqsort()
e scrive nel secondo file le parole distinte (senza ripetizioni) e ordinate, una per linea. Si metta un limite di 100 caratteri sulla lunghezza delle parole.
Suggerimenti: il primo file va aperto in lettura ("r"
), il secondo in scrittura ("w"
), per leggere le parole modificare la funzioneinput_word()
del programma che conta le parole distinte.
Discussione esercizio 36. Implementazione del modulo di memorizzazione del programma che gestisce un archivio di dipendenti tramite file di testo. Funzioni per il posizionamento del cursore dei files aperti:ftell()
,fseek()
e le costantiSEEK_SET
,SEEK_CUR
eSEEK_END
. Differenze tra file binari e file di testo. Cenni sull'uso delle funzioniftell()
efseek()
in un programma che cerca una stringa in un file di testo.
Esercizio 37 Scrivere un funzioneint filenumocc(FILE * f, char *s)
che ritorna il numero di occorrenze della stringas
nel file di testof
.
Esercizio 38 Scrivere un programma che prende come argomenti (del main) i nomi di due file di testo e appende il contenuto del secondo file al primo file. Ad esempio, se il primo file contieneTesto primo file
e il secondo file contieneTesto secondo file
allora il programma modifica il primo file cosìTesto primo fileTesto secondo file
.
Esercizio 39 Scrivere un programma che prende come argomenti (del main) i nomi di due file di testo e scrive nel secondo file una tabella delle frequenze dei caratteri del primo file. Ad esempio, se il primo file contiene "i promessi sposi" (filei_promes.txt
sul sito Progetto Manuzio) allora il programma scrive la seguente tabella nel secondo file:0 0 | 32 217652 | 64 @ 1 | 96 ` 1 | 128 0 | 160 0 | 192 0 | 224 2003 | 1 0 | 33 ! 1497 | 65 A 1298 | 97 a 114953 | 129 0 | 161 0 | 193 0 | 225 1 | 2 0 | 34 " 396 | 66 B 255 | 98 b 9793 | 130 0 | 162 0 | 194 0 | 226 0 | 3 0 | 35 # 0 | 67 C 1119 | 99 c 47033 | 131 0 | 163 0 | 195 0 | 227 0 | 4 0 | 36 $ 0 | 68 D 730 | 100 d 37532 | 132 0 | 164 0 | 196 0 | 228 0 | 5 0 | 37 % 0 | 69 E 1038 | 101 e 120014 | 133 0 | 165 0 | 197 0 | 229 0 | 6 0 | 38 & 0 | 70 F 395 | 102 f 10422 | 134 0 | 166 0 | 198 0 | 230 0 | 7 0 | 39 ' 9958 | 71 G 412 | 103 g 17191 | 135 0 | 167 1 | 199 0 | 231 0 | 8 0 | 40 ( 190 | 72 H 80 | 104 h 13763 | 136 0 | 168 0 | 200 92 | 232 1365 | 9 0 | 41 ) 190 | 73 I 921 | 105 i 95745 | 137 0 | 169 0 | 201 0 | 233 1262 | 10 2990 | 42 * 57 | 74 J 3 | 106 j 20 | 138 0 | 170 0 | 202 0 | 234 0 | 11 0 | 43 + 0 | 75 K 1 | 107 k 1 | 139 0 | 171 0 | 203 0 | 235 0 | 12 0 | 44 , 26324 | 76 L 1199 | 108 l 56023 | 140 0 | 172 0 | 204 0 | 236 1435 | 13 2990 | 45 - 4416 | 77 M 1034 | 109 m 23272 | 141 0 | 173 0 | 205 0 | 237 0 | 14 0 | 46 . 9565 | 78 N 495 | 110 n 74385 | 142 0 | 174 0 | 206 0 | 238 0 | 15 0 | 47 / 19 | 79 O 409 | 111 o 95944 | 143 0 | 175 0 | 207 0 | 239 0 | 16 0 | 48 0 25 | 80 P 737 | 112 p 29741 | 144 0 | 176 0 | 208 0 | 240 0 | 17 0 | 49 1 79 | 81 Q 373 | 113 q 7638 | 145 0 | 177 0 | 209 0 | 241 1 | 18 0 | 50 2 48 | 82 R 916 | 114 r 66912 | 146 0 | 178 0 | 210 0 | 242 2743 | 19 0 | 51 3 32 | 83 S 945 | 115 s 55175 | 147 0 | 179 0 | 211 0 | 243 0 | 20 0 | 52 4 21 | 84 T 406 | 116 t 62265 | 148 0 | 180 0 | 212 0 | 244 0 | 21 0 | 53 5 35 | 85 U 162 | 117 u 34650 | 149 0 | 181 0 | 213 0 | 245 0 | 22 0 | 54 6 35 | 86 V 409 | 118 v 23183 | 150 0 | 182 0 | 214 0 | 246 0 | 23 0 | 55 7 15 | 87 W 4 | 119 w 15 | 151 0 | 183 0 | 215 0 | 247 0 | 24 0 | 56 8 18 | 88 X 62 | 120 x 16 | 152 0 | 184 0 | 216 0 | 248 0 | 25 0 | 57 9 15 | 89 Y 0 | 121 y 8 | 153 0 | 185 0 | 217 0 | 249 1817 | 26 0 | 58 : 2663 | 90 Z 15 | 122 z 7788 | 154 0 | 186 0 | 218 0 | 250 0 | 27 0 | 59 ; 4017 | 91 [ 0 | 123 { 0 | 155 0 | 187 0 | 219 0 | 251 0 | 28 0 | 60 < 0 | 92 \ 0 | 124 | 0 | 156 0 | 188 0 | 220 0 | 252 0 | 29 0 | 61 = 0 | 93 ] 0 | 125 } 0 | 157 0 | 189 0 | 221 0 | 253 0 | 30 0 | 62 > 0 | 94 ^ 0 | 126 ~ 0 | 158 0 | 190 0 | 222 0 | 254 0 | 31 0 | 63 ? 1335 | 95 _ 0 | 127 0 | 159 0 | 191 0 | 223 0 | 255 0 |
Discussione esercizi 37, 38 e 39. Funzioni per leggere e scrivere file binari:fread()
efwrite()
. Implementazione del modulo di memorizzazione del programma che gestisce un archivio di dipendenti tramite file binari.
Descrizione generale delle strutture dati pila (stack) e coda (queue): usi tipici, operazioni fondamentali, implementazioni.
Esercizio 40 Scrivere un programma che prende come argomento il nome di un file e se non esiste lo crea e vi scrive il primo milione di numeri primi (in ordine crescente). Poi permette all'utente di inserire interik
e per ognik
stampa ilk
-esimo numero primo, leggendolo dal file. Il file è binario e i numeri primi sono memorizzati comeint
. Ad esempio, se l'utente inseriscek = 1
il programma stampa2
, sek = 1000
il programma stampa7919
e sek = 1000000
il programma stampa15485863
.
Discussione esercizio 40. Esempio di uso di pile: valutazione di semplici formule booleane. Realizzazione di una piccola libreria per pile di caratteri: separazione interfaccia-implementazione. Implementazione tramite liste. Implementazione di una funzioneint boolformula(char *formula)
, che valuta la formula booleana contenuta nella stringaformula
, usando una pila di caratteri.
Esercizio 41 Modificare la funzioneint boolformula(char *formula)
per implementare una funzioneint mod10formula(char *formula)
che valuta semplici formule nell'aritmetica modulo 10. Tali formule sono formate dai caratteri'('
,')'
,'+'
,'*'
,'0'
,'1'
, ...,'9'
, dove gli operatori'+'
e'*'
sono la somma e la moltiplicazione modulo 10. Ad esempio, la formula3 + (4*(2 + 6 + 9)*(1 + 9) + 6)
ha valore 9.
Esercizi di preparazione alla prova scritta: esercizi con soluzioni.
Simulazione prova scritta: esercizi con soluzioni.
![]() |
![]() |
Questo sito usa cookies, usandolo ne accettate la presenza. (CookiePolicy)
Torna al Dipartimento di Informatica ![]() |
|
![]() |
![]() |