Fondamenti di Programmazione (canale E-O) a.a. 2009-2010
Esercizi di preparazione all'esame - 15 gennaio 2010
Esercizio 1
-
Scrivere una funzione
void clean(SList L)
che preso in input il
puntatore L
al primo elemento di una lista ordinata di stringhe,
elimina i duplicati.
La funzione non deve modificare il primo elemento della lista. Gli elementi
della lista hanno il seguente tipo:
typedef struct SElem {
char str[30];
struct SElem *next;
} SElem, *SList;
La memoria degli elementi eliminati deve essere rilasciata. Ad esempio, se la
lista è "BLUE" -> "BLUE" -> "GREEN" -> "RED" -> "RED" -> "YELLOW"
allora la funzione la modifica così:
"BLUE" -> "GREEN" -> "RED" -> "YELLOW"
.
Esercizio 2
-
Scrivere una funzione
void invfile(char *nameF, char *newF)
che legge il file
di tipo testo il cui nome è nella stringa nameF
, contenente una sequenza di
numeri interi separati da spazi, e crea un nuovo file di testo, con nome dato
dalla stringa newF
, e vi scrive la sequenza inversa. Ad esempio, se il file
nameF
contiene la sequenza 3 7 -2 15
allora il nuovo file
creato dalla funzione deve contenere 15 -2 7 3
.
Esercizio 3
-
Scrivere una funzione
int **table(int n, int (*f)(int, int))
che ritorna una
matrice quadrata di dimensione n
di interi, allocata dinamicamente, riempita
con i valori dati dalla funzione f
(l'elemento (i, j)
della
matrice ha valore dato da f(i, j)
, per 0 <= i, j < n
).
Gli elementi della matrice ritornata si devono poter accedere tramite la sintassi
delle parentesi quadre. Ad esempio, se n = 5
e la funzione f
è la funzione che ritorna il prodotto dei due interi in input, allora la
chiamata table(5, f)
ritorna la seguente matrice:
0 0 0 0 0
0 1 2 3 4
0 2 4 6 8
0 3 6 9 12
0 4 8 12 16
Esercizio 4
-
Data una sequenza di numeri diciamo che un numero x della sequenza è un
massimo locale se sia il numero che precede x che quello che lo
segue sono strettamente minori di x (né il primo né l'ultimo
numero della sequenza può essere un massimo locale). Scrivere una funzione che
presa in input una lista di numeri restituisce un vettore contenente i massimi locali
della lista (nell'ordine in cui appaiono nella lista). Il tipo degli elementi della lista
è il seguente:
typedef struct Num {
float n;
struct Num *next;
} Num, *NList;
Il prototipo della funzione è float *localMax(NList L, int *pcount)
.
In *pcount
restituisce la dimensione del vettore ritornato (che deve
essere allocato dinamicamente). Il vettore non deve essere sovradimensionato. Ad esempio,
se la lista è 12 -> 3.5 -> 7.1 -> 4 -> 3 -> 2 -> 5.2 -> 1 -> 8 -> 8
allora la funzione ritorna il vettore [7.1, 5.2]
e in *pcount
restituisce 2
.
Esercizio 5
-
Si consideri il seguente tipo:
typedef struct {
long task;
int h; //ore: 0 - 23
int m; //minuti: 0 - 59
int s; //secondi: 0 - 59
} TaskRec;
Scrivere una funzione int updateTasks(char *taskF, int hh, int mm, int ss)
che preso in input il nome taskF
di un file binario che contiene una sequenza di
record di tipo TaskRec
elimina da esso tutti i record il cui orario (dato dai
campi h
, m
ed s
) è antecedente
all'orario dato da hh
, mm
ed ss
(assumendo che
tutti gli orari si riferiscano allo stesso giorno). La funzione ritorna il
numero di record nel file aggiornato. Eliminare un record significa che gli
eventuali record che vengono dopo nel file devono essere "spostati" per chiudere
il "buco" lasciato dal record eliminato. Ad esempio, se inizialmente il file
taskF
contiene la sequenza di record:
{1234, 2, 15, 23}, {2345, 7, 30, 15}, {1238, 7, 30, 11}, {2351, 13, 24, 53}
allora la chiamata updateTask(taskF, 7, 30, 15)
ritorna 2
e
la sequenza contenuta nel file diventa: {2345, 7, 30, 15}, {2351, 13, 24, 53}
.
Esercizio 6
-
Si consideri il seguente tipo:
typedef struct Elem {
char * str; // stringa allocata dinamicamente
struct Elem *next;
} Elem, *List;
Scrivere una funzione List minstr(List L, int (*cmp)(const char *, const char *))
che elimina dalla lista di stringhe L
la stringa che risulta essere minima
rispetto alla relazione d'ordine data dalla funzione cmp()
. La funzione
cmp(s1, s2)
ritorna -1
se s1 < s2
,
0
se s1 = s2
e 1
se s1 > s2
.
La funzione minstr()
deve ritornare il puntatore alla lista modificata.
Ad esempio, se la lista L
è
"verde" -> "giallo" -> "rosso" -> "blu" -> "rosso"
allora la chiamata
minstr(L, strcmp)
modifica la lista così:
"verde" -> "giallo" -> "rosso" -> "rosso"
.
Esercizio 7
-
Scrivere una funzione che presa in input una lista di stringhe crea una stringa
uguale alla concatenazione delle stringhe della lista. Il tipo degli
elementi della lista è il seguente:
typedef struct SElem {
char * str;
struct SElem *next;
} SElem;
Il prototipo della funzione è char *listToStr(SElem *)
.
Ovviamente la stringa ritornata deve essere allocata dinamicamente. Ad esempio,
se la lista è "List" -> "a di es" -> "" -> "e" -> "mpio"
allora la funzione deve restituire la stringa "Lista di esempio"
.
Esercizio 8
-
Si considerino i seguenti tipi:
typedef struct {
short str; //1 se e' valido il campo s, 0 se e' valido il campo n
union {
char s[101]; //se valido contiene una stringa di lunghezza <= 100
int n; //se valido contiene un numero
} val;
} Rec;
typedef struct Elem {
char * string; // stringa allocata dinamicamente
struct Elem *next;
} Elem, *List;
Scrivere una funzione List updateList(List L, char *nameF)
che presa in input
una lista di stringhe ordinata L
vi inserisce, mantenendo la lista ordinata,
le stringhe contenute nel file binario il cui nome è nella stringa
nameF
e che
contiene una sequenza di record di tipo Rec
. La funzione non deve inserire
stringhe che sono già presenti nella lista e l'ordinamento delle stringhe è
quello dato dalla funzione della libreria standard strcmp()
. Siccome la
lunghezza media delle stringhe nel file è molto minore di 100, l'allocazione
delle stringhe nella lista non deve sprecare memoria. La funzione ritorna il
puntatore al primo elemento della lista aggiornata. La lista di input può anche
essere vuota (L = NULL
). Se la lista è
"cane" -> "gatto" -> "lupo"
e il file
contiene {1, "leone"}, {0, 13}, {1, "cane"}, {1, "leone"}, {1, "aquila"}
allora
la funzione ritorna la lista
"aquila" -> "cane" -> "gatto" -> "leone" -> "lupo"
.
#include <string.h>
#include <stdlib.h>
typedef struct SElem {
char str[30];
struct SElem *next;
} SElem, *SList;
void clean(SList L) {
if (L == NULL || L->next == NULL)
return;
SElem *e = L;
do {
if (strcmp(e->str, e->next->str) == 0) {
SElem *p = e->next;
e->next = p->next;
free(p);
} else e = e->next;
} while (e->next != NULL);
}
#include <stdio.h>
void invfile(char *nameF, char *newF) {
FILE *f = fopen(nameF, "r");
int n, lenF = 0;
while (fscanf(f, "%d", &n) == 1) lenF++;
int k = 0, v[lenF];
rewind(f);
while (fscanf(f, "%d", &(v[k])) == 1) k++;
fclose(f);
FILE *nF = fopen(newF, "w");
for (k = lenF - 1; k >= 0; k--)
fprintf(nF, "%d ", v[k]);
fclose(nF);
}
#include <stdlib.h>
int **table(int n, int (*f)(int, int)) {
int **M = malloc(n*sizeof(int *));
int i, j;
for (i = 0 ; i < n ; i++)
M[i] = malloc(n*sizeof(int));
for (i = 0 ; i < n ; i++) {
for (j = 0 ; j < n ; j++)
M[i][j] = f(i, j);
}
return M;
}
#include <stdlib.h>
typedef struct Num {
float n;
struct Num *next;
} Num, *NList;
Num *firstMax(Num *p) {
if (p == NULL || p->next == NULL) return NULL;
else {
float prec = p->n;
p = p->next;
while (p->next != NULL && !(p->n > prec && p->n > p->next->n)) {
prec = p->n;
p = p->next;
}
return (p->next != NULL ? p : NULL);
}
}
float *localMax(NList L, int *pcount) {
float *maxArray = NULL;
int maxCount = 0;
Num *e = L;
while ((e = firstMax(e)) != NULL) {
maxArray = realloc(maxArray, (maxCount + 1)*sizeof(float));
maxArray[maxCount++] = e->n;
}
*pcount = maxCount;
return maxArray;
}
#include <stdio.h>
typedef struct {
long task;
int h;
int m;
int s;
} TaskRec;
int ant(int h, int m, int s, int hh, int mm, int ss) {
if (h < hh) return 1;
if (h == hh && m < mm) return 1;
if (h == hh && m == mm && s < ss) return 1;
return 0;
}
int updateTasks(char *taskF, int hh, int mm, int ss) {
FILE *f = fopen(taskF, "r+b");
int nc = 0, posLast = 0, posNext = 0;
TaskRec rec;
while (fread(&rec, sizeof(rec), 1, f) == 1) {
if (!ant(rec.h, rec.m, rec.s, hh, mm, ss)) {
fseek(f, posLast, SEEK_SET);
fwrite(&rec, sizeof(rec), 1, f);
posLast += sizeof(rec);
nc++;
}
posNext += sizeof (rec);
fseek(f, posNext, SEEK_SET);
}
fclose(f);
return nc;
}
#include <stdlib.h>
typedef struct Elem {
char * str;
struct Elem *next;
} Elem, *List;
List minstr(List L, int (*cmp)(const char *, const char *)) {
if (L == NULL) return NULL;
Elem *min = L, *curr = L->next;
while (curr != NULL) {
if (cmp(curr->str, min->str) < 0)
min = curr;
curr = curr->next;
}
Elem *prev = NULL;
curr = L;
while (curr != min) {
prev = curr;
curr = curr->next;
}
if (prev == NULL) L = L->next;
else prev->next = min->next;
free(min->str);
free(min);
return L;
}
#include <stdlib.h>
#include <string.h>
typedef struct SElem {
char * str;
struct SElem *next;
} SElem;
char *listToStr(SElem *L) {
char *str;
const SElem *p = L;
long len = 0;
while (p != NULL) {
len += strlen(p->str);
p = p->next;
}
str = malloc(len + 1);
str[0] = '\0';
p = L;
while (p != NULL) {
strcat(str, p->str);
p = p->next;
}
return str;
}
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct {
short str;
union {
char s[101];
int n;
} val;
} Rec;
typedef struct Elem {
char * string;
struct Elem *next;
} Elem, *List;
List insOrd(List L, const char *str)
{
Elem **prec = &L;
while (*prec != NULL && strcmp(str, (*prec)->string) > 0)
prec = &((*prec)->next);
if (*prec == NULL || strcmp(str, (*prec)->string) != 0) {
Elem *new = malloc(sizeof(Elem));
new->string = malloc(strlen(str) + 1);
strcpy(new->string, str);
new->next = *prec;
*prec = new;
}
return L;
}
List updateList(List L, char *nameF)
{
FILE *f = fopen(nameF, "rb");
Rec r;
while (fread(&r, sizeof(Rec), 1, f) == 1)
if (r.str == 1)
L = insOrd(L, r.val.s);
fclose(f);
return L;
}