Sei sulla pagina 1di 17

2

I file
 File: sequenza di byte a cui il Sistema
Operativo dà un nome ed una collocazione sul
I file dispositivo di memoria di massa (es. disco)
 Può essere paragonato ad una lunga stringa
 Uno stream è un generico flusso di caratteri
Ver. 2.4  Un file può essere una sorgente di stream
(anche la tastiera è una sorgente di stream)
 Un file può essere una destinazione di stream
(anche il video è una destinazione di stream)
2 3 3 1 . 1 9 C I A O \0
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...

© 2010 - Claudio Fornaro - Corso di programmazione in C

3 4

I file Classificazione per accesso


 I byte di un file sono idealmente raggruppati  Per accedere ad uno specifico record è
in blocchi detti record o campi (field) necessario posizionarsi al byte da dove inizia
 Un record è un blocco di byte che costituisce  File ad accesso sequenziale
un oggetto (numero, stringa, struttura, etc.)  hanno record di lunghezza variabile
 per accedere al record numero n bisogna leggere
2 3 3 1 . 1 9 C I A O \0 tutti i precedenti n -1 record per determinare il
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...
byte da dove esso inizia
 Ogni lettura/scrittura legge/scrive un record  File ad accesso diretto (casuale, random)
 Tutte le funzioni e le costanti che riguardano i  hanno record di lunghezza fissa
file sono dichiarate/definite in <stdio.h>  la lunghezza L del record viene decisa dal
programmatore file per file
 per accedere al record numero n si determina il
byte da dove esso inizia con il calcolo: n *L
5 6

Classificazione per contenuto File e stream


 File di testo  Dal punto di vista del linguaggio C, non c’è
 Sono sequenze di caratteri organizzati in righe differenza tra leggere da un file o dalla
 Ogni riga è terminata da un ritorno a capo tastiera, o tra scrivere su un file o sul video:
 Il file può terminare con un carattere di fine file sono in ogni caso degli stream di caratteri
 Le funzioni di I/O per stringhe e caratteri gestiscono  L’unica differenza sta nella necessità di
il carattere '\n' come generico ritorno a capo indicare alle funzioni di I/O lo stream da
 File binari utilizzare (mentre per tastiera e video non
 Sono sequenze “grezze” di byte: nessun carattere serve indicarlo)
né sequenza di caratteri viene interpretata in modo
speciale (fine riga, fine file)
 In queste slide ci occupiamo solo di file di
testo ad accesso sequenziale

7 8

Ritorno a capo nei file di testo La costante EOF


 A seconda del sistema operativo utilizzato, il  EOF (acronimo di End Of File) è una costante
ritorno a capo nei file di testo è in realtà simbolica di tipo int definita da una #define
costituito da una sequenza di uno o più car.: in <stdio.h> e di solito pari al valore –1
 MS-DOS/Win: CR+LF (codici ASCII 13 e 10: \r\n)  Viene restituita da alcune funzioni di I/O per
 Unix/Linux: LF (codice 10: \n) segnalare il raggiungimento della fine del file
 Le funzioni di I/O su file di testo considerano il (alcune la usano anche come generica
carattere ‘\n’ come un generico ritorno a capo, segnalazione di errore)
indipendentemente dalla sequenza di caratteri  Il valore numerico di EOF (–1) NON
effettivamente utilizzata dal S.O. in uso: corrisponde al codice ASCII del carattere di
 in input la sequenza di ritorno a capo propria del fine file eventualmente collocato alla fine di un
S.O. in uso viene trasformata in ‘\n’ file di testo (si tratta del carattere con codice
 in output il carattere ‘\n’ viene sostituito con la ASCII 26 = CTRL-Z in DOS/Windows, del
sequenza propria del sistema operativo in uso carattere 4 = CTRL-D in UNIX/Linux)
9 10

Il tipo FILE Il tipo FILE


 Per utilizzare un file è necessario che il  La struttura dati FILE contiene le informazioni
sistema memorizzi una serie di informazioni relative al file, tra queste un campo detto
relative al file stesso offset (o file position pointer ) che memorizza
 Viene usata una speciale struttura dati il punto in cui la lettura o scrittura è arrivata
(struct) che ha tipo FILE (in maiuscolo) (indica il numero progressivo del prossimo
 Si definisce una variabile di tipo puntatore a byte da leggere o scrivere, calcolato rispetto al
FILE detta file pointer per memorizzare primo byte del file che ha offset=0)
l’indirizzo della struttura FILE associata al file  Esempio per file in lettura
FILE *variabile;
2 3 3 1 . 1 9 C I A O \0
 FILE *fp; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...

letti Il valore di offset è 10

11 12

Apertura di un file Apertura di un file


 Per utilizzare un file bisogna informare il  Modi di apertura semplice per file di testo:
Sistema Operativo che lo si vuole utilizzare e "r" – sola lettura (read), il file deve già esistere
per quale scopo (lettura o scrittura), questa "w" – sola scrittura (write), crea vuoto il file da
operazione è detta apertura del file scrivere; se esiste già, lo elimina e lo ricrea
 La funzione fopen apre un file, crea e riempie nuovo (quindi se ne perde il contenuto)
la struttura FILE da associare ad esso "a" – sola scrittura (append), se non esiste viene
fp=fopen(nome, modo);
creato nuovo e vuoto, se invece esiste NON
 nome è una stringa (costante o variabile) viene cancellato e i dati vengono aggiunti al
contenente il nome del file e l’eventuale fondo di quelli già presenti
percorso, la dimensione massima di tale
stringa può essere FILENAME_MAX (costante  Le modalità "r+", "w+", "a+" sono dette
definita in <stdio.h>) di aggiornamento e permettono di leggere e
 modo è una stringa indicante la modalità di scrivere lo stesso file (si veda più avanti)
apertura del file (lettura o scrittura)
13 14

Apertura di un file Apertura di un file


 fopen restituisce NULL se non riesce ad  E’ possibile aprire contemporaneamente più
aprire il file (più precisamente, fopen file o anche lo stesso file sia con lo stesso
restituisce il puntatore alla struttura FILE modo sia in modi diversi, ma bisogna fare
corrispondente al file aperto) attenzione alla bufferizzazione dei file in
 Bisogna verificare sempre il valore di fopen: output (bisogna fare il flush dei buffer di
 un file in input potrebbe non esistere (o il percorso output, vedere più avanti)
è sbagliato)
 un file in output potrebbe non poter essere creato
(ad es. si trova su un disco o su una chiavetta USB
protetta dalla scrittura o il file da scrivere esiste già
ed è protetto dalla cancellazione – read only)

15 16

Apertura di un file Apertura di un file


 Lo schema tipico di apertura del file è:  Se il nome del file è noto a priori, lo si può
printf("File da aprire: "); certamente indicare nella fopen:
gets(miofile); if ((fp=fopen("file.txt","r"))==NULL)
if ((fp=fopen(miofile,"r"))==NULL) {
{ fprintf(stderr, "Errore fopen\n");
fprintf(stderr, "Errore fopen\n"); return EXIT_FAILURE;
}
return EXIT_FAILURE;
 Nel caso si indichi il percorso, si ricordi che nei
}
sistemi operativi Windows è necessario separare le
Notare le parentesi sottolineate: permettono di parti per mezzo di un carattere backslash \ e che
assegnare prima il valore restituito dalla per inserire questo nelle stringhe costanti è
necessario raddoppiarlo (il primo fa da escape):
fopen a fp e poi verificare se il valore di fp è "C:\\documenti\\file.txt"
NULL  Si ricordi che quando il backslash viene introdotto
dall’utente, non lo si deve invece raddoppiare
17 18

Chiusura di un file Scrittura in un file di testo


 Informa il Sistema Operativo che è terminato  Ogni scrittura aggiunge caratteri in fondo al file
l’utilizzo di un certo file (l’offset indica il primo carattere dopo l’ultimo
scritto precedentemente)
 fclose(fp);
 Le funzioni di output su file hanno lo stesso
 Libera le risorse di sistema legate a quel file comportamento di quelle di output su video,
 E' automatica al termine del programma salvo l’indicazione del file pointer
 fprintf(fp,stringaFormato,listaEspressioni);
 Nel caso di file di output, fa il flush dei buffer vedere printf
(vedere più avanti)  fputc(c, fp);
manda il carattere c nel file fp; dà EOF in caso
di errore; se c è \n, lo converte opportunam.
 fputs(str, fp);
come puts, salvo che non aggiunge un '\n'
al fondo; dà NULL in caso di errore

19 20

Buffer di output Lettura da un file di testo


 Per efficienza, normalmente i dati diretti a file  I caratteri vengono automaticamente prelevati
di output vengono temporaneamente dal file man mano che sono richiesti dalle
accumulati in memoria e scritti sul disco solo funzioni di input (e l’offset avanza)
quando i buffer sono pieni  Quando le funzioni leggono i caratteri di un
 Questa porzione di memoria è detta buffer file, cercano di leggerne quanti più è possibile
 Lo svuotamento dei buffer è detto flush a seconda del tipo di valore richiesto (ad es. se
 Il programmatore può chiedere lo devono leggere un valore intero la lettura
svuotamento del buffer associato a fp con: termina al primo carattere non-cifra)
fflush(fp);  Ogni lettura inizia dal carattere successivo a
mentre per svuotare i buffer di tutti gli stream quello dove era terminata la precedente lettura
aperti in output si può usare:  Le funzioni di input da file hanno lo stesso
fflush(NULL); comportamento di quelle di input da tastiera,
salvo l’indicazione del file pointer
21 22

Lettura da un file di testo Lettura da un file di testo


 fscanf(fp, stringaFormato, listaVariabili);  fgets(str, n, fp);
dà il numero di elementi letti da fp, EOF in caso legge una riga intera da fp (fino al '\n'
di errore e fine file, vedere scanf incluso) e la mette in str (compreso '\n');
 x = fgetc(fp); legge fino a n-1 caratteri: se nel file la riga è
legge un carattere da fp e lo mette in x (che più lunga gli altri caratteri restano per la lettura
deve essere un int); dà EOF in caso di errore successiva; dà NULL in caso di errore e fine file
o fine file; dà '\n' dopo aver letto tutta la
sequenza di caratteri che nel S.O. in uso
costituiscono il ritorno a capo

23 24

Buffer di input Perché la fgetc richiede un int?


 Non esiste una funzione standard C89 che  La funzione fgetc preleva un singolo
permetta di svuotare i buffer di stream di input carattere da uno stream e:
 Lo standard C89 non prevede che la funzione  deve restituire il codice ASCII del carattere letto
fflush sia applicata a stream di input  deve comunicare l’eventuale raggiungimento della
fine del file
 Alcuni compilatori permettono di svuotare i
buffer di input utilizzando fflush, ma se si  Poiché essa produce un solo valore, questo
vuole un programma standard C89 non la si deve veicolare entrambe le informazioni
usi e si trovino soluzioni alternative che non  I possibili diversi valori restituiti sono 257:
richiedono flush (non è detto esistano sempre)  le 256 combinazioni degli 8 bit di un char
 un altro valore (EOF) per segnalare la fine del file
quindi gli 8 bit di un char non bastano e ci
vuole un tipo intero con almeno 9 bit: un int
25 26

Perché la fgetc richiede un int? Ciclo di lettura da file


 Esempio  Bisogna sempre controllare se si è giunti alla
Si supponga che un int abbia 16 bit e la fine del file
costante EOF sia definita –1, il valore int  Per determinare se si è raggiunta la fine del file
prodotto dalla fgetc:
(ossia non c’ è più niente da leggere):
 nel caso venga letto correttamente un carattere (no
 si controlla il valore restituito dalle funzioni di input
fine file) è il codice ASCII di quel carattere
(es. ‘A’ = 01000001) preceduto da un byte a 0: dopo la lettura (restituiscono la segnalazione di fine
file quando la lettura di un record fallisce, NON
00000000 01000001 appena letto l’ultimo valore)
e con un cast a char si elimina la parte di sinistra  si usa la funzione feof prima di fare la lettura
 nel caso si sia trovata la fine del file è –1 su 2 byte:
11111111 11111111
N.B. –1 in complemento a 2 è composto da tutti 1

27 28

Ciclo di lettura da file Ciclo di lettura da file


 Esempio corretto di lettura da file (schema  Esempio errato:
tipico di lettura): while (fscanf(fp,"%d%d",&x,&y)!=EOF)
while (fscanf(fp,"%d", &x) != EOF) {
{
istruzioni istruzioni
} }
la funzione fscanf legge un valore (uno solo) Si ricordi che la fscanf restituisce EOF solo se
e viene valutato il risultato: non riesce a leggere nessun valore, altrim.
 se è EOF : la lettura è fallita e x non ha cambiato restituisce il numero di valori letti e assegnati.
valore
 se non è EOF : un valore è stato letto dal file e In questo esempio, se nel file è rimasto un solo
memorizzato in x, l’offset viene fatto avanzare del valore l’ultima fscanf dà 1 e non EOF !
numero di byte pari ai caratteri letti (se legge 12 L’esempio è corretto se a priori si sa che nel
avanza di 2 caratteri)
file i valori da leggere sono sempre a coppie
29 30

Ciclo di lettura da file Ciclo di lettura da file


 Si potrebbe risolvere il problema precedente  Per risolvere anche quest’ultimo problema:
specificando il risultato atteso per la fscanf: while (n=(fscanf(fp,"%d%d",&x,&y)==2))
while (fscanf(fp,"%d%d",&x,&y)==2) {
{ istruzioni
istruzioni }
} if (n!=2)
Ma attenzione che in questo modo se il numero {
di valori nel file è dispari, l’ultimo viene letto fprintf(stderr, "dispari!");
comunque e messo in x e non c’è modo per }
accorgersi del problema

31 32

La funzione feof La funzione feof


 Per verificare se si è raggiunta la fine del file  Per determinare se un file è vuoto, si può
si può anche usare la funzione feof(fp) tentare di leggerlo e verificare se la lettura è
andata a buon file. Se necessario si può
 Questa dà un risultato: riportare l’offset all’inizio del file con la
 diverso da 0 (vero) se il file è terminato (è stato funzione rewind:
letto tutto) if (fgetc(fp)==EOF)
 pari a 0 (falso) se c’è almeno un byte da leggere {
(ma non indica quanti) fprintf(stderr, "File vuoto\n");
return EXIT_FAILURE;
 Fornisce risultati corretti solo dopo aver }
tentato di leggere oltre la fine del file, quindi rewind(fp);
while (!feof(fp))
non si può usare per stabilire se un file è {
vuoto oppure no prima di iniziare a leggerlo e fscanf(fp, "%d", &x);
ha altri problemi printf("%d", x);
}
33 34

La funzione feof La funzione feof


 Nonostante la modifica effettuata, il codice  Anche la lettura effettuata con fgetc può
precedente ha un altro problema dovuto creare problemi: la funzione feof lascia
all’accoppiata feof+fscanf erroneamente effettuare una lettura in più
 Dopo aver letto l’ultimo valore, se questo è  Esempio errato:
seguito nel file da uno o più white space la while (!feof(fp))
feof correttamente non identifica la fine del {
file e non restituisce valore vero x=fgetc(fp);
...
 Quindi la successiva lettura non va a buon }
fine, x non viene assegnata e la printf
 Le funzioni di input tranne la fgetc leggono
visualizza nuovamente x, ossia l’ultimo valore quanti più caratteri possono dal file
letto in precedenza (compatibilmente con il tipo di valore richiesto),
per costituire i record di input

35 36

La funzione feof La funzione feof


 Queste funzioni cercano necessariamente di  Questo valore EOF viene elaborato come gli altri
leggere un carattere in più di quello che costituisce caratteri letti correttamente, a meno che non lo si
il record (finché non lo si legge non si può sapere intercetti con una if:
while (!feof(fp))
che non deve essere incluso nel record)
if ((x=fgetc(fp)!=EOF)
 Se queste funzioni trovano la fine del file mentre elabora x;
leggono i caratteri per costituire l’ultimo record di  Ma il duplice controllo sulla fine del file comporta
input, allora la feof può segnalarlo un’inefficienza
 La funzione fgetc legge 1 solo carattere e non  Se non indispensabile, si eviti feof con fgetc
cerca di leggere oltre questo
 Quando fgetc legge l’ultimo carattere non può
sapere che esso è l’ultimo, ma lo scopre solo
quando tenta di leggere il successivo (che non
esiste), quindi solo ora restituisce EOF
37 38

Lettura da un file di testo Lettura da un file di testo


 La funzione ungetc(c, fp)“rimanda” il  Esempio di utilizzo di ungetc
carattere c nel file fp come se non fosse mai Leggendo da un file, si vogliono saltare tutti i
stato letto caratteri che precedono il primo numero intero
 Si può rimandare indietro un solo carattere per leggere quel numero intero (ad es. da
dopo ogni lettura “Alfa beta123abc” estrae il numero 123)
 Il carattere c non viene in realtà “rimandato” while((c=fgetc(fp))!=EOF &&
nel file, ma viene collocato in un buffer di 1 !isdigit(c))
;
byte (quindi non si può scrivere un file con
chiamate successive a ungetc) ungetc(c, fp);
fscanf(fp, "%d", &x);
 Tutte le funzioni di input prima di prelevare i  Il ciclo while continua a leggere e scartare caratteri
caratteri dal file prelevano il byte dal buffer finché si tratta di caratteri non-cifra
(se c’è)  Quando trova l’ 1 esce e unget lo rimanda in fp
 Ora la fscanf può leggere il 123

39 40

Stream preesistenti Stream preesistenti


 Quando il programma viene mandato in  Si noti che:
esecuzione, il sistema operativo gli fornisce 3 fprintf(stdout,"%d",…);
equivale in tutto alla funzione
stream già aperti: printf("%d",…);
 stdin collegato alla tastiera
 Il sistema operativo può essere impostato in modo
 stdout collegato al video da mandare su dispositivi di output diversi gli
 stderr collegato al video (non bufferizzato) stream dei risultati (stdout) e quello degli errori
 Vi sono due stream di output perché: (stderr) mediante la redirezione dell’ I/O, le
modalità dipendono dal SO utilizzato, a titolo di
 stdout dovrebbe essere utilizzato solo per
esempio in DOS/Windows si ha:
visualizzare i risultati dell’elaborazione
 programma >file_per_stdout
 stderr dovrebbe essere utilizzato solo per la  programma 2>file_per_stderr
diagnostica (gli errori del programma, non sono i  programma >file_stdout 2>file_stderr
dati prodotti come risultato dell’elaborazione)  programma >file_stdout_e_stderr 2>&1
fprintf(stderr, "File vuoto");
41 42

Altre funzioni sui file Gestione degli errori


 remove(filename) cancella il filename (stringa)  Quando si verifica un errore, alla variabile
dal disco, restituisce un valore intero non nullo errno viene assegnato un valore intero che
se non riesce lo identifica (richiede <errno.h>, vedere la
 rename(filevecchio, filenuovo) cambia nome documentazione del compilatore per i valori)
a filevecchio (stringa) sul disco, restituisce un
 strerror(n) restituisce [un puntatore a]
valore intero non nullo se non riesce
una stringa contenente la descrizione
 rewind(fp) riporta l’offset del file all’inizio in
dell’errore il cui codice è n (normalmente n è
modo che la successiva lettura/scrittura inizi
dal primo carattere; azzera l’eventuale errno), richiede <string.h>
indicazione di presenza di errori e di EOF
 fseek/ftell e fgetpos/fsetpos
riposizionano l’indicatore dell’offset del file (per
i file di testo ha problemi ed è usata raramen.)

43 44

Gestione degli errori Modalità di aggiornamento


 ferror(fp) restituisce un valore intero non  L’apertura di un file in modalità di
nullo se si è verificato un errore sullo stream aggiornamento permette la lettura e la
fp, richiede <stdio.h> scrittura dello stesso file mediante lo stesso
file pointer (fp)
 clearerr(fp) cancella le indicazioni di errori
 Modi di apertura in aggiornamento:
e di EOF relativi a fp, richiede <stdio.h> "r+" – lettura/scrittura, il file deve esistere
 perror(stringa) visualizza stringa e un "w+" – lettura/scrittura, crea il file vuoto
messaggio di errore corrispondente al valore "a+" – lettura/scrittura al fondo, lo crea se non
in errno, richiede <stdio.h> esiste, aggiunge alla fine se esiste già
 La differenza tra "r+" e "w+" è solo
nell’apertura:
"r+"  se il file non esiste dà errore
"w+"  se il file esiste già, lo ricrea vuoto
45 46

Modalità di aggiornamento Modalità di aggiornamento


 Il modo "a+" non cancella il contenuto di un  Tra un’operazione di scrittura e una di lettura
file già esistente, posiziona il file position (o viceversa) sullo stesso file è necessario che
pointer alla fine del file e permette di scrivere ci sia una chiamata a fflush o a una
solo in fondo al file funzione di posizionamento dell’offset quale:
 Anche se con fseek si sposta l’offset rewind, fseek o fsetpos
indietro, la scrittura avviene sempre  Se si deve leggere dal file un qualcosa che è
aggiungendo record in fondo al file e i dati possibile sia ancora nei buffer, è necessario
precedenti non possono quindi essere chiamare la funzione fflush
modificati (neppure quelli appena scritti,
nemmeno se il file non è stato ancora chiuso)
 Con opportuna fseek è possibile leggere i
dati da qualsiasi punto del file

47 48

Considerazioni sull’efficienza Esercizi


 Tutte le operazioni di I/O relative ai file sono 1. Scrivere con un editor un file contenente dei
intrinsecamente e notevolmente più lente di numeri, uno per riga. Sviluppare un
quelle che usano solo la memoria, nonostante programma che chieda all’utente il nome di
la presenza di buffer e cache questo file, lo apra e calcoli e stampi a video
quanti sono i valori letti, il valore massimo, il
 Conviene ridurre il più possibile l’accesso al valore minimo, la somma e la media di tutti i
file (ma se è molto piccolo potrebbe essere valori presenti nel file.
contenuto interamente nel buffer e l’accesso 2. Scrivere un programma che chieda all’utente
al file essere un mero accesso alla memoria) il nome di un file di testo e conti quante righe
 Quando è necessario utilizzare molte volte i e quanti caratteri esso contiene (non si
dati contenuti in un file, conviene in genere considerino i caratteri di ritorno a capo ed
caricarne il contenuto in memoria in eventuale fine file).
opportune strutture dati
49 50

Esercizi Esercizi
3. Scrivere un programma che legga un file 4. Si scriva un programma che chieda il nome di
contenente coppie di numeri interi (x e y), una un file contenente un testo qualsiasi e di
per riga e scriva un secondo file che contenga questo conti quante sono le parole che
le differenze x – y, una per riga. iniziano con ciascuna lettera dell’alfabeto.
Si supponga che il file di input non abbia errori Esempio di output:
e che nomi dei file vengano chiesti all’utente. Parole che iniziano con A: 45
File 1 File 2
Parole che iniziano con B: 12
Parole che iniziano con C: 27
23 32 -9 …
2 11 -9 Parole che iniziano con Z: 3
19 6 13
23 5 18
3 2 1
… … …

51 52

Esercizi Esercizi
5. Un file di testo contiene, in ciascuna riga 6. Scrivere un programma che legga da un file
separati da spazi, 2 o 3 valori reali: un testo e spezzi su più righe quelle più
1. nel primo caso si tratta della base e dell’altezza di lunghe di N caratteri (N chiesto all’utente).
un triangolo La riga viene spezzata anche in mezzo ad una
2. nel secondo caso si tratta della base minore, della parola o prima di uno spazio. L’output deve
base maggiore e dall’altezza di un trapezio essere salvato in un altro file. Ad esempio, se
Si scriva un programma che chieda all’utente viene letta la riga seguente (è una sola, qui è
il nome di questo file, lo analizzi e indichi qual scritta su due righe perché troppo lunga):
Mi devo recare all’ufficio postale
è la riga del file corrispondente alla figura precipitevolissimevolmente
geometrica di area maggiore e il valore di
l’output (con N pari a 22) deve essere:
quest’area. Se si trovano figure di aree uguali,
Mi devo recare all’uf
si consideri la prima di queste. ficio postale precipi
tevolissimevolmente
53 54

Esercizi Esercizi
7. Come il precedente, ma le righe si possono 8. Merge di due file
spezzare solo dove c’è uno spazio (che non va Due file di testo contengono, disposti
visualizzato a capo), se negli N caratteri non variamente su più righe, dei numeri interi.
c’è uno spazio, si spezzi la parola all’N-esimo Ciascuno dei due file è già ordinato in senso
carattere come nell’esercizio precedente. CRESCENTE e non è noto a priori quanti
elementi contenga (possono anche avere un
Esempio di output con N pari a 22:
numero di valori differente).
Mi devo recare
all’ufficio postale
Si scriva un programma che legga questi due
precipitevolissimevolm file e ne produca un terzo contenente i valori
ente dei due file ordinati tutti quanti in senso
CRESCENTE. Non si utilizzino vettori né
algoritmi di ordinamento. I nomi dei tre file
vengano chiesti all’utente.

55 56

Esercizi Esercizi
9. Il cifrario di Cesare (Continuazione)
Si scriva un programma che cifri/decifri un file Il valore del codice indica di quanti caratteri si
di testo in base ad un codice segreto. Il deve traslare ciascuna delle lettere: se ad es.
programma deve chiedere il nome del file di il codice è 3, allora ‘A’  ‘D’, ‘B’  ‘E’, ...
input, il nome del file di output e il codice ‘X’  ‘A’, ‘Y’  ‘B’, ‘Z’  ‘C’.
segreto (un numero intero). La cifratura La corrispondenza completa delle lettere
avviene sostituendo le sole lettere (maiuscole maiuscole (per le minuscole è analogo) è:
A B C D E F G H I J K L MNO P Q R S T U VWX Y Z
e minuscole separatamente) con altre lettere
D E F G H I J K L MNO P Q R S T U VWX Y Z A B C
in base al valore del codice.
Ad esempio, con codice=3 “Ciao” diventa
“Fldr”. Si noti che per decifrare un testo
basta inserire come codice il valore opposto a
quello usato per la cifratura (qui –3).
57 58

Esercizi Esercizi
10. Simile al precedente, ma la sostituzione delle (Continuazione)
lettere avviene secondo il seguente algoritmo. Il programma chiede l’introduzione di una
Il codice segreto di cifratura/decifratura è parola chiave da cui, eliminando i caratteri
costituito da una parola composta di sole duplicati e le non-lettere, si ha il codice
lettere tutte diverse. La prima lettera del segreto. Ad esempio, dalla parola chiave
codice viene fatta corrispondere alla lettera “Fragola” si ottiene il codice segreto
“FRAGOL” e la corrispondenza delle lettere è:
‘A’, la seconda alla ‘B’, e così via fino all’ultima
A B C D E F G H I J K L MNO P Q R S T U VWX Y Z
lettera del codice. Le lettere non indicate nel
F RAGO L Z Y XWV U T S Q P NM K J I H E D C B
codice vengono riordinate alfabeticamente al
contrario (dalla Z alla A) e fatte corrispondere Ad esempio, la parola “Ciao” viene cifrata in
alle restanti lettere dell’alfabeto (maiuscole e “Axfq” (notare maiuscole e minuscole).
minuscole separatamente). Il programma deve chiedere se si vuole cifrare
o decifrare il file.

59 60

Esercizi Esercizi
11. Si scriva un programma che chieda all’utente 12. Unasuperficie viene descritta da una matrice
il nome di un file contenente la griglia di valori di valori in floating-point in doppia precisione
di un Sudoku risolto (N righe con N valori). composta di R righe e C colonne (costanti
Il programma deve verificare ciascuna riga, note a priori). Ogni elemento della matrice
ciascuna colonna e ciascun riquadro e corrisponde ad un quadrato di dimensioni
segnalare le righe, le colonne e i riquadri che 1cm x 1cm. I valori rappresentano l’altezza
non soddisfano le condizioni di validità. media di quella superficie in quel punto e
Condizione di validità: non ci devono essere sono letti da un file. Tale file contiene C valori
valori ripetuti. (separati da spazi) per ciascuna delle R righe
Il programma accetti automaticamente griglie e non ha errori. Il primo elemento della
di lato massimo 25 numeri. matrice corrisponde alla parte di superficie
situata più a nord-ovest e ha coordinate (0,0).
61 62

Esercizi Esercizi
(Continuazione) (Continuazione)
Si noti che le coordinate X corrispondono Si usa un modello fisico semplificato dove la
alle colonne, le Y alle righe. pallina:
Si suppone di voler simulare il comportamento 1. può scendere in ciascuna delle 8 caselle che la
di una pallina che viene collocata su uno dei circondano (se ci sono, ossia non è ai bordi)
riquadri della superficie (le cui coordinate sono 2. scende lungo il cammino più ripido, ossia delle 8
caselle raggiunge quella più in basso (se ce ne
richieste all’utente) e poi lasciata libera. Il sono più di una all’altezza minima si scelga la
programma deve visualizzare la sequenza prima trovata)
delle coordinate di tutte le posizioni che 3. non ha inerzia (cioè scende sempre lungo il
vengono attraversate dalla pallina fino a cammino più ripido)
quando si ferma, inclusa la posizione iniziale, 4. non può/deve uscire dai limiti della superficie
con l’indicazione dell’altezza in quel punto. 5. si ferma quando non ci sono caselle più in basso
della posizione che occupa

63 64

Esercizi Esercizi
(Continuazione) 13. Simodifichi l’esercizio precedente
Posizione iniziale considerando un modello fisico in cui la
- coordinata X (1-20): 5 pallina possa spostarsi solo in diagonale
- coordinata Y (1-30): 3
14. Come il precedente, ma la pallina possa
Percorso della pallina spostarsi solo in direzione nord/sud/est/ovest
---------------------- (orizzontale/verticale).
0 - (5,3) [20.42]
1 - (6,2) [15.21]
2 - (7,3) [11.11]
3 - (7,4) [7.235]
4 - (8,5) [3.66]
5 - (9,4) [-1.7]
6 - (9,3) [-3.45]
65

Homework 5
Si scriva un programma per gestire un’agenda
elettronica. I dati relativi alle persone sono:
nome, cognome, indirizzo, telefono e
nota; NON possono contenere spazi e sono
contenuti in un file di testo denominato
database.txt. Viene presentata un’interfaccia
a menu per a) inserire, b) togliere, c) cercare
i dati relativi ad una persona (solo in base al
cognome), d) visualizzare tutte le coppie
nome/cognome senza dettagli ed e) uscire dal
programma. Le persone sono al massimo 200, i
dati devono essere copiati tutti in memoria
quando il programma parte e scritti solo alla fine.