Strumenti Utente

Strumenti Sito


informatica:sol:laboratorio15:esercitazionia:esercitazione1

Esercitazione 1

Esercizi proposti su: puntatori, stringhe, puntatori a funzione, argc-argv, allocazione/deallocazione dinamica, …. Cercare di completare tutti gli esercizi durante le ore di laboratorio e nel caso come homework.

In caso di difficoltà su aspetti del C, discuterne con il docente.

Illustrazione uso gdb

Vediamo come si usa il debugger gdb usando questo codice non funzionante. I comandi del 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 questo programma C (ce ne sono almeno 2):

#include <stdlib.h>
#include <stdio.h>
#define N 32
 
int main() {
    int *A = malloc(N);
    int i=0;
    while(++i<N) {
	A[i] = !(i%2);
    } 
    printf("stampa ...\n"); 
    for(int i=0;i<N;++i) 
	printf("%d ", A[i]);
    printf("\n");
    printf("exiting ...\n");
    free(A);
    return 0; 
}

Copiare il codice precedente in 'debugging.c'. Compilare il codice con l'opzione “-g”, ad esempio:

gcc -std=c99 -Wall -Werror -g debugging.c -o debugging

quindi lanciare l'eseguibile e verificare quali errori produce, poi usando il debugger:

$ gdb ./debugging

è possibile fermare il programma durante la sua esecuzione (ad esempio mettendo un breakpoint all'inizio del 'while' – (gdb) b 8 ), ispezionare le variabili (ad esempio '(gdb) p A[1]', '(gdb) next', etc..

Esercizio 2

Scrivere una funzione “swapPtr” che swappa due puntatori qualsiasi:

void swapPtr(void **ptr1, void **ptr2);

Testare la funzione con un semplice programma che stampi il vaore puntato prima e dopo lo swap.

Esercizio 3

Data una stringa con caratteri minuscoli e maiuscoli, trasformarla in una stringa con tutti i caratteri maiuscoli. NOTE: è possibile utilizzare le funzioni di libreria islower e toupper definite in ctype.h (vedere man 3 islower). Ad esempio usare la stringa:

char str[]="Questa e' una Stringa non tanto Lunga che CONtiene 123 !";

il risultato deve essere:

printf("%s\n", str);
$ QUESTA E' UNA STRINGA NON TANTO LUNGA CHE CONTIENE 123 !

Una variante di questo esercizio è quello di trasformare i caratteri maiuscoli in minuscoli e viceversa.

Esercizio 4

Scrivere un programma che dato un vettore di un certo numero di elementi esegua la somma o il prodotto di tutti gli elementi del vettore a seconda del parametro passato come input al programma. Se l'argomento è '-s' dovrà essere effettuata la somma degli elementi, se l'argomento è '-m' dovrà essere effettuato il prodotto. Scrivere il programma in modo generico utilizzando un puntatore a funzione. Usare il seguente tipo puntatore a funzione:

// tipo puntatore a funzione, prima argomento il puntatore al vettore, secondo argomento la size del vettore
typedef long (*function_t)(long *, size_t); 

Esercizio 5

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 prima[1024] = "prima";
  printf("%s\n", mystrcat(prima, "seconda", "terza lunga", "quarta", "quinta", "ultima!", NULL));
 
  return 0;
}

NOTA: A che cosa serve l'ultimo argomento 'NULL' ?

Esercizio 6

Scrivere un programma che dato un intero A a 32bit (usare i tipi int16_t, int32_t definiti in #include<stdint.h>) calcoli lo 'xor bit a bit' dei 2 byte piu' significativi (quelli di sinistra) con i 2 byte meno significativi. L'operatore di xor bit a bit in C è '^' (es. 0101 ^ 1100 = 1001). Dato A1 contenente A in formato network-byte-order (cioè formato big-endian, utilizzare A1=htonl(A) – vedi man 3 htonl), riordinare esplicitamente i byte di A1 in host-byte-order (cioè formato little-endian per sistemi Intel/AMD based) senza usare la funzione 'ntohl'. Dato il numero in formato esadecimale 0x1234567, i due formati hanno la seguente rappresentazione in memoria:

  high <------------------- low
 ---------------------------------
|  0x01  |  0x23  |  0x45 |  0x67 |    little-endian  
 ---------------------------------
 ---------------------------------
|  0x67  |  0x45  |  0x23 |  0x01 |    big-endian
 ---------------------------------
    3         2        1       0   

Esercizio 7 (binaryTree)

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 8

Scrivere un programma (il cui eseguibile chiameremo 'stringsort') che prende come argumenti da linea di comando un certo numero di stringhe (un numero arbitrario) e le ordina alfanumericamente utilizzando la chiamata di libreria 'qsort' (man 3 qsort). Testare il programma come segue (vedere i manuali dei comandi 'cat' e 'xargs'):
1. preparare un file con il comando cat nel modo seguente:

$> cat << FINE > filediinput.txt
> questa è la prima riga 
> Questa è la seconda più lunga
> AAA questa è quella che deve finire per prima
> jjj questa è prima della prima riga
> zzz questa è ultima....
> FINE

2. lanciare il comando (il simbolo '|' mette in pipeline l'output del comando che precede con l'input del comando che segue) :

$> cat filediinput.txt | xargs -I {} echo \"{}\" | xargs ./stringsort

3. verificare che l'output sia correttamente ordinato.

Che cosa fa il comando 'xargs' come secondo elemento della pipeline ?

Esercizio 9

Non utilizzando la funzioni di libreria 'getopt' (man 3 getopt), scrivere un programma che effettua il parsing della linea di comando (argv) riconoscendo 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
informatica/sol/laboratorio15/esercitazionia/esercitazione1.txt · Ultima modifica: 16/03/2015 alle 16:16 (10 anni fa) da Massimo Torquati

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki