+ All Categories
Home > Documents > In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi,...

In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi,...

Date post: 01-May-2015
Category:
Upload: fiorenza-giovannini
View: 213 times
Download: 0 times
Share this document with a friend
58
Transcript
Page 1: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.
Page 2: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file è ad esempio dichiarato di interi esso non può contenere che interi.Tutti i file di tipo non-testo sono detti file binari.

La estensione di un file testo è NomeFile.txtLa estensione di un file binario è NomeFile.dat

La sintassi di un file binario è diversa da quella di un file testo.

identificatore = FILE OF type

Page 3: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROGRAM FileTesto(output, Teresa);VAR

Teresa:text;Ch:char;

BEGINEND.

PROGRAM FileBinari(output, Ints,Reals,Records);TYPE String30=STRING[30];

NameType=RECORDFirst,Middle,Last:String30;

END; IntsFile=FILE OF integer; RealsFile=FILE OF real; RecFile=FILE OF NameType;VAR

Ints:IntsFile;Reals:RealsFile;Names:RecFile;

BEGINEND.

Preparazione alla lettura del filereset(NomeFile) es. reset(Reals)

Preparazione alla scrittura del filerewrite(NomeFile) es. rewrite(Reals)

Page 4: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Il controllo di fine file viene eseguito come per i text file con la funzione <eof> eof(NomeFile)

Essendo i dati scritti uno di seguito all’altro non esiste più l’<eoln>.

Nel caso del RecFile i record NameType=RECORD

descritti da First,Middle,Last:String30;

avremo

La lettura avviene record per record, non stringa per stringa

Giulio Luca Rossi Carlo Maria Bianchi Gian Giacomo Verdi ……………..……………..

Carlo Maria Bianchi

Area Dati

AName.First CarloAName.Middle MariaAName.Last Bianchi

Page 5: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

E’ possibile leggere anche più di un valore alla volta da un file.Esempio

read(Reals, R1, R2, R3,….)

Per leggere un intero file si può far uso dell’ <eof>Esempioreset(Ints);WHILE NOT eof(Ints) DO

BEGINread(Ints, Intero);elabora(Intero)

END;

L’uso dell’ <eoln> produce un errore di sintassi.

Page 6: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

E’ possibile scrivere in un file binario se ovviamente è stato preparato per la scrittura.Esempiowrite(Ints, AnInt, 3*AnInt);write(Reals, Re1, 3.1416);write(Names, AName);write(Names, Name1, Name2);

Come si vede anche più di un dato può contemporaneamente essere scritto in un file binario.

Attenzione !!!Ogni elemento che si scrive deve essere dello stesso Type del file.Quindi sono sbagliate le scritture del tipowrite(Ints, Re1, 3.2*Re1);write(Reals, AnInt, AnInt DIV 2);write(Names, Aname.First, Aname.Middle, Aname.Last);

Errore !!!!!!

Non essendoci <eoln> non è permesso il writeln.

TYPE String30=STRING[30];

NameType=RECORDFirst,Middle,Last:String30;

END; IntsFile=FILE OF integer; RealsFile=FILE OF real; RecFile=FILE OF NameType;VAR

Ints:IntsFile;Reals:RealsFile;Names:RecFile;

Page 7: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

COPIA DI FILE BINARI

Supponiamo di avere due file binary AFile e Bfile aventi lo stesso SomeType le cui componenti sono del tipo ComponentType.

WHILE NOT eof(Afile) DOread(Afile, Acomponent)write(Bfile, Acomponent)

PROCEDURE CopyFile(VAR InNames, OutNames:RecFile);VAR

AName:NameType; BEGIN

WHILE NOT eof(InNames) DOread(InNames, AName);write(OutNames, AName)

ENDEND;

Page 8: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Si noti che con una sola operazione di read o write si possono leggere molti valori contemporaneamente se questo è previsto dalla struttura dei file in gioco.Ad esempio un record con 20 campi può essere scritto con una sola operazione e non campo per campo.

Nel caso in cui si vogliono dare i valori di un record campo per campo, ad esempio da tastiera, allora si può adoperare la seguente procedura:

WITH RecordVar DOintroduci il valore del campo

write(OutFile, RecordVar)

Page 9: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROCEDURE WriteAName(VAR OutFile:NameFile);VAR

Aname: NameType;BEGIN

WITH Aname DOBEGIN

write(‘ First Name: ‘);readln(First);write(‘ Middle Name: ‘);readln(Middle );write(‘ Last Name: ‘);readln(Last );

END;write(OutFile, AName)

END;

TYPE String30=STRING[30];

NameType=RECORDFirst,Middle,Last:String30;

END; IntsFile=FILE OF integer; RealsFile=FILE OF real; RecFile=FILE OF NameType;VAR

Ints:IntsFile;Reals:RealsFile;Names:RecFile;

Page 10: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

TYPEStringa20 = STRING[20]

RisultatiArray =ARRAY[1..TotaleProve] OF integer;

AnagraficaRecord = RECORDCognome,Nome : Stringa20END;

DataRecord = RECORDGiorno,Mese,Anno : integerEND;

StuRecord = RECORD Anagrafe :AnagraficaRecord ;

Nascita:DataRecord ; Matricola :StringaNome; AnnoCorso:StringaNome; Risultati :RisultatiArray ; Media:real;

END;

Studente

Anagrafe Nascita Matricola

Cognome Nome AnnoMeseGiorno

AnnoCorso Risultati Media

CONST MaxStud=150;

TYPEStuRecord = RECORD……………….END;

ClassArray=ARRAY[1..Maxstud] OF StuRecord;StuRecFile=FILE OF StuRecord;VAR

InFile:StuRecFile;AClass: ClassArray;TotalStudents:integer;

Page 11: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Procedura per la costruzione di un Array di record a partire da un file binario.

PROCEDURE FillClass(VAR AClass: ClassArray; VAR TotalStudents: integer; VAR InFile: StuRecFile);

VARAStudent: StuRecord;

BEGINTotalStudents:=0;reset(InFile);WHILE NOT eof(InFile) DOBEGIN

TotalStudents:= TotalStudents+1;read(InFile, AStudent);Aclass[TotalStudents]:=AStudent

ENDEND;

Supponiamo di introdurre meno di MaxStud record

StuRecord = RECORD Anagrafe :AnagraficaRecord ;

Nascita:DataRecord ; Matricola :StringaNome; AnnoCorso:StringaNome; Risultati :RisultatiArray ; Media:real;

END;

Page 12: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

AGGIORNAMENTO DI FILE DI RECORD BINARI

Dati due File di record binari ordinati, fare il merge del primo nel secondo producendo un terzo file ordinato.

Corso ProgrammazioneSessione Estiva

CSPE99

Corso ProgrammazioneSessione Invernale

CSPI99

Corso ProgrammazioneCSP99

Semester OldMaster

NewMaster

merge Sessione StuRecord

Sessione StuRecord

StuRecord

MStuRec

MStuRec

Page 13: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Pseudo Codice di UpdateMerge

AssignFiles(LaSessione, Semester, OldMaster, NewMaster);

Merge(LaSessione, Semester, OldMaster, NewMaster);

Risultati(Semester,OldMaster,NewMaster);

writeln(' Fine aggiornamento ')END.

Page 14: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

MERGEPseudo codice

{Merge(LaSessione, Semester, OldMaster ,NewMaster}

prendi un record MStu1 da OldMaster {GetMasterRec(MStu1)}prendi un record MStu2 da Semester {GetSemesterRec(LaSessione,MStu2,Semester}

WHILE NOT sono finiti i due file DOwrite il record con “nome” più piccolo in NewMasterprendi un altro record dal file giusto {OldMaster o Semester}

copia gli ultimi record MStu1 e MStu2 in NewMaster {CopyLastTwo(MStu1,MStu2,NewMaster}

{CopyOldMasterRecs(OldMaster,NewMaster}copia ordinatamente i record dai file non esauriti in NewMaster

{CopySemesterRecs(LaSessione,Semester,NewMaster}Semester

OldMaster

NewMaster

StuRecord MStuRec

MStuRec

Page 15: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

CONSTTotaleProve=100;TYPEStringa4 = STRING[4];Stringa10 = STRING[10];Stringa25 = STRING[25];RisultatiArray=ARRAY[1..TotaleProve] OF integer;

StuRecord = RECORD Cognome, Nome : Stringa25;

Nascita:Stringa10; Matricola:Stringa10; AnnoCorso:Stringa4; Risultati:RisultatiArray; Media:real;

END;MStuRecord= RECORD

Sessione:Stringa25;Info:StuRecordEND;

StuRecFile= FILE OF StuRecord;MStuRecFile= FILE OF MStuRecord;VAR

LaSessione: Stringa25; {semestre appena finito}Semester: StuRecFile; {file semestre appena finito}OldMaster:MStuRecFile; {file preesistente}NewMaster : MStuRecFile; {file aggiornato}

StuRecord

Nascita MatricolaCognome Nome AnnoCorso Risultati MediaSessione

MStuRecord

Semester OldMaster

NewMaster

SessioneStuRecord

SessioneStuRecord

StuRecord

MStuRec

MStuRec

Page 16: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

AssignFiles

LaSessioneSemesterOldMasterNewMaster

Merge

LaSessioneSemesterOldMasterNewMaster

OldMaster

GetMasterRec

MStu1

GetSemesterRec

Semester MStu2

Stu1GoesFirst

writewrite

GetMasterRec GetSemesterRec

Vero Falso

MStu1.InfoMStu2.Info

OldMaster MStu1 Semester MStu2

NewMaterMStu1

NewMaterMStu2

CopyLastTwo

NewMaterMStu1MStu2

CopySemesterRecs

OldMasterNewMaster

CopyMasterRecs

SemesterNewMaster

Risultati

SemesterOldMasterNewMaster

Page 17: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROCEDURE AssignFiles(VAR LaSessione:Stringa25;VAR Semester:StuRecFile;VAR OldMaster, NewMaster : MStuRecFile);

{si legge la sessione da tastiera, si aprono i file Semester, OldMaster, in lettura e NewMaster in scrittura }VAR

CourseName, InvernaleOEstiva,Anno: Stringa25;BEGIN

write(' Nome corso= ');readln(CourseName); {es. PRO}write(' Sessione ("Invernale: i" o "Estiva: e")): ');readln(InvernaleOEstiva); {es. e}write(' Anno (due digiti): ');readln(Anno); {es. 00}LaSessione:= InvernaleOEstiva+ Anno; {es. e00}assign(Semester, CourseName+'e'+'.dat'); {es. PROe00.dat}IF InvernaleOEstiva='e' THEN

assign(OldMaster, CourseName+’i'+'00.dat')ELSE

assign(OldMaster, CourseName+'e'+'00.dat'); {es. PROe.dat}assign(NewMaster, CourseName+ InvernaleOEstiva +'new.dat'); {es. PROenew.dat}

reset(OldMaster);reset(Semester);rewrite(NewMaster)

END;

Semester OldMaster

NewMaster

SessioneStuRecord

SessioneStuRecord

StuRecord

MStuRec

MStuRec

Page 18: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROCEDURE Merge (LaSessione:Stringa25; VAR Semester:StuRecFile;VAR OldMaster, NewMaster : MStuRecFile);

VARAstu:StuRecord; {variabile record letta da Semester}MStu1, MStu2: MStuRecord; {variabile record letta da OldMaster e quella formata da AStu e LaSessione}BEGINGetMasterRec(MStu1,OldMaster);GetSemesterRec(LaSessione,MStu2,Semester);WHILE NOT eof(OldMaster) AND NOT eof(Semester) DOBEGIN IF Stu1GoesFirst(MStu1.Info,Mstu2.Info) THEN BEGIN write(NewMaster,MStu1); GetMasterRec(MStu1,OldMaster) END ELSE BEGIN write(NewMaster,MStu2); GetSemesterRec(LaSessione,MStu2,Semester) END;END; CopyLastTwo(MStu1,MStu2,NewMaster); CopyOldMasterRecs(OldMaster,NewMaster); CopySemesterRecs(LaSessione,Semester,NewMaster); close(Semester); close(OldMaster); close(NewMaster)END;

Semester OldMaster

NewMaster

SessioneStuRecord

SessioneStuRecord

StuRecord

MStuRec

MStuRec

MStuRecord= RECORDSessione:Stringa25;Info:StuRecordEND;

Necessario perché il Get... avviene dopo la write

Page 19: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROCEDURE GetMasterRec(VAR MStu:MStuRecord;VAR OldMaster:MStuRecFile);BEGINIF NOT eof(OldMaster) THEN

read(OldMaster,MStu)END;

PROCEDURE GetSemesterRec(LaSessione:Stringa25;VAR MStu:MStuRecord; VAR Semester:StuRecFile);BEGIN

IF NOT eof(Semester) THEN BEGIN read(Semester,MStu.Info); MStu.Sessione:=LaSessione ENDEND;

StuRecord

Nascita MatricolaCognome Nome AnnoCorso Risultati MediaSessione

MStuRecord

Semester OldMaster

NewMaster

SessioneStuRecord

SessioneStuRecord

StuRecord

MStuRec

MStuRec

Page 20: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

FUNCTION Stu1GoesFirst(Stu1,Stu2:StuRecord):boolean;BEGIN IF Stu1.Cognome<>Stu2.Cognome THEN Stu1GoesFirst:=Stu1.Cognome<Stu2.Cognome ELSE IF Stu1.Nome<>Stu2.Nome THEN Stu1GoesFirst:=Stu1.Nome<Stu2.Nome ELSE Stu1GoesFirst:=Stu1.Matricola<Stu2.MatricolaEND;

Stu1.Cognome<>

Stu2.Cognome

Stu1, Stu2

Stu1.Nome<>

Stu2.Nome

Stu1.Cognome<

Stu2.Cognome

Stu1.Nome<

Stu2.Nome

<>

=

<>

=

Vero

FalsoFalso

Vero

Vero

Stu1.Matricola<>

Stu2. Matricola

Falso

Page 21: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROCEDURE CopyLastTwo(MStu1,MStu2:MStuRecord;VAR NewMaster:MStuRecFile);BEGIN IF Stu1GoesFirst(MStu1.Info,Mstu2.Info) THEN BEGIN write(NewMaster,MStu1); write(NewMaster,MStu2) END ELSE BEGIN write(NewMaster,MStu2); write(NewMaster,MStu1) END;

END;

PROCEDURE CopyOldMasterRecs(VAR OldMaster, NewMaster:MStuRecFile);VAR AName:MStuRecord;BEGIN WHILE NOT eof(OldMaster) DO BEGIN read(OldMaster,AName); write(NewMaster,AName) ENDEND;

Page 22: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROCEDURE CopySemesterRecs(LaSessione:Stringa25; VAR Semester:StuRecFile;VAR NewMaster : MStuRecFile);

VAR MStu:MSTuRecord;BEGIN WHILE NOT eof(Semester) DO BEGIN read(Semester,MStu.Info); MStu.Sessione:=LaSessione; write(NewMaster,MStu) ENDEND;

Page 23: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROCEDURE Risultati (VAR SemFile:StuRecFile; VAR OldFile,NewFile :MStuRecFile);VAR NameSem:StuRecord; NameOld:MStuRecord; NameNew:MStuRecord; BEGIN writeln(' Semestre Old New '); WHILE NOT eof(NewFile) DO BEGIN

IF eof(SemFile) THEN BEGIN NameSem.Cognome:=' -- '; NameSem.Nome:=' -- ' END ELSE read(SemFile,NameSem); IF eof(OldFile) THEN BEGIN NameOld.Info.Cognome:=' -- '; NameOld.Info.Nome:=' -- ' END ELSE read(OldFile,NameOld) END; read(NewFile,NameNew); writeln(NameSem.Cognome:6,' ',NameSem.Nome:4,' ', NameOld.Info.Cognome:6,' ', NameOld.Info.Nome:4,' ', NameNew.Info.Cognome:6,' ', NameNew.Info.Nome:4); END; END;

Page 24: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Semestre Old Newagazzi carlo brescia ugo agazzi carlobottazzi anna distante claudio bottazzi annanapoli giulio livorno giulia brescia ugoperna claudio venezia anna distante claudiovenezia elena viterbo giorgio livorno giulia -- -- -- -- napoli giulio -- -- -- -- perna claudio -- -- -- -- venezia anna -- -- -- -- venezia elena -- -- -- -- viterbo giorgioFine aggiornamento

Page 25: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Pseudo codice per il Merge e Update di due file InFile1 InFile2

GetRec(Rec1,InFile1)GetRec(Rec2,InFile2)

WHILE NOT eof(InFile1) AND NOT eof(InFile2) DO

IF Rec1.Key < Rec2.Key THEN write(OutFile,Rec1) GetRec(Rec1,InFile1)ELSE write(OutFile,Rec2) GetRec(Rec2,InFile2)

CopyLastTwo(Rec1,Rec2,OutFile) CopyRemainder(InFile1,OutFile} CopyRemainder(InFile2,OutFile}

close all files

Page 26: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Esercizio

Scrivere due procedure:

•una per creare un file di tipo Semester e un file di tipo OldMaster

•una per leggere gli stessi file.

Page 27: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

I PUNTATORI

Allocazione StaticaDato un blocco ogni variabile è allocata in memoria quando inizia l’elaborazione del blocco e deallocata quando l’elaborazione di tutto il blocco termina.

Allocazione DinamicaQuando ogni variabile è allocata o deallocata in memoria durante l’elaborazione del blocco.

Il puntatoreUn puntatore è una variabile il cui valore rappresenta un indirizzo di memoria. Esso serve per creare o eliminare una variabile dinamica.

Variabile dinamicaE’ una variabile alla quale si assegna spazio in memoria durante l’elaborazione di un blocco.

Page 28: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

identificatore type= ^ESEMPIO

TYPE DataType = RECORD

Giorno:1..31;Mese:1..12;

Anno:integer END;DataPunt=^DateType;IntPunt=^integer;

VAROggi:DataPunt;A,B:IntPunt;Domani:DataType;

Si noti che la variabile Oggi, così come la variabile IntPunt, non assume i tre valori del record, o il valore di intero, a cui fa riferimento ma solo quello dell’indirizzo di memoria a partire del quale vi sono eventualmente i valori

Variabile Anonima: una variabile alla quale si accede solo tramite un puntatore

Variabile Nominata: una variabile alla quale si accede tramite un nome

Page 29: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Per assegnare un indirizzo a una variabile puntatore si usa la procedura new:es. new(Oggi)

TYPE DataType = RECORD

Giorno:1..31;Mese:1..12;

Anno:integer END;DataPunt=^DateType;IntPunt=^integer;

VAROggi:DataPunt;A,B:IntPunt;

Spazio di memoria assegnatoPrima di fare la chiamata new(Oggi)Oggi^ ?

Dopo la chiamata new(Oggi)Oggi^ ? ? ?

Per assegnare dei valori alla variabile dinamica Oggi

new(Oggi)Oggi^

read(Oggi^.Giorno, Oggi^.Mese, Oggi^.Anno)Enter 21 11 2000

Oggi^ .Giorno .Mese .Anno

? ? ?

21 11 2000

Page 30: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

TYPE DateType = RECORD

Giorno:1..31;Mese:1..12;

Anno:integer END;

DataPunt=^DateType;IntPunt=^integer;VAROggi:DataPunt;A,B:IntPunt;

new(A);new(B);new(Oggi);A^:=5;B^:=7;write(‘Dammi la data (giorno mese anno): ‘);WITH Oggi^ DO

readln(Giorno, Mese, Anno)

Dammi la data (giorno mese anno) : 21 11 2000

21 11 2000Oggi^

5A^

7B^

Page 31: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Gli unici operatori che si applicano alle variabili puntatori sono:

operatore di assegnazione :=

operatori booleani = <>

TYPE DataType = RECORD

Giorno:1..31;Mese:1..12;

Anno:integer END;DataPunt=^DateType;IntPunt=^integer;

VAROggi:DataPunt;A,B,C:IntPunt;Domani:DataType;

L’operazione C :=B

12C^

7B^

X garbage

7L’operazione A^ :=B^

5A^

7B^

12C^

Page 32: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

TYPEIntPunt=^integer;

VARA,B,C:IntPunt;

7A^

7B^

A^ : =5B^ := 7A^ :=B^IF (A^ = B^) AND (A <> B) THEN writeln(‘ I puntatori sono diversi ma i valori delle variabili puntate sono eguali’)

Page 33: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

TYPEIntPunt=^integer;

VARA,B,C:IntPunt;

C :=BIF (C = B) THEN writeln(‘ I puntatori puntano alla stessa variabile’)

12C^

7B^

X garbage

dispose(C)C :=BIF (C = B) THEN writeln(‘ I puntatori puntano alla stessa variabile’)

12C^

B^ ?

12C^

B^

Come eliminare la spazzatura

Page 34: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

In memoria esiste una speciale area detta run-time-heap dove sono allocate le variabili puntatore.

Nello heap ci sono le variabili puntatori create da new ad es. A B C D

Page 35: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Vi è un solo valore che una variabile puntatore può assumere e che non punta a nulla: NIL.

Es: D:= NIL;

Questa assegnazione serve per informare che per ora la variabile puntatore non è stata ancora associata a una variabile dinamica.

Si possono fare test per vedere se il puntatore è libero di essere associato ad una variabile dinamica.

Attenzione NIL non è assegnato per default.

L’istruzione C:=B mostra che possiamo assegnare memoria ad un puntatore senza fare uso di new questo ci permette di avere due puntatori che puntano alla stessa variabile dinamica, riducendo così lo spazio di memoria usato.

Possiamo quindi scrivere

new(B);B^:=18;B:=C Questa istruzione è valida solo se il puntatore C esiste.

Attenzione se a un puntatore è assegnato NIL, es. D:= NIL, non è possibile fare dispose(D).

Page 36: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Se abbiamo allocato memoria es.

new(D);D^:=5;D:= NIL

resta spazzatura

bisogna invece fare coem di seguito

new(D);D^:=5;dispose(D);D:= NIL;

NIL non elimina la spazzatura

Poichè possiamo assegnare memoria ad un puntatore senza fare uso di new questo ci permette di avere due puntatori che puntano alla stessa variabile dinamica, riducendo così lo spazio di memoria usato.

Page 37: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

ARRAY DI PUNTATORI

Anagrafe ClienteN Info

ClientRecord

Cognome Nome

CONSTMaxStu=100;TotaleProve=5;TYPE

String25=STRING[25];String10=STRING[10];String4=STRING[4];RisultatiArray=ARRAY[1.. TotaleProve] OF integer

StuRecord = RECORD Cognome, Nome: String25; Nascita: String10; Matricola:String10; Risultati:RisultatiArray; Media:real; END;

ClientesFile=FILE OF ClientRecord;ClientPointer=^ClientRecord;PointerArray=ARRAY[0..MaxClients] OF ClientPointer;

VARClientsOnFile:ClientsFile;ByName, ByNo: PointerArray;TotalStu:integer;

Supponiamo che i ClienteN siano stringhe di lunghezza 5 tutte piene. Quindi avremo numeri tipo 00000 00123 23041

Useremo la stringa 00000 come sentinella.

Page 38: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROBLEMALeggere il file Semester e realizzare due array di puntatori uno ordinato per nome (ByName) ed uno per matricola (ByMat).

L’array ByName contiene i puntatori agli studenti ordinati per nome.Vogliamo scrivere una funzione che faccia una ricerca di uno studente per numero di matricola sull’array ByMat.

1

mid

TotalStu

1

mid

TotalStu

ByName ByMat

050/714 21 22 23 30 27Abate Carlo 30/11/76 2000 25

050/734 28 22 28 30 27Carlini Anna 30/11/72 1999 27

050/514 30 21 23 30 27Zucchi Ugo 03/01/75 2000 24

Page 39: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Pseudo Codice

AssegnaFile(Semester)

OrganizzaDati(ByName,ByMat,TotalStu,Semester)

write('Dammi la matricola cercata: ');

readln(Matr);

Risultati(CercaStudente(ByMat,Matr,1,TotalStu));

Page 40: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROGRAM ArrayPuntatori(input, output, Semester);

CONSTMaxStu=100;TotaleProve=100;TYPEStringa4 = STRING[4];Stringa10 = STRING[10];Stringa25 = STRING[25];RisultatiArray=ARRAY[1..TotaleProve] OF integer;

StuRecord = RECORD Cognome, Nome : Stringa25;

Nascita:Stringa10; Matricola:Stringa10; AnnoCorso:Stringa4; Risultati:RisultatiArray; Media:real;

END;

StuFile=FILE OF StuRecord;StuPointer=^StuRecord;PointerArray=ARRAY[0.. MaxStu] OF StuPointer;

VARSemester: StuFile; ByName, ByMat: PointerArray;TotalStu:integer;

Matr:Stringa10;

Page 41: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROCEDURE Insert(NewElement:StuPointer; Candidate: integer; VAR ByMatP:PointerArray);BEGINWHILE (ByMatP[Candidate-1]^.Matricola > NewElement^.Matricola ) DOBEGIN

ByMatP[Candidate]:= ByMatP[Candidate-1]; Candidate:=Candidate-1

END;ByMatP[Candidate]:=NewElementEND;

PROCEDURE OrganizzaDati(VAR ByName,ByMat:PointerArray;VAR TotalStu:integer; VAR StuOnFile:StuFile);

VAR AStu:StuPointer;BEGINreset(StuOnFile);TotalStu := 0;new(ByMat[0]);ByMat[0]^.Matricola:='00000';WHILE NOT eof(StuOnFile) DO BEGIN

new(AStu);read(StuOnFile, AStu^);TotalStu := TotalStu + 1;ByName[TotalStu] := AStu;Insert(AStu, TotalStu, ByMat)

END;close(StuOnFile)END;

Page 42: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

FUNCTION CercaStudente(VAR ByMatP: PointerArray;Numero:Stringa10; Lo,Hi:integer): StuPointer;

VARProbe:integer;BEGIN

IF Lo > Hi THEN CercaStudente :=NIL

ELSE BEGIN

Probe:=(Lo+Hi) DIV 2;IF ByMatP[Probe]^.Matricola = Numero THEN

CercaStudente:= ByMatP[Probe];ELSE IF ByMatP[Probe]^.Matricola < Numero THEN

CercaStudente:= CercaStudente(ByMat, Numero, Probe+1,Hi) ELSE

CercaStudente:= CercaStudente(ByMat, Numero, Lo,Probe-1) END

END;

PROCEDURE Risultati(MatrCand:Stupointer); BEGIN writeln(Matrcand^.Cognome,' ', MatrCand^.Nome,' ', MatrCand^.Matricola); END;

Page 43: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

{******************** MAIN ******************}

BEGINassign(semester,'a:\probe.dat');OrganizzaDati(ByName,ByMat, TotalStu, Semester);readln;write('Dammi la matricola cercata: ');readln(Matr);Risultati(CercaStudente(ByMat,Matr,1,TotalStu));readlnEND.

Page 44: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Esercizio

Scrivere il programma completo per la gestione dei records attraverso array di puntatori ordinati per Nome, Matricola, Data di Nascita, Media.

Page 45: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Alcuni suggerimenti sui file

Evitare di usare il REPEAT … UNTIL quando si leggono file binari o testo.

reset(SomeFile)REPEAT

read(SomeFile,SomeComponent)elabora(SomeComponent)

UNTIL eof(SomeFile)reset(SomeFile)IF NOT eof(SomeFile) THENREPEAT

read(SomeFile,SomeComponent)elabora(SomeComponent)

UNTIL eof(SomeFile)

SBAGLIATO !!!!!!!!!!

CORRETTO !!!!!!!!!!

Non mettere mai un reset o un rewrite all’interno di un loop.

WHILE NOT eof(SomeFile) DO BEGIN

reset(SomeFile);read(SomeFile,SomeComponent)elabora(SomeComponent)

END;

SBAGLIATO !!!!!!!!!!

Page 46: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Ricordare che il valore di una variabile file cambia sempre quando si usano il read o il write, quindi le chiamate alle variabili file vanno sempre fatte per VAR e mai per valore.

Ricordare che readln e writeln si possono usare solo con i file testo e non con i file binari.

Quando si implementano procedure per la gestione di file realizzare sempre procedure per provare se i record o comunque i dati sono correttamente inseriti facendo le prove con pochi esempi.

Page 47: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Alcuni suggerimenti sui puntatori

Per il passaggio di parametri relativi ai puntatori valgono le stesse regole che si applicano per gli altri tipi di variabili.

Quando un puntatore è chiamato per valore viene fatta una copia locale del suo valore, cioè dell’indirizzo.

Quando un puntatore è chiamato per variabile viene prodotto un alias locale per il suo valore attuale, ricordando sempre che si tratta di indirizzi.

Page 48: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROGRAM TestChiamatePuntatori;TYPEIntP=^integer;VARAnIntP:IntP;PROCEDURE ValCall(XP:IntP);BEGINXP^:=7;END;PROCEDURE VarCall(VAR XP:IntP);BEGINXP^:=7;END;

BEGINnew(AnIntP);AnIntP^:=5;ValCall(AnIntP);writeln(‘Output= ‘,AnIntp^:1);END.

Output= 7 Questo accade perché l’indirizzo passato dalla chiamata rimane lo stesso mentre il valore della variabile dinamica è cambiato. Questa chiamata equivale ad una chiamata per VAR su XP^.

BEGINnew(AnIntP);AnIntP^:=5;ValCallVar(AnIntP);writeln(‘Output= ‘,AnIntp^:1);END.

Output= 7 Il valore resta lo stesso essendo la chiamata precedente equivalente ad una chiamata per VAR su XP^.

Page 49: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROGRAM TestChiamatePuntatori;TYPEIntP=^integer;VARAnIntP:IntP;PROCEDURE ValCall(XP:IntP);BEGINdispose(XP);END;PROCEDURE VarCall (VAR XP:IntP);BEGINdispose(XP);END;

BEGINnew(AnIntP);AnIntP^:=5;ValCall(AnIntP);writeln(‘Output= ‘,AnIntp^:1);END.

Output= non predicibile Questo accade perché l’indirizzo passato dalla chiamata viene deallocato. Poiché questo indirizzo nel main corrisponde anche a quello di AnInt^ il valore di AnInt^ ora non è più predicibile.

BEGINnew(AnIntP);AnIntP^:=5;VarCall (AnIntP);writeln(‘Output= ‘,AnIntp^:1);END.

Output= non predicibile Come prima.

Page 50: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROGRAM TestChiamatePuntatori;TYPEIntP=^integer;VARAnIntP:IntP;PROCEDURE ValCall(XP:IntP);BEGINdispose(XP);new(XP);END;PROCEDURE VarCall (XP:IntP);BEGINdispose(XP);new(XP);END;

BEGINnew(AnIntP);AnIntP^:=5;ValCall(AnIntP);writeln(‘Output= ‘,AnIntp^:1);END.

Output= non predicibile Questo accade perché l’indirizzo passato dalla chiamata viene deallocato. Poiché questo indirizzo nel main corrisponde anche a quello di AnInt^ il valore di AnInt^ ora non è più predicibile. Inoltre la memoria allocata da new diventa spazzatura non appena si esce dal blocco.

BEGINnew(AnIntP);AnIntP^:=5;VarCall (AnIntP);writeln(‘Output= ‘,AnIntp^:1);END.

Output= non predicibile Come prima. Solo che ora non si crea spazzatura.

Page 51: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROGRAM TestChiamatePuntatori;TYPEIntP=^integer;VARAnIntP:IntP;PROCEDURE ValCall(XP:IntP);BEGINXP:=NIL;END;PROCEDURE VarCall (XP:IntP);BEGINXP:=NIL;END;

BEGINnew(AnIntP);AnIntP^:=5;ValCall(AnIntP);writeln(‘Output= ‘,AnIntp^:1);END.

Output= 5 Questa istruzione riassegna un valore a XP. Ora XP e AnInt hanno valori differenti. Quando si esce da ValCall XP è perso e quindi AnInt resta =5. Non c’è spazzatura perché abbiamo usato il NIL.

BEGINnew(AnIntP);AnIntP^:=5;VarCall (AnIntP);writeln(‘Output= ‘,AnIntp^:1);END.

Output= 5 Questa istruzione riassegna a AnIntP il valore NIL. Quindi quando si esce da ValCall AnIntP^ non è predicibile inoltre a AnIntP è stato assegnato un nuovo valore per cui il precedente contenente 5 è diventato spazzatura.

Page 52: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROGRAM TestChiamatePuntatori;TYPEIntP=^integer;VARAnIntP:IntP;PROCEDURE ValCall(XP:IntP);BEGINnew(XP);XP^:=7writeln(XP:1)END;PROCEDURE VarCall (XP:IntP);BEGINnew(XP);XP^:=7writeln(XP:1)END;

BEGINnew(AnIntP);AnIntP^:=5;ValCall(AnIntP);writeln(‘Output= ‘,AnIntp^:1);END.

OutputCall=7Output= 5 Qui si alloca un nuovo indirizzo per la variabile che prima aveva indirizzo AnInt. L’effetto della assegnazione XP:=7 è ristretto solo agli scopi della procedura ValCall.Ora XP e AnIntP rappresentano due diverse variabili puntatore, quando usciamo dalla procedura AnIntP^ vale sempre 5, mentre il valore di XP^ è perduto come spazzatura.

BEGINnew(AnIntP);AnIntP^:=5;VarCall (AnIntP);writeln(‘Output= ‘,AnIntp^:1);END.

OutputCall=7Output= 7 L’istruzione new(XP) fa sì che AnIntP diventa spazzatura. Quindi il valore 7 è mostrato due volte poiché tramite la Call VAR restituisce detto valore a AnIntp^.

Page 53: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

ESERCIZIO E-MAIL

PROGRAM MESSAGGI;USES Stringa;VAR strDate, strEmail: stringADT;

InFile:text;MsgNum:integer;

PROCEDURE InitString (VAR strDate,strEMail:stringADT); {Inizializza le stringhe di inzio Data ed inizio Indirizzo}BEGIN END;

{Visualizza l'indirizzo elettronico e le date usando la ricorsione}PROCEDURE ExtractEMail_Date_Ric (VAR MsgNum: integer; VAR InFile:text);VAR

outstr,strApp,Date,EMail:stringADT;BEGIN

IF not eof(InFile) THENBEGIN

ReadlnString(OutStr,InFile);StrExtract(OutStr,1,strDate.len,strApp);IF strEqual(strApp,strDate) THENBEGIN

MsgNum:=MsgNum+1;StrExtract(outstr,strDate.len+1,outstr.len,Date);ReadlnString(outstr,InFile);StrExtract(outstr,strEMail.len+1,outstr.len,EMail);

END; ExtractEMail_Date_Ric(MsgNum,InFile);IF strEqual(strApp,strDate) THEN

BEGINPrintString(Date);write(' ');PrintString(EMail);writeln;

END;

END;END;PROCEDURE Introduction;BEGIN END;

Page 54: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

{ BODY }

BEGIN InitString(strDate,strEMail); MsgNum:=0; Introduction; assign(InFile,'c:\tp\esempi\posta2.txt'); reset(InFile);

writeln('Visualizzazione con la Ricorsione');writeln(' Data Indirizzo');MsgNum:=0;reset(InFile);ExtractEmail_Date_Ric(MsgNum,InFile);close(InFile);writeln('Sono stati trovati ',MsgNum,' messaggi.');

readlnEND.

Page 55: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

PROGRAM leggi_file_di_posta;uses strinsur;{ estrae da un file di posta elettronica gli indirizzi e le date e li stampa in ordine crescente per data }VARtesto:text; { file}righe:integer; { contatore di righe stampate }PROCEDURE elaboratesto(var testo:text;var righe:integer);{ procedura ricorsiva che elabora il testo } VAR from,ext,str1,date,ind:tipostringa; { stringhe } BEGIN converti('From -',from); { crea una stringa di controllo } inizializza(ext); inizializza(str1); inizializza(date); inizializza(ind); WHILE NOT(eof(testo)) AND (not(strequal(ext,from))) DO {estrae da ogni rigo una stringa e la confronta con quella di controllo }

BEGIN readlnstring(str1,testo); strextract(str1,1,6,ext); END;

IF strequal(ext,from) THEN BEGIN strextract(str1,8,50,date); { estrae la data } readlnstring(str1,testo); strextract(str1,14,50,ind); { estrae l'indirizzo }

elaboratesto(testo,righe); write(' C''Š un messaggio da parte di '); { stampa l'indirizzo e la data letti } writelnstringa(ind,output); write(' ricevuto in data = '); writelnstringa(date,output); writeln;

righe:=righe+1; { incrementa il contatore che permette di stampare 7 messaggi alla volta } IF (righe mod 7)=0 THEN BEGIN writeln('Premi un tasto per continuare '); readln;

END; END; END;

Page 56: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

{ BODY }

BEGIN

assign(testo,'c:\tp\esempi\posta.txt');reset(testo);righe:=0;elaboratesto(testo,righe);write('Non ci sono pi— messaggi ');readln;

END.

Page 57: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Procedura B

ExtractEMail_Date_Ric(InFileIF not eof(InFile) THEN BEGIN

leggi(testo)estrai(strApp)IF strDate = ‘FROM’ THEN

BEGINestrai(data)leggi(testo)estrai(indirizzo)END

ExtractEMail_Date_Ric(InFile);fai_le_stampe

END

NOT(eof) strData =

FROMLeggiestrai

Fine Ricorsione

pop

Ricorsionepush

Leggiestrai

Stampa

SI

NO SI

NO

Procedura Aelaboratesto (testo)inizializzaStringhe(ext, str1, data, ind)WHILE NOT eof(testo) AND NOT ext=‘FROM’ DO {estrae da ogni rigo una stringa e la confronta con quella di controllo }

leggi(testo)estrai(ext)IF ext=‘FROM’ THEN

BEGIN estrai(data)

leggi(testo)estrai(ind)elaboratesto(testo)

fai_le_stampeEND

ENDEND

NOT(eof) &ext= FORM

strData =FROM

Leggiestrai

Fine Ricorsione

pop

Ricorsionepush

Leggiestrai

Stampa

WHILE

NO

SI

NO

SI

Page 58: In Pascal è possibile avere oltre ai file testo, cioè file di char, anche file di interi, stringhe, records. Unica condizione è quella che se un file.

Recommended