1
/* Esempio di lettura, confronto e scrittura in un array contenuto in un
record a sua volta contenuto in un array di record*/
struct Tdati {
int numeri[4];
char lettere[5];
};
Tdati dati[30];
numeri[4]
dati[30]
2
3
1
lettere[5]
6
A B
G D K
2
/* Esempio di lettura, confronto e scrittura in un array contenuto in un record a
sua volta contenuto in un array di record*/
struct Tdati {
int main () {
char lettere[20];
cout<<"\nCarica interi per riga ";
int numeri[4]; };
Inserimento (dati, elemArray);
Tdati dati[30];
Stampa(dati, elemArray);
// PROTOTIPI
confronta(dati, elemArray);
void Inserimento(Tdati [], int);
system("pause");
void Stampa(const Tdati [], int);
}
void confronta(Tdati [], int);
int elemArray=4;
void Inserimento (Tdati dat1[], int ndat)
{ for (int j=0;j<ndat;j++)
{ cout<<endl;
for (int i=0;i<ndat;i++)
{cout<<" A["<<j<<"]= ";cin>>dat1[j].numeri[i]; }
cout << "lettere ="; cin >> dat1[j].lettere;
}
}
3
/* Esempio di lettura, confronto e scrittura in un array contenuto in un record a
sua volta contenuto in un array di record*/
struct Tdati {
char lettere[20];
int main () {
int numeri[4]; };
cout<<"\nCarica interi per riga ";
Tdati dati[30];
Inserimento (dati, elemArray);
// PROTOTIPI
Stampa(dati, elemArray);
void Inserimento(Tdati [], int);
confronta(dati, elemArray);
void Stampa(const Tdati [], int);
system("pause");
void confronta(Tdati [], int);
}
int elemArray=4;
void Stampa(const Tdati dat1[], int ndat) {
for (int j=0;j<ndat;j++)
{cout<<"\n riga "<<j<<--"<<dat1[j].lettere<<" ** ";
for (int i=0;i<ndat;i++)
{ cout<<dat1[j].numeri[i]<<" "; }
}
}
4
void confronta(Tdati dat1[], int ndat)
int main () {
{
cout<<"\nCarica interi per riga "
char lettere2[20]; int ass[ndat];
Inserimento (dati, elemArray);
bool flag; int cont=0;
Stampa(dati, elemArray);
cout <<"\n\n Lista numeri da confrontare "<<endl; confronta(dati, elemArray);
for (int y=0;y<ndat;y++) cin>>ass[y];
system("pause");
cout<<"\n\nlettere da confrontare ";cin>>lettere2; }
for (int j=0;j<ndat;j++)
{ if (strcmp(dat1[j].lettere,lettere2)==0)
cout<<"\n La lettere in posizione "<<j<<" coincide con quella assegnata"<<endl;
else cont++;
flag=true;
int i=0;
while ((i<ndat)&&(flag==true))
{ if (dat1[j].numeri[i]!=ass[i])flag=false;
i++; }
if (flag==true)
cout<<" riga "<<j<<" numeri uguali "<<endl;
if (cont==ndat)cout<<" non ci sono stringhe uguali "<<endl;
}
if (flag==true) cout<<" non ci sono sequenze di numeri uguali "<<endl;
5
array
rec1
}
Esercizi
1) Utilizzando la struttura Tpersona, definita nell’esempio aggiungere
al menù la voce cancellazione di un record: la function da scrivere
deve prima ricercare l’elemento da cancellare (con la funzione Ricerca)
e, successivamente, cancellarlo dall’array di record .
2) Definire la struttura impiegato che, oltre a tutti i dati già contenuti in
Tpersona, ha:
data di assunzione;
livello ( operaio, impiegato, dirigente, ….);
stipendio annuo percepito l’anno precedente.
Utilizzando il programma proposto nell’esempio, apportare le
necessarie modifiche per gestire i dati della struttura impiegato (
inserimento, ricerca, stampa ).
6
Esercizi
3) Utilizzando la struttura Tpdata già definita, scrivere una procedura,
SommaData che, assegnata una data ed un numero di giorni,
restituisca, in formato gg mm aa, la somma tra la data ed il numero di
giorni (si supponga che i mesi siano tutti di 31gg).
Ad esempio
SommaData applicata alla data 13 5 11 e 124 giorni deve restituire la
data 13 9 11
7
Esercizi
.
4) Definire una struttura Orario che comprenda giorni, ore ( da 0 a 23 ), minuti e
secondi rappresentato nel formato seguente: gg hh mm ss.
Scrivere due procedure, SommaTempo e SottraiTempo, che, assegnati due tempi
espressi in termini di numero di giorni, ore, minuti ed secondi, restituiscano, in
formato coerente, rispettivamente la somma e la sottrazione tra i due tempi (sottraendo
il tempo più lungo da quello più breve).
Ad esempio
SommaTempo applicata all’orario hh 13 mm 45 ss 23 e 224 secondi deve restituire
l’orario hh 13 mm 49 ss7
Altro esempio
SommaTempo applicata all’orario gg 2 hh 48 mm 10 ss 70 sommato a hh 23 mm
48 ss 50
Restituisce gg 5 hh 0 mm 0 ss 0
Mentre SottraiTempo
Restituisce gg 3 hh 0 mm 22 ss 20
8
orario2
9
Un accenno alla programmazione a oggetti.
Oggetti: persone, animali, piante, automobili, aerei, palazzi, computer
e quant'altro.
Gli uomini pensano in termini di oggetti.
Possiamo suddividere gli oggetti in due grandi categorie: oggetti
animati e inanimati. I primi sono vivi, si muovono e intraprendono
azioni, al contrario dei secondi.
Entrambi i tipi di oggetti hanno una caratteristica in comune:
gli attributi, come la dimensione, la forma, il colore e il peso.
Hanno tutti dei comportamenti: una palla rotola, rimbalza, si gonfia o
si sgonfia; un bambino piange, dorme, gattona, cammina e sbatte le
palpebre; un'automobile accelera, frena e svolta; un asciugamano
assorbe l'acqua.
Noi studieremo i tipi di attributi e i comportamenti che caratterizzano
gli oggetti software.
10
La classe è un tipo definito dall’utente con annesse tutte le
operazioni e le proprietà che lo rendono adatto ai nostri scopi.
Gli oggetti sono le variabili di quel tipo: diremo anche che un
oggetto è un’istanza della classe.
Per conservare la modularità, è necessario che ogni oggetto esegua il
suo compito senza che l’utilizzatore conosca esattamente come ciò
avvenga.
Questo si verifica sicuramente con i tipi standard, int e float: infatti
noi eseguiamo tutte le operazioni del caso senza necessariamente
sapere come esse sono implementate.
11
In C l'unità di programmazione è la funzione.
In C++ l’unità è la classe, da cui eventualmente si istanziano
(creano) gli oggetti.
La relazione fra classi e oggetti può essere esemplificata nel modo
seguente:
il progetto di un’auto sta all’automobile allo stesso modo in cui la
classe sta ad un oggetto.
Infatti, è possibile costruire parecchie automobili partendo dallo
stesso progetto e, allo stesso modo, possiamo istanziare parecchi
oggetti da una sola classe.
Non si può correre, frenare o girare con l’auto di un progetto : si può
solo correre, frenare o girare con un’auto vera.
12
Le strutture, utilizzabili con la parola chiave struct, hanno
permesso di definire vari tipi, come studente, anagrafe, data etc.,
che si servono sia di tipi elementari che di altre strutture.
Così come accade per i tipi int e float, sarebbe auspicabile poter
definire delle operazioni anche per strutture tipo la struct studente.
In questo caso, per esempio, potremmo avere, come operazioni la
lettura e scrittura dei dati dello studente, il calcolo della media dei
voti e delle tasse pagate fino ad un certo periodo, e così via.
È, quindi, evidente che è necessario introdurre un nuovo costrutto
che inglobi in sè sia i dati che le operazioni.
A tal fine si introduce un nuovo tipo utilizzando la parola chiave
class.
13
La nozione di classe e oggetti
• Tipo: l’insieme dei valori che può assumere una
variabile (semplice o strutturata) e l’insieme delle
operazioni che possono applicarsi a tali valori
operatoreA
var
Tipo1
operatoreB
Tipo2
Tipo3
• Classe: la definizione di un tipo esteso che racchiude
sia i valori che lo caratterizzano (proprietà o
attributi), sia gli operatori che agiscono su quei valori
(metodi)
classeA
oggetto
metodo1
prop1
metodo2
prop2
prop2
14
Vantaggi delle classi
classeA
• Incapsulamento dati
– I metodi come unico punto di accesso
(interfaccia) alle sue proprietà
metodi
prop1
prop2
prop3
prop4
metodi
– Lo stato di un oggetto (l’insieme delle sue
proprietà) può essere modificato solo
attraverso l’interfaccia progettata
(Oscuramento/Protezione dati)
15
Gli oggetti stream
• Uno stream è un'astrazione, che rappresenta un
"qualcosa" da o verso cui "fluisce" una sequenza di bytes
STREAM
– può essere interpretato come un "file intelligente" (con
proprietà e metodi), che agisce come "sorgente" da cui
estrarre (input), o "destinazione" in cui inserire (output)
i dati
• Esempi di stream:
– Input da tastiera, output a schermo
– File in lettura, file in scrittura
– Buffer
– Canali di trasmissione di rete
16
Gli oggetti stream
• Un concetto importante è la posizione corrente in uno
stream (file position indicator), che coincide con
l'indice del prossimo byte che deve essere letto o
scritto
STREAM
c
i
a
o
– Ogni operazione di I/O modifica la posizione
corrente
– La posizione corrente può essere ricavata o
modificata direttamente usando particolari metodi
17
Gli oggetti stream
• Gli oggetti stream sono organizzati secondo una
gerarchia di classi dette genericamente stream
– Ogni classe è specializzata per tipo di operatori
di input e output supportati e per il tipo delle
sorgenti e destinazioni (file, I/O, stringhe, etc.)
ios_base
ios
<iostream>
cin
istream
cout
<ofstream>
<ifstream>
ifstream
ostream
iostream
ofstream
<fstream>
fstream
18
Gli oggetti stream
• cin e cout sono oggetti (globali) rispettivamente delle classi
istream e ostream di cui conosciamo già alcuni metodi:
cin>>dato; (operatore di estrazione)
cin.getline(char s[], int n, char c=’\n’)
ios_base
cout<<dato; (operatore di inserimento)
cout.width(ampiezza);
cout.precision(cifre);
<iostream>
cin
L’operatore punto (.)
serve a selezionare un
metodo di un oggetto
ios
istream
cout
ostream
<fstream>
ifstream
iostream
ofstream
fstream
19
I file binari
Abbiamo ora la necessità di conservare i dati sul disco per non doverli
riscrivere ogni volta che il programma viene eseguito.
Per gestire le strutture in maniera diretta, introduciamo i file binari.
Ricordiamo che il nome fisico di un file è il nome del file sul disco
come è visto dal sistema operativo; il nome logico, invece, è il nome
con cui viene gestito dal programma.
Il legame tra file fisico e file logico è dato dal metodo open applicato
all’oggetto file:
File1.open(Disney, modalità di accesso)
File1=nome file logico
Disney=nome file fisico (es.”pippo.dat”)
20
La classe stream ( flusso ) è la base per l’I/O in C++.
Come precedentemente accennato essa è formata da una sequenza di
byte che fluiscono da un dispositivo all’altro, da cui il termine
stream.
La sequenza di byte può fluire dalla tastiera alla memoria centrale del
computer: abbiamo così l’input standard, l’oggetto cin, che è un
oggetto stream.
Analogamente, l’oggetto cout rappresenta l’output standard, il flusso di
dati dalla memoria centrale al monitor.
Agli oggetti cout e cin abbiamo applicato, rispettivamente, gli operatori
di inserimento << e di estrazione >>, un po’ come accade ai numeri
interi di tipo int a cui applichiamo gli operatori di incremento 21(++) e
decremento (--).
Questi oggetti possono essere gestiti da altri metodi (procedure e
funzioni) cui si accede mediante il punto (.), che rappresenta la
selezione di un metodo dell’oggetto; per esempio, per leggere
una stringa s dalla tastiera scriviamo
cin.getline(s,100);
dove cin è l’oggetto, getline il metodo, s la variabile stringa letta
dalla tastiera;
il punto che separa cin da getline indica che quel metodo
appartiene a quell’oggetto.
22
Oltre agli oggetti cin e cout, il file <iostream> contiene anche
l’oggetto cerr ;
cerr è associato al dispositivo di errore standard per cui, se si
verifica un errore di I/O, esso viene immediatamente notificato
all’output standard (vedi esempio nel paragrafo successivo).
Anche i file sono dei flussi e quindi appartengono alla classe
stream; la libreria per la loro gestione è contenuta in
<ifstream>, per quanto concerne l’input ed in <ofstream> per
l’output;
se si ha la necessità di eseguire funzioni di lettura e scrittura si può
includere il file <fstream> che le contiene entrambe.
23
Una volta creata la corrispondenza tra file fisico e file logico, il
sistema operativo si occuperà di travasare i dati dall’uno
all’altro.
Quando ordiniamo di scrivere sul file logico, i dati inviati vengono
memorizzati in una zona di memoria temporanea connessa al
file stesso. Nel momento in cui tale zona di memoria viene
riempita oppure il file viene chiuso, allora il computer
provvederà ad inviare tutti i dati al file fisico.
Analogamente, nella fase di lettura, il computer legge dal file fisico
una quantità di dati tale da riempire il buffer (oppure legge
tutti i dati del file se questi sono in quantità inferiore alla
lunghezza del buffer); ogni istruzione di lettura successiva
continuerà a leggere dati dal buffer finché esso non si svuota;
a quel punto i nuovi dati vengono prelevati dal file ed inseriti
24
nel buffer per essere letti successivamente.
LA SINTASSI DEI FILE BINARI
File1.open(nome file fisico, modalità di accesso)
dove
File1 è una variabile di tipo fstream ,
.
nome file fisico è il nome, comprensivo del path, con cui è
conosciuto dal sistema operativo,
modalità di accesso può assumere uno dei seguenti valori
Modalità
di accesso
ios::in
Descrizione
ios::out
Apre il file per la scrittura
ios::ate
Apre il file posizionandosi alla fine del file.
ios::app
L’output viene aggiunto alla fine del file
ios::trunc
Se il file esiste viene cancellato scrivendoci sopra
ios::binary
Accesso in modalità binaria
Apre il file per la lettura
25
La classe ios è la capostipite di tutte le classi di I/O.
Tutte le altre classi di I/O come
ifstream, ofstream, fstream, …….
derivano da essa.
Per poter utilizzare questa proprietà è necessario servirsi del
namespace della classe, ios, seguito dall’operatore di scope:: per cui,
ad esempio, la scrittura
ios::in
indica che il file sarà aperto soltanto in lettura, che è la modalità
standard per i file dichiarati come ifstream.
Si possono combinare varie modalità di accesso con l’operatore | (OR )
tra bit.
Per esempio, la modalità di default di apertura di un file in scrittura è
ios::out | ios::trunc
perché in un file di tipo ofstream si può scrivere soltanto dopo aver
cancellato tutto in quanto il puntatore di scrittura si dispone ad inizio
26
file.
Oltre le classi ifstream e ofstream esiste la classe fstream che
consente di aprire un file sia in lettura che in scrittura; alcuni
compilatori aprono un file di tipo fstream con le seguenti modalità di
default
ios::in | ios::out
I file di testo, sono gestiti in maniera sequenziale: per ricercare un
dato è necessario scorrere tutte le celle iniziando dalla prima, mentre
l’inserimento di un dato può avvenire soltanto alla fine.
.
27
Il C++ gestisce anche i file ad accesso diretto in cui è possibile
posizionarsi in qualsiasi punto all’interno di essi.
Per questo tipo di file sono necessari due puntatori, uno che indica la
posizione di lettura ed un altro quello di scrittura.
Ci sono inoltre funzioni che consentono di leggere e scrivere in una
qualsiasi posizione all’interno del file.
Questi file, che hanno una struttura profondamente diversa dai file di
testo, sono detti file binari.
28
I file binari possiedono due puntatori, uno in lettura ed uno in
scrittura, che si posizionano esattamente nel punto successivo in cui
va effettuata l’operazione; il puntatore di lettura punta al prossimo
elemento da leggere, il puntatore di scrittura punta alla locazione in
cui va scritto il successivo elemento.
Quanto detto vale non solo per i file ma per qualsiasi stream, per cui
si utilizzano spesso i termini
get stream pointer
per il puntatore di lettura e
put stream pointer
per quello di scrittura.
Per questa ragione, le funzioni che leggono i dati hanno un carattere
g(et) alla fine, mentre le funzioni di scrittura hanno una lettera p(ut).
29
Le funzioni da utilizzare per posizionare il puntatore all’interno del
file binario sono le seguenti:
Funzioni (metodi)
tellg()
Descrizione
tellp()
Anche questo metodo non richiede parametri;
ritorna un intero che rappresenta la posizione del
puntatore di scrittura
Questo metodo non richiede parametri; ritorna un
intero che rappresenta la posizione del puntatore
di lettura
seekg(long pos) Questo metodo posiziona il puntatore di lettura
nella posizione pos
Ricordiamo che la posizione parte dal valore 0
seekp(long pos) Questo metodo posiziona il puntatore di scrittura
nella posizione pos
30
I due metodi, seekg e seekp, possono essere sovraccaricati con altre due
.
funzioni che stabiliscono anche la direzione in cui muovere il puntatore:
seekg( long pos, direzione)
seekp( long pos, direzione)
dove direzione può assumere uno dei valori seguenti
Direzione
Descrizione
ios::beg
Il valore del parametro pos è calcolato dall’inizio del
file ( è la condizione di default )
ios::cur
Il valore del parametro pos è calcolato dalla
posizione corrente
ios::end
Il valore del parametro pos è calcolato dalla fine del
file e quindi, se si vuole leggere, deve essere un
numero negativo
31
Scarica

ppt