Upload
rosanna-gioia
View
263
Download
0
Embed Size (px)
Citation preview
PolitecnicoPolitecnicodi Milanodi Milano
EserciziEsercizi
Esercizi di riepilogo sul linguaggio C: file, puntatori, Esercizi di riepilogo sul linguaggio C: file, puntatori, listeliste
- - 22 - -
Codifica file di testoCodifica file di testo
Utilizzando la codifica di Cesare, scrivere un programma in grado di criptare e decriptare un file di testoIl programma chiederà all’utente il nome del file da elaborare, il nome del file in cui scrivere il risultato, l’operazione da effettuare (codifica o decodifica) ed il codice.
- - 33 - -
Codifica file di testoCodifica file di testo
#include <stdio.h>#include <string.h>
const unsigned int CRIPTA = 0;const unsigned int DECRIPTA = 1;
void codificaCesare (char *car, unsigned int k, unsigned int azione){
int temp;
.
- - 44 - -
Codifica file di testoCodifica file di testo
if (azione == CRIPTA){
*car = *car - 'a';temp = *car + k;if (temp < 26){
*car = temp;}else{
*car = temp - 26;}*car = *car + 'a';
} .
- - 55 - -
Codifica file di testoCodifica file di testo
else /* decripta */{
*car = *car - 'a';temp = *car - k;if (temp >= 0){
*car = temp;}else{
*car = temp + 26;}*car = *car + 'a';
}} .
- - 66 - -
Codifica file di testoCodifica file di testovoid codificaFile(char nFileIn[], char nFileOut[], unsigned int cod, unsigned int oper){
FILE *fileIn, *fileOut;char car;
fileIn = fopen (nFileIn, "r");fileOut = fopen (nFileOut, "w");fscanf (fileIn, "%c", &car);while (!feof(fileIn)){
codificaCesare (&car, cod, oper);fprintf (fileOut, "%c", car);fscanf (fileIn, "%c", &car);
}fclose (fileIn);fclose (fileOut);
} .
- - 77 - -
Codifica file di testoCodifica file di testo
void main(){
char nomeFileIn[100], nomeFileOut[100];unsigned int codice, operazione;
printf ("File input: ");scanf ("%s", nomeFileIn);printf ("File output: ");scanf ("%s", nomeFileOut);printf ("Codice: ");scanf ("%u", &codice);printf ("0=cripta, 1=decripta: ");scanf ("%u", &operazione);codificaFile (nomeFileIn, nomeFileOut, codice, operazione);
} .
- - 88 - -
Elimina Elimina tagtag HTML HTML
Il programma legge un file di testo contenente una pagina HTML, elimina i tag presenti e salva il testo in un altro file. I tag scartati saranno visualizzati sul monitor.Miglioramenti:
Scrivere solo il testo che si trova in <body>…</body>Scrivere i tag in modo più leggibile:
uso sotto l’altrocon i simboli < e >
- - 99 - -
Elimina Elimina tagtag HTML HTML
#include <stdio.h>
void eliminaTag (char nomeFileHTML[], char nomeFileTesto[]){
typedef enum {tag, testo, errore} TipoStato;FILE *docHTML, *docTesto;char car;TipoStato stato = testo;
docHTML = fopen (nomeFileHTML, "r");if (docHTML == NULL){
printf ("File %s non trovato\n", nomeFileHTML);
return;}
- - 1010 - -
Elimina Elimina tagtag HTML HTML
docTesto = fopen (nomeFileTesto, "w");fscanf (docHTML, "%c", &car);while (!feof(docHTML) && stato != errore){
if (stato == testo){
switch (car){
case '<': stato = tag; break;
case '>': stato = errore; break;
default: fprintf (docTesto, "%c", car);
break;}
}
- - 1111 - -
Elimina Elimina tagtag HTML HTML
else if (stato == tag){
switch (car){
case '<': stato = errore; break;
case '>': stato = testo; break;
default: printf ("%c", car); break;
}}fscanf (docHTML, "%c", &car);
}fclose (docTesto);fclose (docHTML);
}
- - 1212 - -
Elimina Elimina tagtag HTML HTML
void main(){
char nomeFileHTML[255], nomeFileTesto[255];
printf ("Nome file HTML: ");scanf ("%s", nomeFileHTML);printf ("Nome file testo: ");scanf ("%s", nomeFileTesto);eliminaTag (nomeFileHTML, nomeFileTesto);
}
- - 1313 - -
Archivio filmArchivio film
Il programma dovrà permettere all’utente, tramite un menù, di gestire un archivio di filmDovranno essere disponibili le seguenti operazioni:
1. L’utente inserisce un certo numero di film:Codice identificativo numerico e titolo (senza spazi)L’inserimento della lista di film è terminato immettendo uno codice pari a zero
2. L’utente inserisce un codice e l’elaboratore verifica se il corrispondente film è presente nel file (ed in questo caso ne scrive i dati sul monitor)
Utilizzare l’algoritmo di ricerca binaria e l’algoritmo bubble-sortE se usassimo l’ordinamento per inserzione?
- - 1414 - -
Archivio film: ricerca binariaArchivio film: ricerca binaria
0
Valore della variabile inizio
2
Valore della variabile fine
1
Valore della variabile medio
fseek (archivio, -sizeof(Film), SEEK_END);
Posizione iniziale all’apertura del file
Posizione dopo fseek()
inizio = 0;fine = ftell(archivio) / sizeof(Film);medio = (inizio + fine) / 2;
102 2030 101 204 305 306
archivio = fopen ("pippo", "rb");
- - 1515 - -
Archivio filmArchivio film
#include <stdio.h>typedef struct{
unsigned int codice;char titolo[100];
} Film;
void ordina (char nomeFile[]){
typedef enum {falso, vero} Booleano;FILE *archivio;Film filmCorrente, filmSuccessivo;unsigned int numFilm, i;Booleano scambio;
- - 1616 - -
Archivio filmArchivio film
/* "r+b" permette di leggere/scrivere su file binario esistente */
archivio = fopen (nomeFile, "r+b");fseek (archivio, -sizeof(Film), SEEK_END);/* calcola numero di film inseriti nel file */numFilm = ftell (archivio) / sizeof(Film) + 1 ; do
{scambio = falso;/* si riporta a inizio file */fseek (archivio, 0, SEEK_SET);
- - 1717 - -
Archivio filmArchivio film
for (i = 0; i < numFilm - 1; i++) { fread (&filmCorrente, sizeof(Film), 1, archivio); fread (&filmSuccessivo, sizeof(Film), 1, archivio);
if (filmCorrente.codice > filmSuccessivo.codice) { /* sposta testina due record all'indietro */ fseek(archivio,-2*sizeof(Film), SEEK_CUR);
fwrite (&filmSuccessivo, sizeof(Film),1, archivio);
- - 1818 - -
Archivio filmArchivio film
fwrite (&filmCorrente, sizeof(Film), 1, archivio);
scambio = vero;}
}} while (scambio);fclose (archivio);
}
- - 1919 - -
Archivio filmArchivio film
void inserisci (char nomeFile[]){FILE *archivio; Film nuovoFilm;
/* apertura file per scrivere in append */ archivio = fopen (nomeFile, "ab"); printf ("Codice film diverso da 0: "); scanf ("%u", &nuovoFilm.codice); if (nuovoFilm.codice != 0) { printf ("Titolo film: ");
scanf ("%s", nuovoFilm.titolo); }
- - 2020 - -
Archivio filmArchivio film
while (nuovoFilm.codice != 0) {
fwrite (&nuovoFilm, sizeof(nuovoFilm), 1, archivio);
printf ("Codice film diverso da 0: "); scanf ("%u", &nuovoFilm.codice);
if (nuovoFilm.codice != 0) { printf ("Titolo film: ");
scanf ("%s", nuovoFilm.titolo);}
} fclose (archivio);
ordina (nomeFile); /* riordina tutto il file */}
- - 2121 - -
Archivio filmArchivio film
void cerca (char nomeFile[]){ typedef enum {falso, vero} Booleano; Booleano trovato = falso; FILE *archivio; Film filmCorrente; unsigned int codCercato; int inizio, fine, medio;
printf ("Codice cercato: "); scanf ("%u", &codCercato); archivio = fopen (nomeFile, "rb"); inizio = 0; fseek (archivio, -sizeof(Film), SEEK_END); fine = ftell (archivio) / sizeof(Film);
- - 2222 - -
Archivio filmArchivio film
do { medio = (inizio + fine) / 2; fseek (archivio, medio * sizeof(Film), SEEK_SET);
fread (&filmCorrente, sizeof(filmCorrente), 1, archivio); if (codCercato < filmCorrente.codice) { fine = medio - 1; }
else if (codCercato > filmCorrente.codice){
inizio = medio + 1; }
- - 2323 - -
Archivio filmArchivio film
else {
trovato = vero; } } while (!trovato && inizio <= fine); if (trovato) {
printf ("Trovato in posiz: %u\n", medio);printf("Codice: %u\n",filmCorrente.codice);
printf("Titolo: %s\n",filmCorrente.titolo); } else { printf ("Non trovato!\n"); } fclose (archivio);}
- - 2424 - -
Archivio filmArchivio film
unsigned int menu (){
unsigned int scelta;
printf ("1. Inserisci elenco film\n"); printf ("2. Cerca film\n"); printf ("3. Esci\n"); printf ("\nScelta: "); scanf ("%u", &scelta); return scelta;}
- - 2525 - -
Archivio filmArchivio film
void main(){
char nomeArchivio[] = "numeri.dat"; unsigned int n; do { n = menu(); switch (n)
{ case 1: inserisci (nomeArchivio);
break; case 2: cerca (nomeArchivio);
break; } } while (n != 3);}
- - 2626 - -
Riepilogo sui file…Riepilogo sui file…
Le funzioni fscanf(), fread(), fprintf(), fwrite() leggono/scrivono a partire dalla posizione corrente della “testina” all’interno del fileDopo l’operazione, la “testina” si sposta in avanti di una quantità di byte pari al numero di byte letti/scrittiIl tipo del dato letto dal file deve essere in accordo con quanto la funzione si aspetta:
Se un file contiene una stringa e lo leggo con:fscanf (file, "%d", &varIntera);la variabile varIntera conterrà un valore scorretto!Idem per quanto riguarda fread().
- - 2727 - -
Riepilogo sui file…Riepilogo sui file…
Uso di sizeof() con fread() e fwrite():Quando leggo/scrivo variabili che non siano vettori, uso il nome della variabile:int v;fread (&v, sizeof(v), 1, ilfile);
Quando leggo/scrivo variabili vettore, uso:Il nome della variabile, per leggere/scrivere tutto il vettore in un colpo solo:int vet[10];fread (vet, sizeof(vet), 1, ilfile);
Il nome del tipo, per leggere/scrivere solo una cella del vettore:int vet[10], i = 0;fread (&vet[i], sizeof(int), 1, ilfile);
- - 2828 - -
Riepilogo sui file…Riepilogo sui file…
File di testo o binari?Quando è richiesto di leggere/scrivere delle variabili strutturate, si usano i file binariQuando è richiesto di spostarsi all’interno del file (fseek()), si usano i file binariQuando è richiesto di leggere/scrivere stringhe di caratteri, si usano (tipicamente) file di testo
Quando scrivo con fprintf(), leggo con fscanf(),quando scrivo con fwrite(), leggo con fread().
- - 2929 - -
PuntatoriPuntatori
char *p, s[]=“xyz”;
p = s;
int *p2;
p2 = 23; oppure…
int *p3;
*p3 = 23; oppure…
int *p4, var;
p4 = &var;
*p4 = 23;
?23p2Indirizzo: 23
23p4 var
23p3 99Indirizzo: 99
Es. di valore casuale
\0zyxp s
- - 3030 - -
PuntatoriPuntatori
Dato il seguente frammento di programma C:int *p1, *p2, x, y;x = 10;y = 20;p1 = &x;p2 = p1;*p1 = 5;p2 = &y;y = 30;*p2 = *p1 + *p2;*p1 = *p1 + x;Disegnare il valore di tutte le variabili al termine dell’esecuzione di ogni riga.Le variabili x e y si trovano, rispettivamente, nelle celle di memoria di indirizzo 1000 e 2000.
- - 3131 - -
PuntatoriPuntatori
int *p1, *p2, x, y;
x = 10;
y = 20;
p1 = &x;
p2 = p1;
? ? ? ?
? 10 ? ?
? 10 20 ?
1000 10 20 ?
1000 10 20 1000
p1 x y p21000 2000
- - 3232 - -
PuntatoriPuntatori
*p1 = 5;
p2 = &y;
y = 30;
*p2 = *p1 + *p2;
*p1 = *p1 + x;
1000 5 20 1000
1000 5 20 2000
1000 5 30 2000
1000 5 35 2000
1000 10 35 2000
p1 x y p21000 2000
- - 3333 - -
Le liste dinamicheLe liste dinamiche
- - 3434 - -
Le liste dinamiche: operazioni Le liste dinamiche: operazioni tipichetipiche
Inserimento di un elemento:In testa alla listaIn coda alla listaIn un punto generico (equivale ad inserire in testa ad una sotto-lista)
Cancellazione di un elemento:Dalla testaDalla codaDa un punto generico (equivale a cancellare la testa di una sotto-lista)
Cancellazione totale della lista RicercaStampa della listaOrdinamento
- - 3535 - -
Le liste dinamiche: definizioneLe liste dinamiche: definizione
#include <stdio.h>#include <stdlib.h>
struct Elem{
int dato; struct Elem *prox;
};
typedef struct Elem ElementoLista;typedef ElementoLista *Lista;
- - 3636 - -
Le liste dinamiche: “libreria” di Le liste dinamiche: “libreria” di funzionifunzioni
Lista inserisciInTesta (Lista lista, int dato);Lista inserisciInCoda (Lista lista, int dato);Lista cancellaTesta (Lista lista);Lista cancellaCoda (Lista lista);Lista cancellaLista (Lista lista);Lista cercaInLista (Lista lista, int dato);void scriviLista (Lista lista);
In un caso reale, sostituirò int con il tipo che mi interessaPer esempio, potrei definire il tipo CartaIdentita e costruire quindi un lista di carte di identità.
- - 3737 - -
Le liste dinamiche: il mainLe liste dinamiche: il main
void main(){
unsigned int num, i;int d, cercato;Lista laMiaLista, elem;
/* Nessuna limitazione a priori! */printf ("Quanti dati? "); scanf ("%u", &num);for (i = 0; i < num; i++){
printf ("Dato: ");scanf ("%d", &d);laMiaLista=inserisciInCoda(laMiaLista,d);
}printf ("Dato da cercare: ");scanf ("%d", &cercato);
- - 3838 - -
Le liste dinamiche: il mainLe liste dinamiche: il main
scriviLista(laMiaLista);elem = cercaInLista (laMiaLista, cercato);if (elem != NULL){
printf ("Dato cercato: %d\n", elem->dato);}else{
printf ("Dato non trovato\n");}laMiaLista = cancellaTesta (laMiaLista);scriviLista(laMiaLista);laMiaLista = cancellaCoda (laMiaLista);scriviLista(laMiaLista);laMiaLista = cancellaLista (laMiaLista);scriviLista(laMiaLista);
}
- - 3939 - -
Le liste dinamiche: inserisci in testaLe liste dinamiche: inserisci in testa
Lista inserisciInTesta (Lista lista, int dato){
Lista nuovoElem;
nuovoElem=(Lista)malloc(sizeof(ElementoLista));nuovoElem->dato = dato;nuovoElem->prox = lista;return nuovoElem;
}
Dopo ogni inserimento, lista (il puntatore alla testa della lista) viene modificato.
- - 4040 - -
Le liste dinamiche: inserisci in codaLe liste dinamiche: inserisci in coda
Lista inserisciInCoda (Lista lista, int dato){
Lista nuovoElem, cursore;nuovoElem=(Lista)malloc(sizeof(ElementoLista));nuovoElem->dato = dato;nuovoElem->prox = NULL;if (lista == NULL)
return nuovoElem;else{
cursore = lista;while (cursore->prox != NULL)
cursore = cursore->prox;cursore->prox = nuovoElem;return lista;
}}
- - 4141 - -
Le liste dinamiche: inserisci in codaLe liste dinamiche: inserisci in coda
Due casi:Lista vuota il nuovo elemento è il primo della lista; la funzione ne ritorna l’indirizzoLista non vuota arriva all’ultimo elemento e vi “appende” il nuovo.
Nel secondo caso, lista non viene modificatoLa funzione deve comunque ritornare qualcosa: ritorna lista
- - 4242 - -
Le liste dinamiche: cancella la testaLe liste dinamiche: cancella la testa
Lista cancellaTesta (Lista lista){
Lista temp;
temp = lista->prox;free (lista);return temp;
}
Dopo ogni cancellazione, lista (il puntatore alla testa della lista) viene modificato.
- - 4343 - -
Le liste dinamiche: cancella la codaLe liste dinamiche: cancella la coda
Lista cancellaCoda (Lista lista){
Lista cursore;
if (lista == NULL){
return lista;}else if (lista->prox == NULL){
free (lista);return NULL;
}
- - 4444 - -
Le liste dinamiche: cancella la codaLe liste dinamiche: cancella la coda
else{
cursore = lista;while (cursore->prox->prox != NULL){
cursore = cursore->prox;}free (cursore->prox);cursore->prox = NULL;return lista;
}}
- - 4545 - -
Le liste dinamiche: cancella la codaLe liste dinamiche: cancella la coda
Tre casi:Lista già vuota non fa nullaLista composta da un solo elemento la testa punta a NULLLista composta da più elementi il penultimo punta a NULL
- - 4646 - -
Le liste dinamiche: cancellazione Le liste dinamiche: cancellazione totaletotale
Lista cancellaLista (Lista lista){
Lista temp, cursore;
cursore = lista;while (cursore != NULL){
temp = cursore->prox;free (cursore);cursore = temp;
}return cursore;
}
Come potrei definirla usando le funzioni cancellaTesta() o cancellaCoda() ?
- - 4747 - -
Le liste dinamiche: ricercaLe liste dinamiche: ricerca
Lista cercaInLista (Lista lista, int dato){
Lista cursore;int trovato = 0;
cursore = lista;while (cursore != NULL && trovato == 0){
if (cursore->dato == dato)trovato = 1;
elsecursore = cursore->prox;
}if (trovato == 1)
return cursore;else
return NULL;}
- - 4848 - -
Le liste dinamiche: ricercaLe liste dinamiche: ricerca
Ricerca lineare: parto dal primo elemento e vado avantiNon molto efficiente (la ricerca binaria è molto più veloce)Ma, posso fare diversamente?
Liste accesso sequenziale!
- - 4949 - -
Le liste dinamiche: scrivi listaLe liste dinamiche: scrivi lista
void scriviLista (Lista lista){
Lista cursore;
printf ("Inizio lista\n");cursore = lista;while (cursore != NULL){
printf ("%d\n", cursore->dato);cursore = cursore->prox;
}printf ("Fine lista\n");
}
- - 5050 - -
Le liste dinamiche: conclusioneLe liste dinamiche: conclusione
Allocazione dinamica il programmatore non è obbligato a porre dei limiti al numero di dati da memorizzare in RAM
Prendo spazio quando serve, usando la malloc()
Libero spazio quando posso, usando la free()
Scomodo i vettori sono più facili da usareNon esistono pasti gratis!!!
Accesso solo sequenzialeIdem come sopra!!!