====== 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 [[http://www.gnu.org/software/gdb| gdb]] usando il codice ''usodebug.c'' contenuto in {{:informatica:sol:laboratorio17:esercitazionib:debug.tgz| questo}} tarball. I comandi principali di ''gdb'' da ricordare sono: \\ - run ( r ), break ( b ), step ( s ), next ( n ), print ( p ), set args , backtrace ( bt ), finish, continue ( c ), quit ( q ). ===== Esercizio 1 ===== Usare il debugger ''gdb'' (o per chi vuole la sua interfaccia grafica [[http://www.gnu.org/software/ddd|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* buffer, int buffer_size, char *prima, ...); La funzione prende un buffer, la lunghezza del buffer ed almeno uno stringa. Le stringhe possono essere un numero variabile (>1). La funzione concatena tutte le stringhe nel 'buffer' e ritorna il buffer stesso. ATTENZIONE alla gestione della memoria! Utilizzare il seguente main: #include #include #include #include #define RIALLOCA(buf, newsize) \ char* mystrcat(char *buf, size_t sz, char *first, ...) { } 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 -s -m -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 -s -m -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