Questa è una vecchia versione del documento!
Indice
Esercitazione 1
Illustrazione dei principali comandi emacs. Cenni a vi. Illustrazione dell'uso del debugger gdb su un semplice programma. Esercizio sul debugger gdb.
Illustrazione uso gdb
Vediamo come si usa il debugger gdb usando il codice usodebug.c
contenuto in questo tarball. I comandi principali di gdb
da ricordare sono:
- run ( r ), break <file:linea> ( b ), step ( s ), next ( n ), print <variabile> ( p ), set args <argomenti>, backtrace ( bt ), finish, continue ( c ), quit ( q ).
Esercizio 1
Usare il debugger gdb
(o per chi vuole la sua interfaccia grafica ddd ) per trovare gli errori in findbug.c
(nello stesso tarball precedente) e correggerli.
Compilare il codice nel seguente modo (ATTENZIONE all'opzione-g
che abilita le informazioni di debugging):
gcc -std=c99 -g findbug.c -o findbug
quindi lanciare l'eseguibile e verificare quali errori produce, quindi, usando il debugger:
$ gdb ./findbug
inserire un breakpoint nel main (b
main) ed eseguire il programma (r
) step-by-step (n
o s
). Identificato l'errore e modificare il programma opportunamente.
Trovare il bug nel file findbug2.c
(nello stesso tarball)
Esercizio 2
Scrivere un programma C che prende in ingresso 2 interi e 2 stringhe. Stampare a video tutta la lista degli argomenti (argv) e tutte le variabili d'ambiente del programma (envp). Ricordare che una possibile segnatura della funzione main e':
int main(int argc, char *argv[], char *envp[]);
Esercizio 3
Scrivere una funzione 'mystrcat' con la seguente segnatura:
const char *mystrcat(char *prima, ...);
che prenda un numero di stringhe variabili e che concateni tutte le stringhe alla 'prima' con lo stesso comportamento della funzione di libreria strcat
(man 3 strcat).
Utilizzare il seguente main:
int main() { char *buffer=NULL; RIALLOCA(buffer, 16); // macro che effettua l'allocazione buffer[0]='\0'; buffer = mystrcat(buffer, 16, "prima stringa", "seconda", "terza molto molto molto lunga", "quarta", "quinta lunga", "ultima!",NULL); printf("%s\n", buffer); free(buffer); return 0; }
NOTA: Che cosa puo' succedere al programma se invece di
printf("%s\n", buffer);
si fosse scritto:
printf("%s\n", mystrcat(buffer, 16, "prima stringa", "seconda", "terza molto molto molto lunga", "quarta", "quinta lunga", "ultima!",NULL));
Per chi ha bisogno di prendere dimestichezza con il C (homeworks)
Esercizio 4
Scrivere un programma che, dato un array di N elementi interi, costruisca un albero binario di ricerca (cioè per ogni nodo dell'albero, l'elemento del nodo è maggiore di tutti gli elementi del sottoalbero di sinistra e minore o uguale di tutti gli elementi del sottoalbero di destra). Implementare le seguenti funzioni:
struct node_t *buildTree(long elem, struct node_t *t); // costruisce l'albero e restituisce il nodo radice long getMin(struct node_t *root); // restituisce il valore minimo long getMax(struct node_t *root); // restituisce il valore massimo void printInOrder(struct node_t *root); // stampa gli elementi in modo ordinato void deleteTree(struct node_t *root); // cancella tutti i nodi dell'albero
Definire il tipo 'struct node_t' opportunamente. Implementare tutte le funzioni usando la ricorsione.
Esercizio 5
Non utilizzando la funzioni di libreria 'getopt' (man 3 getopt), scrivere un programma che effettua il parsing della linea di comando e che riconosce le seguenti opzioni:
-n <numero> -s <stringa> -m <altro-numero> -h.
Il programma dovrà stampare le opzioni riconosciute con il relativo argomento. L'opzione -h non ha argomento e corrisponde al messaggio di help (program usage). Se e' presente l'opzione -h dovra' essere stampato solo il messaggio di usage cioè:
nome-programma -n <numero> -s <stringa> -m <numero> -h
Se ci sono opzioni non riconosciute queste dovranno essere stampate a video con il messaggio “opzione X non riconosciuta”. Per convertire le stringhe in interi usare la funzione di libreria atoi (vedere man 3 atoi) o meglio ancora la funzione strtol (vedere man strtol). Testare il programma con i seguenti casi (supponiamo che l'eseguibile si chiami cmdlineparsing):
cmdlineparsing -n 10 -m 11 -s 'ciao mondo' cmdlineparsing -n 10 -h // deve stampare il messaggio di usage cmdlineparsing -n 10 -k 12 // k e' una opzione non riconosciuta cmdlineparsing ----n 10 -s-s 'ciao mondo' // deve stampare -n: 10 e -s: -s cmdlineparsing -n10 -m11 -s'ciao mondo' // deve stampare gli argomenti come nel primo caso cmdlineparsing -n -m 11 // deve stampare un messaggio di errore per -n