Indice
Esercitazione 1
Dove si richiama il C sequenziale: in particolarere puntatori, strutture ricorsive, puntatori a funzione. Poi si introduce con un esempio il concetto di libreria (che verra' approfondito nelle lezioni di teoria) e si fa la conoscenza con il debugger.
Esercizio 1: sul debugging
Usare il debugger ddd per trovare cosa non va nel seguente programma C:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <time.h> #define N 5 int main(void) { int a[N]; int i; srand(time(NULL)); i=0; while (i<N) { a[++i]=rand()%2; printf("iterazione %d\n",i); } printf("exiting ...\n"); }
in pratica il codice, salvato in “file.c” compilato con
gcc -Wall -pedantic -o ese file.c
ed eseguito con
$ ./ese
va inspiegabilmente in ciclo all'interno del ciclo. Per eseguire in modalita' interattiva di debugging:
- Compilare con opzione “-g”, ad esempio
gcc -Wall -pedantic -g -o ese file.c
- lanciare l'eseguibile usando il debugger come in
$ ddd ./ese
a questo punto e' possibile fermare il programma durante la sua esecuzione, ispezionare le variabili etc..
Elaborazione: Per i solutori piu' che abili, provare a trovare cosa non va nei due programmi C nei due programmi in esempi.tar
Esercizio 2: liste concatenate di interi
Implementare in C le seguenti funzioni che lavorano su liste concatenate di interi di tipo
typedef struct nodo { int valore; struct nodo * next; } nodo; typedef nodo * lista;
e definire le seguenti funzioni che operano sulla lista
/** crea una lista vuota \retval NULL il puntatore alla lista vuota */ lista newList (void); /** dealloca la lista \param l la lista */ void freeList (lista l); /** iserisce n nella lista l creando un nuovo nodo \param l la lista \param n elemento da inserire \retval p puntatore alla nuova lista se l'allocazione ha avuto successo \retval NULL in caso di errore */ lista insertList (lista l, int n); /** cancella n dalla lista (se c'e') \param l la lista \param n elemento da cancellare \retval p puntatore alla nuova lista */ lista removeList (lista l, int n);
Testare il funzionamento delle funzioni implementate con un opportuno main()
.
Esercizio 3: map e reduce su liste
Usando le liste dell'esercizio 1 implementare le seguenti funzioni:
/** trasforma una lista applicando ad ogni elemento la funzione f \param l la lista \param f la funzione da mappare */ void mapList (int (*f) (int), lista l); /** combina gli elementi della lista l usando un operatore binario associativo \param l la lsita \param f l'operatore binario \param en l'elemento neutro di f \return la 'somma' degli elementi di l secondo f (l1 f l2 f ... f lN f en) */ int reduceList(int (*f) (int,int), int en, lista l);
Testare il risultato con un opportuno main.
Esercizio 4: Libreria di liste
Realizzare una libreria che fornisce le operazioni su liste implementate negli esercizi 1 e 2.
In C tipicamente per realizzare una libreria si difinisce un file .h
con i prototipi ed i tipi messi a disposizione dalla libreria e si fornisce il codice in un opportuno file di libreria .a
.
Nel nostro caso l'header si chiamera' lista.h
e la libreria si chiamera' libList.a
.
Procedere nel modo seguente:
- Definire un file
lista.h
che contiene i tipi ed i prototipi delle funzioni implementate negli esercizi 1 e 2. - Definire un file
lista.c
che contiene il codice che implementa le funzioni. - Generare il modulo oggetto
lista.o
da inserire nella libreria con il comandogcc
come segue
$ gcc -Wall -pedantic -c lista.c
- Creare la libreria con i lcomando
ar
come segue
$ ar -r libList.a lista.o
Quando la creazione e' andata a buon fine creare un file main.c
che contenga uno dei main di test sviluppati negli esercizi precedenti e compilarlo utilizzando la libreria. In particolare :
- il main di test dovra' includere il file
lista.h
- in fase di compilazione utilizzare la libreria sviluppata con
$ gcc -Wall -pedantic main.c -lList -L.
dove l'pzione -l
indica il nome della libreria da usare in fase di linking e l'opzione -L
specifica la directory dove cercarla (oltre alle directory standard tipo /usr/lib
).
.