G. Mecca – Università della Basilicata – mecca@unibas.it
Programmazione Procedurale in Linguaggio C++
Strutture di Dati Conclusioni – parte a
versione 2.2
Questo lavoro è concesso in uso secondo i termini di una licenza Creative Commons (vedi ultima pagina)
Sommario
m
Ricapitolazione
m
Passaggio dei Parametri
m
Gestione dei File
Strutture di Dati: Conclusioni >> Sommario
G. Mecca - Programmazione Procedurale in Linguaggio C++ 3
Ricapitolazione
m
Struttura di dati
ðorganizzazione delle variabili del programma per rappresentare i dati di un problema
ðesistono strutture di dati notevoli, per cui le dichiarazioni e le operazioni sono note
m
Esempio
ðla lista con array e record
Strutture di Dati: Conclusioni >> Ricapitolazione
Ricapitolazione
m
Lista
ðstruttura matematica che consente di rappresentare collezioni di vario genere ðcollezioni ordinate e non ordinate
ðcollezioni con duplicati e senza duplicati ðcollezioni di dimensione variabile o fissa
ðalto livello di flessibilità, che la rende adatta a molte applicazioni
Strutture di Dati: Conclusioni >> Ricapitolazione
G. Mecca - Programmazione Procedurale in Linguaggio C++ 5
Ricapitolazione
m
Rappresentazione della lista
ðviene utilizzato un array di dimensione costante per contenere gli elementi
ðviene utilizzato un indicatore di riempimento per tenere traccia dell’occupazione dell’array
m
Scrittura delle operazioni
ðproblema 1: gestire l’indicatore ðproblema 2: verificare la correttezzaStrutture di Dati: Conclusioni >> Ricapitolazione
Passaggio dei Parametri
m
In molti casi
ðla lista può contenere un array di grandi dimensioni
ðattenzione al passaggio dei parametri
m
Normalmente
ðdi un array viene passato l’indirizzo del primo registro
m
Nel caso di un array in un record
ðsituazioni diverseStrutture di Dati: Conclusioni >> Passaggio dei Parametri
G. Mecca - Programmazione Procedurale in Linguaggio C++ 7
Passaggio dei Parametri
m
Se la lista viene passata per riferimento
ðal sottoprogramma viene passato solol’indirizzo del registro iniziale del record
m
Se la lista viene passata per valore
ðuna copia completa del record viene creata nello spazio di mem. del sottoprogramma ðinclusa una copia intera del contenuto
dell’array
Strutture di Dati: Conclusioni >> Passaggio dei Parametri
Passaggio dei Parametri
Strutture di Dati: Conclusioni >> Passaggio dei Parametri
void leggi (lista &l) { int i;
cout << “Quanti valori ?”;
cin >> l.indicatore;
for (i=0;i< l.indicatore;i++) cin >> l.valori[i];
return;
}
void main() { lista l;
leggi (l);
...
}
xxx
#203
l.valori[2] xxx
#104 l
l.valori[3] xxx
#105
l.valori[4] xxx
#106
... ...
...
xxx
#202
xxx
#99
l.valori[99] xxx
#201
l.valori[1] xxx
#103
l.valori[0] xxx
#102
l.valori #102
#101
l.indicatore xxx
#100
l #100
G. Mecca - Programmazione Procedurale in Linguaggio C++ 9
Passaggio dei Parametri
Strutture di Dati: Conclusioni >> Passaggio dei Parametri
void stampa (lista l) { int i;
cout << "Valori:" << endl;
if (l.indicatore==0)
cout << "Lista vuota\n“;
else
for(i=0;i<l.indicatore;i++) cout << l.valori[i]<<“ “;
return;
}
void main() { lista l;
leggi (l);
stampa (l);
...
}
... ...
...
#304
#303 ...
#208
#207
#206
#205
#204
#203
#202
l.valori[0] 3
#102 l
-923 l.valori[99]
#201
l.valori #102
#101
l.indicatore 4
#100
i xxx
l.valori[2] 7 l
l.valori[3] -1 l.valori[4] 234 ... ...
l.valori[99] -923 l.valori[1] 4.5 l.valori[0] 3 l.valori #204 l.indicatore 4
Passaggio dei Parametri
m
Nel caso di passaggio per valore
ðpossono esserci problemi di eccessivoconsumo di memoria
ðesempio: più liste con array di grandi dimensioni
m
In sintesi
ðci sono problemi in questa soluzione ðè opportuno tenere bassa la dimensione
dell’array nella lista
Strutture di Dati: Conclusioni >> Passaggio dei Parametri
G. Mecca - Programmazione Procedurale in Linguaggio C++ 11
Gestione dei File
m
Un problema nuovo
ðbisogna caricare dai file un numero di elementi variabile per la lista
m
Problema
ðcome stabilire quando fermarsi ?
m
I soluzione: usare l’indicatore
m
II soluzione: usare l’operatore di lettura
Strutture di Dati: Lista >> Gestione dei File
Gestione dei File
m
I soluzione
ðscelgo un formato per il file che prevede che l’indicatore di riempimento sia il primo
numero sulla prima riga del file ðacquisisco immediatamente dal file
l’indicatore
ðprocedo all’acquisizione degli elementi della lista con un ciclo for pilotato dall’indicatore
Strutture di Dati: Conclusioni >> Gestione dei File
G. Mecca - Programmazione Procedurale in Linguaggio C++ 13
Gestione dei File
Numero elementi:
12
--- -1.7
3 4.7 7 12 18 25.7 28.4 20 14.8 9.9 3.6
Strutture di Dati: Conclusioni >> Gestione dei File
valore dell’indicatore
Gestione dei File
m
Due elementi a cui fare attenzione
ðper cominciare devo accertarmi di leggere al più MAXDIM elementi
ðper cui se l’indicatore nel file supera MAXDIM devo correggere il valore
ðinoltre attenzione al caso in cui vengono mischiate operazioni di input formattato e non formattato (richiede di usare ignore())
Strutture di Dati: Conclusioni >> Gestione dei File
G. Mecca - Programmazione Procedurale in Linguaggio C++ 15
void carica (lista &l, string nomeFile){
int i;
string s;
ifstream inFile(nomeFile.c_str());
getline(inFile, s);
inFile >> l.indicatore;
getline(inFile, s);
inFile.ignore();
if (l.indicatore > MAXDIM) { l.indicatore = MAXDIM;
}
for (i = 0; i < l.indicatore; i++) { inFile >> l.valori[i];
}
inFile.close();
return;
}
Strutture di Dati: Lista >> Gestione dei File
correggo l’eventuale valore in eccesso rispetto al massimo
utilizzo l’indicatore per comandare il ciclo for di acquisizione per cominciare acquisisco dal file il valore dell’indicatore
ripulisce il flusso dopo l’input formattato
void salva (lista &l, string nomeFile){
int i;
ofstream outFile(nomeFile.c_str());
outFile << “Numero elementi:” << endl;
outFile << l.indicatore << endl;
outFile << “---” << endl;
for (i = 0; i < l.indicatore; i++) { outFile << l.valori[i] << endl;
}
outFile.close();
return;
}
Strutture di Dati: Lista >> Gestione dei File
in fase di scrittura, per rispettare il formato del file devo scrivere nella seconda riga il valore dell’indicatore
G. Mecca - Programmazione Procedurale in Linguaggio C++ 17
Gestione dei File
m
II Soluzione
ðnecessaria nel caso in cui non sia disponibile il valore dell’indicatore di riempimento
ðè possibile sfruttare una caratteristica dell’operatore di lettura da flusso, >>
ðoltre a prelevare il valore dal flusso, restituisce un valore
Strutture di Dati: Conclusioni >> Gestione dei File
Gestione dei File
m
Semantica dell’operatore di lettura
ð<flusso> >> <variabile>
ðsi tratta in effetti di un’espressione, che oltre ad effettuare le operazioni di lettura,
restituisce un valore booleano
ðse la lettura viene completata con successo, il risultato è true
ðaltrimenti il risultato è false
Strutture di Dati: Conclusioni >> Gestione dei File
ATTENZIONE alla semantica dell’operatore di
lettura
G. Mecca - Programmazione Procedurale in Linguaggio C++ 19
Gestione dei File
m
Soluzione
ðè possibile acquisire dati dal file con un ciclo ðutilizzando l’istruzione di lettura come
espressione per comandare l’esecuzione ðes: while (<flusso> >> <variabile>) {...}
ðfinché la lettura è possibile, viene restituito true e il ciclo va avanti
ðquando il file si esaurisce, la lettura fallisce ed il ciclo si ferma
Strutture di Dati: Conclusioni >> Gestione dei File
Gestione dei File
m
Nota
ðin questo caso, durante l’acquisizione devo contestualmente contare gli elementi
ðma facendo attenzione ad acquisirne al più MAXDIM
ðall’indicatore assegno il risultato del conteggio
m
Esempio: formato semplice
ðsupponiamo ci sia un elemento per riga
Strutture di Dati: Lista >> Gestione dei File
G. Mecca - Programmazione Procedurale in Linguaggio C++ 21
Lettura da File
void carica (lista &l, string nomeFile){
int i;
ifstream inFile(nomeFile.c_str());
i = 0;
while (inFile >> l.valori[i] && i < MAXDIM){
i++;
}
l.indicatore = i;
inFile.close();
return;
}
Strutture di Dati: Lista >> Gestione dei File
i conta il numero di valori prelevati dal file
all’indicatore viene assegnato il risultato del conteggio
Stampa su File
void salvaSuDisco (lista l, string nomeFile) { int i;
ofstream outFile(nomeFile.c_str());
for (i = 0; i < l.indicatore; i++) { outFile << l.valori[i] << endl;
}
outFile.close();
return;
}
Strutture di Dati: Lista >> Gestione dei File
G. Mecca - Programmazione Procedurale in Linguaggio C++ 23
Lista di Record
m
Nel caso degli studenti universitari
ðanche qui posso utilizzare entrambe lesoluzioni
m
Attenzione
ðin questo caso uso una lista di record ðmischio input formattato e non formattato ðdevo gestire correttamente le ignore()
Strutture di Dati: Conclusioni >> Gestione dei File
Lista di Record
void carica(listaStudenti &studenti, string nomeFile){
int i;
ifstream inFile (nomeFile.c_str());
i = 0;
while (inFile >> studenti.dati[i].matricola &&
i < MAXDIM){
flussoDiLettura.ignore();
getline(flussoDiLettura, studenti.dati[i].cognome);
getline(flussoDiLettura, studenti.dati[i].nome);
flussoDiLettura >> studenti.dati[i].annoCorso;
i++;
}
studenti.indicatore = i;
return;
}
Strutture di Dati: Conclusioni >> Gestione dei File
G. Mecca - Programmazione Procedurale in Linguaggio C++ 25
Lista di Record
m
Attenzione
ðle operazioni sui file sono spesso fonte di eccezioni
m
Esempi
ðtentativo di lettura da un file inesistente ðfile che non rispetta il formato stabilito
ðvalori che non rispettano i vincoli (es: anno di corso < 0)
Strutture di Dati: Conclusioni >> Gestione dei File
Lista di Record
m Alcuni di questi casi
ðpossono essere gestiti con tecniche simili a quelle usate per inserimenti e cancellazioni
ðparametri booleani di esito
m Ma in altri casi
ðil meccanismo non è sufficientemente efficace ðes: come gestire un file non esiste ?
ðcaso generale: interazione con sistemi esterni
ðserve un meccanismo più sofisticato per la gestione degli errori e delle condizioni eccezionali (>>)
Strutture di Dati: Conclusioni >> Gestione dei File
G. Mecca - Programmazione Procedurale in Linguaggio C++ 27
Riassumendo
m
Ricapitolazione
m
Passaggio dei Parametri
m
Gestione dei File
Strutture di Dati: Conclusioni >> Sommario
Termini della Licenza
m This work is licensed under the Creative Commons Attribution- ShareAlike License. To view a copy of this license, visit
http://creativecommons.org/licenses/by-sa/1.0/ or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.
Termini della Licenza
m Questo lavoro viene concesso in uso secondo i termini della licenza “Attribution-ShareAlike” di Creative Commons. Per ottenere una copia della licenza, è possibile visitare
http://creativecommons.org/licenses/by-sa/1.0/ oppure inviare una lettera all’indirizzo Creative Commons, 559 Nathan Abbott Way, Stanford, California 94305, USA.