Programmazione Mod A - Cap 5 prof. Burattini
1
La classe stream
Nel prossimo semestre introdurremo in modo più specifico i concetti di classe e
oggetto; per il momento possiamo semplicemente affermare che
una classe è la definizione di un nuovo tipo, che include sia gli elementi che lo
caratterizzano sia le operazioni eseguibili sugli elementi di quel tipo.
Supponiamo di dover lavorare con stringhe molto grandi; potremmo definire
una nuova classe (cioè un nuovo tipo) che chiamiamo string1. I nostri
programmi potranno contenere questo nuovo tipo, per cui possiamo
dichiarare una variabile string chiamata grande scrivendo semplicemente
string grande;
naturalmente dovremo definire su queste variabili tutte le operazioni già
definite per le stringhe.
La classe string avrà delle sue proprietà ( come inizializzazione, assegnazione,
….) e delle funzioni (dette metodi) che consentono di gestirla ( pensiamo, ad
esempio, alle operazioni di confronto, concatenazione, sottostringa, …….).
Programmazione Mod A - Cap 5 prof. Burattini
2
Il C++ contiene diverse librerie che permettono di utilizzare tipi che vanno al di
là di quelli elementari (int, float, char, bool): tra queste le classi string ( di cui
ci occuperemo in seguito) e stream.
La classe stream ( flusso ) è la base per l’I/O in C++.
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 (++) e decremento (--).
Programmazione Mod A - Cap 5 prof. Burattini
3
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.
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 <istream>, per quanto concerne l’input
ed in <ostream> per l’output;
se si ha la necessità di eseguire funzioni di lettura e scrittura si può includere il
Programmazione Mod A - Cap 5 4
file <fstream> che le contiene
entrambe.
prof. Burattini
I file di testo
File esterni : file immagazzinato in una memoria secondaria che possono essere
utilizzati da più di un programma.
File di tipo testo: file che contengono un testo, cioè caratteri ASCII.
Nome del file fisico: il nome con cui il file è noto nell’ambiente del sistema
operativo; di solito un file di testo ha estensione txt
Nome del file logico: il nome con cui il file è conosciuto dal programma; esso
viene gestito come una zona di memoria temporanea ( un buffer ) su
cui scrivere o leggere.
Un file di testo deve essere immaginato come una successione di caratteri
leggibili, inframezzati dal carattere speciale <eoln> ( end of line ) che indica
la fine di una linea di testo e terminante col carattere speciale <eof> ( end of
file ) che indica la fine del file
Programmazione Mod A - Cap 5 prof. Burattini
5
Supponiamo che il contenuto di un file di nome fisico prova.txt, che si trova sul
disco rigido sia:
Nel mezzo del cammin di nostra vita<eoln>
mi ritrovai in una selva oscura<eoln><eof>
Per scrivere questo testo è sufficiente utilizzare un qualsiasi editor (come lo
stesso sistema di sviluppo DevCpp oppure Blocco Note sotto Windows:
attenzione!! In quest’ultimo caso non aggiungere il suffisso txt, il
programma lo aggiunge di default ).
Per gestire un file in un programma C++ occorre:
1) dichiarare una variabile di tipo ifstream per la lettura del file o
di tipo ofstream per la scrittura del file ( tale variabile corrisponderà al
nome logico del file)
2) aprire il file creando una corrispondenza tra nome fisico e nome logico del
file
Mod A - Cap 5 3) leggere o scrivere i dati Programmazione
nel file.
prof. Burattini
6
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
temporaneamente 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 nuovi dati vengono prelevati dal file ed inseriti nel
buffer per essere letti successivamente.
Programmazione Mod A - Cap 5 prof. Burattini
7
Introduciamo, ora, le prime istruzioni necessarie alla gestione dei file.
Cominciamo con le dichiarazioni:
ifstream file1 ( per la lettura )
o
ofstream file2 ( per la scrittura )
dove file1 e file2 sono identificatori, cioè nomi logici di due file,
file1 è un oggetto della classe ifstream (stream di input),
file2 un oggetto della classe ofstream (stream di output).
Queste classi hanno i seguenti metodi (procedure o funzioni):
nome-variabile.open (nome file fisico)
ESEMPIO: file1.open(“prova1.txt”)
(questa procedura crea un collegamento tra il nome logico file1 ed il file fisico
prova1.txt presente nella memoria secondaria del computer in uso);
si può dichiarare ed aprire direttamente con la seguente istruzione
ifstream file1(“prova1.txt”)
Programmazione Mod A - Cap 5 prof. Burattini
8
La procedura close chiude il collegamento aperto con open tra il nome logico
file1 ed il file fisico prova1.txt presente nella memoria secondaria del
computer in uso:
nome-variabile.close ()
ESEMPIO:
file1.close()
Due funzioni molto utili.
nome-variabile.eof()
ESEMPIO: file1.eof()
restituisce true se tentiamo di leggere la fine del file, false altrimenti;
!(nome-variabile)
ESEMPIO: if (!file1) ….
controlla se il file nome-variabile esiste, oppure è stato aperto correttamente.
Gli ultimi due metodi introdotti hanno senso sia per la lettura che per la
scrittura di file.
Programmazione Mod A - Cap 5 prof. Burattini
9
Per poter leggere una stringa da file basta scrivere
file1 >> stringa
Si utilizza l’operatore di estrazione per “estrarre” dati dal file;
ricordiamo, comunque, che tale operatore legge una stringa fin quando trova
uno spazio o un carattere di fine linea o una tabulazione.
Il programma seguente utilizza diversi metodi applicati ai file. Esso legge i dati
da un file di testo e li scrive sul monitor ( ci si può servire del testo scritto in
prova.txt ).
Programmazione Mod A - Cap 5 prof. Burattini
10
#include <iostream> //
PROGRAMMA 5.1
#include <cstdlib>
#include <fstream>
using namespace std;
int main () {
char Nomefile[20], parola1[10];
ifstream file;
cout << "Nome File=";
cin >> Nomefile; // nome file esterno conservato nella memoria secondaria
file.open (Nomefile); // collegamento tra file (logico) e Nomefile(fisico)
if (!file) //collegamento impossibile (file fisico inesistente)
{ cerr<<"Non si puo’ aprire il file"<<endl;
system(“pause”);
return -1;// esce dal main con errore ( restituisce un numero diverso da 0
}
while (!file.eof()) // finché non si raggiunge la fine del file
{ file >>parola1;
// leggi una parola dal file
cout<< parola1<< " ";// scrivi la parola ed uno spazio sul monitor
}
file.close(); // chiudi il file
system(“pause”);
}
Programmazione Mod A - Cap 5 prof. Burattini
11
Invece di verificare se si è giunti alla fine del file, si può controllare direttamente
se esistono ancora parole da leggere con l’istruzione
file>>parola1
In tal caso le istruzioni evidenziate in grassetto possono essere sostituite dalle
seguenti
while (file>>parola1)
cout<<parola1<<” “;
e vanno lette come
fin quando è possibile estrai dal file tutte le parole.
Questa modalità è quella più utilizzata nella lettura dei dati in C++.
Il file prova.txt contenente il testo
Nel mezzo del cammin di nostra vita<eoln>
mi ritrovai in una selva oscura<eoln><eof>
ha sullo schermo il formato seguente
Programmazione
A - Capin
5 -una selva oscura
Nel mezzo del cammin di nostra
vita mi Mod
ritrovai
prof. Burattini
12
Il programma legge parola per parola ( in quanto si ferma ad ogni spazio o fine
riga );
l’istruzione cout << parola1 << “ “ pone uno spazio dopo ogni lettura della
variabile parola1.
Ci proponiamo di scrivere due programmi, abbastanza simili a quello appena
discusso, che leggono e stampano il file d’esempio prova.txt. Il primo legge
e stampa sul video ogni singolo rigo, mentre il secondo esegue le stesse
operazioni utilizzando il singolo carattere. Dal punto di vista dell’utente che
guarda il risultato sul monitor del computer non cambia nulla: il secondo
programma, infatti, invierà al video anche i caratteri non stampabili, come
il ritorno a capo.
Il primo programma usa la procedura
Nome-variabile.getline(stringa,numero,carattere)
dove stringa è la stringa letta dal file, numero è il numero massimo dei caratteri
letti, carattere è il carattere di terminazione; se quest’ultimo è omesso,
allora s’intende per default il carattere di fine riga.
Programmazione Mod A - Cap 5 prof. Burattini
13
ESEMPIO 1:
file1.getline(rigo,100);
attende di leggere da file1 la variabile stringa rigo contenente al massimo 100
caratteri; la lettura termina alla fine del rigo ( fino a <eoln> ) o quando ha
letto tutti i caratteri;
file1.getline(rigo,100,’@’);
legge ancora la stringa rigo contenente al massimo 100 caratteri, ma la lettura
termina quando incontra il carattere ’@’.
ESEMPIO 2:
while (file.get(ch))
cout.put(ch);
utilizza i metodi get e put che rappresentano rispettivamente i puntatori di
lettura e di scrittura da file di un singolo carattere.
Si esegue la stessa operazione di lettura e stampa precedente utilizzando, però,
il singolo carattere.
Programmazione Mod A - Cap 5 prof. Burattini
14
#include <iostream> //
PROGRAMMA 5.2
#include <cstdlib>
#include <fstream>
using namespace std;
int main () {
char Nomefile[50], riga[100];
ifstream file;
cout << "Nome File=";
cin >>Nomefile;
file.open (Nomefile);
if (!file) {
cerr<<"Non si puo’ aprire il
file"<<endl;
return -1;
}
while (!file.eof()) {
file.getline(riga,100);
cout<<riga<<endl;
}
file.close();
system(“pause”);
}
Programmazione Mod A - Cap 5 prof. Burattini
PROGRAMMA 5.3
Il programma ha la stessa identica
struttura di quello a lato; si
differenzia semplicemente per il
fatto che legge ogni singolo
carattere ( compreso l’end-of-line )
invece della riga.
L’unica differenza è nel riquadro
che comprende il ciclo while.
Una prima istruzione dichiara ch
come carattere, mentre la successiva
legge un carattere finché è possibile
e poi lo scrive su cout.
…………………………
…………………………
char ch;
while (file.get(ch))
cout.put(ch);
…………………………
…………………………
…………………………
15
In generale, un file di testo può essere letto con varie modalità.
Supponiamo di aprire il file prova.txt il cui primo rigo è il seguente
N e l
m e z z o
d e l
c a m m i n
d i
n o s t r a
v i t a
Quando il file si apre per la lettura il puntatore si pone sotto il primo carattere;
abbiamo la possibilità di eseguire tre tipologie di lettura:
leggiamo per parola (programma 5.1); in tal caso la parola letta conterrà “Nel”
ed il puntatore di lettura si sposterà sulla parola successiva;
eser5.1
leggiamo per rigo (programma 5.2); in questo caso viene letto tutto il testo “Nel
mezzo del cammin di nostra vita” contenuto nel primo rigo ed il puntatore
di lettura si sposta sulla riga successiva;
eser5.1b
leggiamo per carattere (programma 5.3); viene letto il carattere “N” ed il
puntatore di lettura si sposta per leggere il carattere successivo.
Programmazione Mod A - Cap 5 prof. Burattini
eser5.1c
16
Esempio
Si abbia un file di tipo testo, prova01.txt, contenente le seguenti informazioni
rispetto agli studenti di una certa università:
cognome e nome dello studente seguito dal simbolo di punto e virgola (;),
numero di matricola, 4 numeri interi che rappresentano il voto dei primi 4 esami
(lo zero indica che l’esame non è stato superato )
Scrivere un programma che, assegnata una media M in input, stampi il cognome,
nome e numero di matricola di tutti gli studenti che hanno una media
maggiore o uguale ad M.
Supponiamo, ad esempio, che i dati inseriti nel file prova01.txt siano i seguenti
de Rossi Mario;13240 28 25 0 24<eoln>
Caio Mario;15340 28 0 26 24
Bianchi Antonio;12540 26 20 30 25
Ferrara Ciro;13124 30 28 0 27
e che il valore di M in input sia 26, allora il programma deve stampare su video
Caio Mario 15340
Ferrara Giulio 13124
Programmazione Mod A - Cap 5 prof. Burattini
17
Per la risoluzione del problema iniziamo con un primo
raffinamento:
Leggi(media int)
Apri file prova01.txt
while non arriva la fine del file
Leggi da file il nome e cognome fino al simbolo ‘;’
Leggi da file la matricola
Leggi da file i 4 voti degli esami e calcola la loro media
Se la media calcolata è > di quella in input stampa cognome,
nome e matricola
Chiudi il file
Il raffinamento è già una soluzione, se si eccettua il passo
Leggi da file i 4 voti degli esami e calcola la loro media
Programmazione Mod A - Cap 5 prof. Burattini
18
Secondo raffinamento:
media=0; Numero_voti=0;
for (i=0; i<4; i++)
Leggi(file,voto)
if (voto >0)
media=media+ voto
Numero_votiNumero_voti +1
If Numero_voti0 Media=media/Numero_voti
Il programma completo è riportato di seguito.
Programmazione Mod A - Cap 5 prof. Burattini
19
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
using namespace std;
int main () {
char nome[30];
int matr, voto, Nvoti;
float somma, InpMedia;
ifstream file;
cout << "Input Media=";
cin >>InpMedia;
file.open ("prova01.txt");
if (!file) {
cerr<<"Non si può aprire il file"<<endl;
system("pause");
return -1;
}
while (!file.eof()) {
file.getline(nome,30,';');
file>>matr;
somma=0; Nvoti=0;
for (int i=0; i<4; i++) {
file>>voto;
if (voto>0) {
somma+=voto;
Nvoti++;
}
if (somma >0)&& (somma/Nvoti> InpMedia)
cout<<nome<<" "<<matr<<endl;
}
file.close();
Programmazione Mod A - Cap 5 system("pause");
prof. Burattini
}
20
Esercizi sui file di testo
1) Sia dato un file testo di nome fisico “studenti.txt“ contenente informazioni sugli
studenti di un corso.
Il primo rigo contiene il nome dello studente seguito dal carattere ‘|’ da uno spazio e da
un intero N indicante il numero di esami sostenuti.
Le N righe successive contengono le informazioni sugli esami sostenuti. Ognuna di
queste righe è composta da un intero rappresentante il codice dell’esame sostenuto,
un intero rappresentante il voto, e un intero rappresentante l'anno in cui l’esame è
stato superato.
Dati un intero C rappresentante un codice d’esame, un intero M rappresentante un voto
ed un intero N rappresentante un anno, scrivere un algoritmo che dia in output il
nome degli studenti che hanno sostenuto l’esame di codice C prima dell'anno N con
un voto>=M.
Esempio
Studenti.txt
Marco Rossi| 3<eoln>
3070 26 2001<eoln>
3080 24 2002<eoln>
3090 25 2000<eoln>
Antonio Sassi| 1<eoln>
3070 27 2002<eoln>
Input
Output
Programmazione Mod
A - Cap 5 21
prof. Burattini
3070 24 2002
Marco Rossi
2) Un file testo “parole.txt” contiene, per ogni riga, una serie di parole, ognuna
delle quali è seguita da uno spazio o dal carattere <eoln>. Ogni parola è
costituita da caratteri alfabetici e può essere composta da sole lettere
maiuscole, sole lettere minuscole o da entrambe.
Scrivere una procedura che legga il file “parole.txt” e costruisca due file.
Nel primo file andranno inserite, una per riga, le parole contenenti solo lettere
maiuscole; nel secondo andranno inserite, sempre una per riga, le parole
contenenti solo lettere minuscole. Le parole contenenti sia lettere maiuscole
che lettere minuscole non andranno memorizzate.
Esempio del file “parole.txt”
CASA libro DADO trENo <eoln>
mattone penna AUTO <eoln>
ROSA acqua raDIo <eoln><eof>
Il primo file sarà:
Il secondo file sarà:
CASA<eoln>
libro<eoln>
DADO<eoln>
mattone<eoln>
AUTO<eoln>
penna<eoln>
ROSA<eoln><eof>
acqua<eoln><eof>
Programmazione Mod A - Cap 5 prof. Burattini
22
3) Sia dato un file testo “parole.txt” composto da sole lettere maiuscole. Ogni
linea di testo è costituita da un carattere seguito da uno spazio e da una
serie di parole tutte separate da uno spazio (compreso l’ultima).
Tutte le parole di un rigo dovrebbero iniziare o terminare con il carattere di
inizio riga.
Scrivere una procedura che legga il file “parole.txt” e stampi a video tutte le
parole che non verificano la condizione suddetta.
Esempio del file “parole.txt”
M MONDO MARE <eoln>
O AGO NERO OTTOBRE <eoln>
P PANE PERA <eoln>
A CASA <eoln><eof>
In questo caso non deve essere stampata alcuna parola.
Esempio del file “parole.txt”
M MONDO GARE <eoln>
O OCA POLLO <eoln>
P PANE SERA <eoln>
F GATTO <eoln><eof>
In questo caso devono essere stampate le parole: GARE, SERA, GATTO
Programmazione Mod A - Cap 5 prof. Burattini
23
4) Siano dati due file testo: studenti.txt e tesi.txt. Il primo contiene informazioni
riguardanti tutti gli studenti di un corso di laurea; il secondo contiene
informazioni riguardanti i soli studenti del medesimo corso di laurea che
hanno già fatto richiesta della tesi.
Le informazioni per ogni studente sono così strutturate:
Studenti.txt
Studenti.txt
Tesi.txt
Matricola (intero)<eoln>
Cognome e nome<eoln>
Esami sostenuti (intero) Esami da sostenere (intero)<eoln>
Nome esame sostenuto^ voto (intero)<eoln>
…
Nome esame sostenuto^ voto (intero)<eoln>
Matricola (intero)<eoln>
Cognome e nome<eoln>
Entrambi i file sono ordinati per numero di matricola crescente.
Scrivere una procedura cheProgrammazione
mostri a video
matricola
e la media di tutti
Mod Ala- Cap
524 gli
Burattini
studenti che hanno richiesto laprof.
tesi
e che hanno svolto tutti gli esami.
ESEMPIO
Studenti.txt
Tesi.txt
4010<eoln>
Rossi Marco<eoln>
18 0<eoln>
…
Nome esame sostenuto^ 26<eoln>
4050<eoln>
Antonio Neri<eoln>
10 8<eoln>
…
Nome esame sostenuto^ 22<eoln>
4060<eoln>
Bianchi Matteo<eoln>
16 2<eoln>
…
Nome esame sostenuto^ 23<eoln><eof>
4010<eoln>
Rossi Marco<eoln>
4060<eoln>
Bianchi
Matteo<eoln><eof>
L’output sarà: 4010 seguito dalla media
Programmazione Mod A - Cap 5 prof. Burattini
25
La classe string: operazioni e proprietà
Ricordiamo che il tipo stringa, introdotto insieme agli array, non è altro che un
array di caratteri.
Abbiamo notato come questo tipo sia poco maneggevole.
Infatti, abbiamo dovuto introdurre delle procedure ad hoc per il confronto tra
stringhe e per il calcolo della loro lunghezza (ricordiamo che le stringhe
viste come array di carattere terminano con il carattere nullo’\0.
La classe string, contenuta nella libreria standard, consente una gestione molto
più semplice delle stringhe.
Programmazione Mod A - Cap 5 prof. Burattini
26
Per poter utilizzare il tipo string è necessario includere il file string:
#include <string>
Si può definire ed iniziare a leggere una stringa in vari modi:
string S1 ;
// S1 è una variabile stringa
string S2= “ciao mamma”; // S2 è una variabile stringa inizializzata con il
valore “ciao mamma”
string S3 =””;
// S3 è una stringa vuota
string S4 (“saluti”); // S4 è una stringa inizializzata con il valore
“saluti”
string S5 (S4);
// S5 è una stringa inizializzata con il valore di S4
(ancora”saluti”)
Programmazione Mod A - Cap 5 prof. Burattini
27
Si può leggere la stringa S1 da tastiera con le istruzioni
cin >> S1; //l’inserimento termina con lo spazio, il tasto Tab o Invio
cin.getline (S1,N) ; // l’inserimento termina soltanto con il tasto Invio
(è possibile inserire spazi tra le parole); si leggono al
massimo N caratteri.
cin.getline (S1,N, car); // l’inserimento termina quando si inserisce il
carattere car (se l’ultimo parametro car non
viene inserito, usa il tasto Invio come default)
Le stringhe definite col tipo string sono generate dinamicamente (non è
necessario definire una lunghezza massima), a differenza delle stringhe che
vengono definite come array di caratteri; esse, inoltre, possono essere
confrontate e concatenate:
String S1 = “ciao”, String S2 “mamma” possiamo scrivere S1=S1+S2 o S1+=S2
ottenendo in tutti i casi la stringa
“ciao mamma “
contenuta in S1
Programmazione Mod A - Cap 5 28
prof. Burattini
s [i]
s.size ( )
s.empty ( )
s.find( c )
s.find (str)
s.rfind ( c )
s.rfind (str)
s.replace (i, n, str)
s.insert (i, str)
s.erase (i, n)
s.resize (n,car)
s.c_str ( )
s.substr (i,n)
Restituisce il carattere di indice i ( se i>= della
lunghezza della stringa, il risultato è indefinito
Restituisce la lunghezza di s
Restituisce true se s è vuota, false altrimenti
Restituisce l’indice della prima occorrenza di c
Restituisce l’indice del primo carattere della prima
occorrenza di str
Come s.find( c ), solo che la ricerca ha inizio dalla fine
Come s.find(str), solo che la ricerca ha inizio dalla fine
Sostituisce n caratteri, a partire dalla posizione i, con la
stringa str.
Inserisce la stringa str a partire dalla posizione i
Elimina n caratteri a partire dalla posizione i
Fissa a n la lunghezza di s; gli altri caratteri fino alla
lunghezza della stringa sono riempiti con il carattere car
Restituisce la stringa corrispondente in stile C
Restituisce una stringa che parte dalla posizione i ed ha
lunghezza n; per esempio se s=”ciao mamma”,
s.substr(5,5) restituisce la stringa “mamma”
Programmazione Mod A - Cap 5 prof. Burattini
29
Scriviamo un programma che ci aiuti a comprendere l’uso dei metodi del tipo
string nella pratica.
Sia assegnato un file contenente un testo in cui alcune parole sono poste tra parentesi
quadre [ ].
Si richiede di generare altri due file:
il primo conterrà 4 puntini al posto di ogni parola tra parentesi quadre,
il secondo conterrà tutte le parole eliminate inserite nello stesso ordine in cui
compaiono nel file iniziale.
I due file generati devono avere un nome fisico dato dal nome del file iniziale a cui
va aggiunto rispettivamente “01” e “02”.
Programmazione Mod A - Cap 5 prof. Burattini
30
Esempio.
Supponiamo che il file di nome testo, senza estensione, abbia il seguente
contenuto:
Anche i file sono dei flussi e quindi appartengono alla
classe [stream]; la libreria per la loro gestione é contenuta
in <[istream]>, per quanto concerne l'input, ed in <[ostream]>
per l'output; se si ha la necessità di eseguire funzioni di
lettura e scrittura si puo' includere il file <[fstream]> che
le contiene entrambe.
Il programma deve creare due file, il primo di nome testo01 ed il secondo
testo02:
testo01
Anche i file sono dei flussi e quindi
appartengono alla classe ....; la libreria per
la loro gestione é contenuta in <....>, per
quanto concerne l'input ed in <....> per
l'output; se si ha la necessità di
eseguire funzioni di lettura e scrittura si
puo' includere il file
<....> Mod
che
le 5contiene
Programmazione
A - Cap
prof. Burattini
entrambe.
testo02
stream
istream
ostream
fstream
31
Il primo raffinamento dell’algoritmo risolutivo è il seguente:
Leggi(NomeFile)
Apri Nomefile in lettura
Apri NomeFile1 e NomeFile2 in scrittura
while non si raggiunge la fine del file
Leggi( rigo dal file)
S3 rigo
while non si raggiunge la fine di S3
J posizione della parentesi quadra aperta
K posizione di lettura sul rigo
If J>0
I posizione della parentesi quadra chiusa
If I>0
S2 tutto il contenuto incluso tra le due parentesi quadre
Scrivi S2 su NomeFile2
Rimpiazza nella stringa S3 tutto il contenuto incluso tra
Programmazione
Mod4Apunti
- Cap 5 32
le due parentesi
quadre con
prof. Burattini
L’algoritmo può essere facilmente tradotto in C++ utilizzando diversi metodi
della classe string senza la necessità di ulteriori raffinamenti.
Prima di scrivere il programma osserviamo che:
•
il nome del file fisico deve essere del tipo array di char;
•
la funzione c_str() applicata ad una stringa di tipo string restituisce una
stringa come array;
•
la stringa letta dal file deve essere una stringa di tipo array;
•
vengono utilizzati diversi metodi.
Programmazione Mod A - Cap 5 prof. Burattini
33
#include <iostream>
Anche i file sono
#include <fstream>
dei flussi e quindi
appartengono alla
#include <cstdlib>
fil1 classe [stream]; la
libreria per la loro
using namespace std;
gestione é
contenuta
int main () {
in <[istream]>,…..
string Nome1,Nome2, s01, s02, s2, s3;
char rigo[120];
Anche i file sono
int i,j,k;
stream
dei flussi e quindi
istream
ifstream fil1;
appartengono alla
…………
classe […….. ]; la
ofstream fil01, fil02;
libreria per la loro
fil02
fil01
gestione é
cout << "Nome File=";
contenuta
in <[……..]>,…..
cin >> Nome1;
Nome2=Nome1+".txt";
fil1.open(Nome2.c_str());
s01=Nome1+"01"; s02=Nome1+"02";// creazione dei nomi dei file di output
fil01.open(s01.c_str());
fil02.open(s02.c_str());
if (!fil1) { //controlla se il file esiste
cerr<<"Non si può aprire il file"<<endl;
system("pause");
return -1;
Programmazione Mod A - Cap 5 34
prof. Burattini
}
//l'algoritmo presentato nel primo raffinamento a partire da:
Anche i file sono
// Finché non si raggiunge la fine del file
dei flussi e quindi
appartengono alla
while (!fil1.eof())
fil1 classe [stream]; la
{
libreria per la loro
gestione é
fil1.getline(rigo,100);
contenuta
s3=rigo;
in <[istream]>,…..
k=0;
// Finché non si raggiunge la fine del rigo
Anche i file sono
while (k!=s3.size()) {
stream
dei flussi e quindi
istream
j=s3.find('[');
appartengono alla
…………
classe […….. ]; la
k=j+1;
libreria per la loro
fil02
fil01
gestione
é
if (j>=0) {
contenuta
i=s3.find(']');
in <[……..]>,…..
k=i+1;
if (i>0) {
s2=s3.substr(j+1,i-j-1);
fil02<<s2<<endl;
s3.replace(j, i-j+1,"....");
}
// termine algoritmo
}
fil1.close(); // chiusura dei file
else
fil01.close();
k=s3.size();
fil02.close();
}
system("pause");
35
fil01<<s3<<endl; // scrivoProgrammazione
s3 su fil01 Mod A - Cap 5 - }
prof. Burattini
}
……………………………………………………………………………………………………………………………………
in <[istream]>, per quanto concerne l'input, ed in <[ostream]>
……………………………………………………………………………………………………………………………………
j
i
k
j
k
i
k
k
eser5.5
Programmazione Mod A - Cap 5 prof. Burattini
36
Template di funzioni.
Durante questo corso abbiamo sottolineato l’aspetto astratto della
programmazione; spesso abbiamo introdotto delle procedure, scritte nel
linguaggio di progetto, che consentono di risolvere problemi generali che si
riferiscono a tipi generici.
Assegnato un certo vettore v è semplice scrivere delle funzioni che lo leggono da
tastiera, lo stampano sul video, ne calcolano il minimo ed il massimo, lo
moltiplicano per uno scalare, e così via.
Ebbene, poiché possiamo avere vettori di interi, reali, caratteri, stringhe, ecc.
per ognuno di essi dobbiamo introdurre una function distinta: avremo una
function che legge da tastiera un vettore di interi, un’altra che legge un
vettore di reali, e così via.
Invece di scrivere tre funzioni distinte il C++ ci permette in questi casi di
dichiarare e definire una sola funzione abbastanza generale da accettare
tipi di dato diversi (ma sui quali opera allo stesso modo) .
Programmazione
Mod A di
- Cap
5Una tale dichiarazione sarà detta
un template
function.
prof. Burattini
37
La sintassi da utilizzare richiede la parola chiave template seguita dalla parola
class, posta tra i tag < class tipo> dove la variabile tipo rappresenta il tipo;
subito dopo segue la definizione della funzione:
template <class Tipo>
Tipo minimo (Tipo v[],
int n) {
int i,h=0;
for (i=1; i<n; i++) {
if (v[i]<v[h])
h=i;
}
return v[h];
}
Supponiamo di richiamare la funzione
con
S1:=minimo(S, 10)
dove S è un vettore che contiene al
massimo 10 stringhe; ebbene, la funzione
restituirà il valore minimo del tipo adatto,
una stringa. La funzione controllerà
soltanto la coerenza tra il Tipo restituito
ed il Tipo di cui è composto l’array.
Ovviamente, se x è un numero reale
double e D è un array di double, la
chiamata di funzione
x:=minimo(D, 10)
restituisce in x il minimo dell’array D di
double.
Programmazione Mod A - Cap 5 prof. Burattini
38
Il programma seguente mostra l’utilizzo dei Template con funzioni e procedure.
#include <iostream>
template <class Tipo>
#include <cstdlib>
void leggi (Tipo v[], int n) {
#include <string.h>
int i;
using namespace std;
for (i=0; i<n; i++) {
template <class Tipo>
cout<<"vettore["<<i<<"]=";
void leggi (Tipo[], int);
cin>>v[i];
template <class Tipo>
}
Tipo minimo (Tipo[], int);
}
int main () {
template <class Tipo>
int a[5], n;
Tipo minimo (Tipo v[], int n) {
string s[5];
int i,h=0;
cout<<" Lunghezza vettore intero ="; cin>>n;
for (i=1; i<n; i++) {
leggi(a, n);
if (v[i]<v[h]) h=i;
cout<<"Il minimo del vettore intero è
}
"<<minimo(a, n)<<endl;
return v[h];
cout<<" Lunghezza vettore stringa ="; cin>>n;
}
leggi(s, n);
cout<<"Il minimo del vettore stringa è
"<<minimo(s, n)<<endl;
system("pause");
Programmazione Mod A - Cap 5 39
}
prof. Burattini
eser5.6
// continua a lato
Scarica

ppt