Program Esempio2; Uses Crt,WinDos; Var nome1,nome2,stringa:string; file1,file2:text; begin clrscr; write(‘Inserire il nome di un file: ‘); readln(nome1); write(‘Inserire il nome del file copia: ‘); readln(nome2); Assign(file1,nome1); Assign(file2,nome2); Reset(file1); Rewrite(file2); repeat readln(file1,stringa); writeln(file2,stringa); until eof(file1); Close(file1); Close(file2); writeln(‘Copia completata!’); readln end.
Bene, questo programma non è di immediata comprensione, poiché contiene un concentrato di procedure e regole nuove non indifferente. Procediamo con calma:
Assign(nome1,file1); : questa procedura assegna alla variabile file1 di tipo text il nome del file contenuto nella stringa nome1.
Per questo, è doveroso aprire una parentesi su come Pascal legge i nomi dei file: innanzitutto, un nome può essere composto da al massimo 8 caratteri, estensione esclusa; se il nome supera gli 8 caratteri viene troncato a 6 e si aggiunge un ‘~1’ (il codice ASCII di ~ è 126). Perciò il nome ‘testouno.txt’ è giusto e viene mantenuto così; ‘testoquattro.txt’ è sbagliato e il compilatore vi manderà un messaggio di errore (error 2: File not found); ‘testoq~1.txt’ è la versione giusta dell’esempio precedente: i caratteri vengono troncati a 6 e aggiunto un ‘~1’. Inoltre, il nome può contenere anche l’indirizzo completo di un file, dove ogni cartella deve sottostare alla legge degli 8 caratteri, perciò: ‘C:\Documents and settings\Proprietario\Fileone.txt’ è sbagliato, mentre ‘C:\Docume~1\Propri~1\Fileone.txt’ è giusto.
Per non convertire tutti i nomi a mano, potete scaricare il codice sorgente vb nella sezione Sorgenti->VB.NET, che contiene delle funzioni vb per convertire il nome normale di un file in nome corto.
Reset(file1); : l’istruzione reset(x), dove x è una variabile inizializzata con Assign e di tipo text o file, serve per aprire il file x, in vista di operazioni di lettura/scrittura su di esso.
Rewrite(file2); : valgono le stesse regole di reset. Rewrite(x:text o file) è una procedura che crea un nuovo file x (se non è specificata la directory nel suo nome, viene creato nel path corrente). Se esiste già un file di nome x, lo sovrascrive.
repeat...until eof(file1); : ripete un ciclo di istruzioni finché l’espressione indicata dopo until è vera. Nel nostro caso, il programma continua a leggere, riga per riga, ogni sequenza di caratteri contenuta in file1 e la copia in file2, finché la variabile reimpostata eof (che significa End Of File; supporta solo parametri di tipo text o file) non è vera (se non si mette un segno di comparazione, il compilatore sottintende un ‘=true’), e quindi il file da cui leggere è al termine.
Close(file1); : la procedura close chiude un file.
Questo programma è già di un livello più alto: meriterebbe uno studio più accurato per capire il funzionamento, da parte del lettore.
Come si è ben visto, il ciclo repeat...until serve per ripetere un istruzione o un blocco di istruizioni fino a che una condizione non è vera: come avrete sicuramente notato, in questo caso non serve racchiudere il blocco di istruzioni fra un begin ed un end, poichè i confini del blocco sono già repeat e until.
Un ultima osservazione: si può trovare anche un ciclo repeat...until senza istruzioni, così:
(*ripete un ciclo di istruzioni vuoto finchè non viene premuto un pulsante*) repeat until keypressed;
Anche se è un caso usato non molto spesso, è giusto saperlo.
Nelle strutture iterative, ossia le istruzioni che fanno ripetere sempre uno stesso blocco di istruzioni un certo numero di volte o finchè una condizione è vera, è opportuno controllare sempre che le condizioni di uscita siano giuste. per esempio:
Program CicloInfinito; Uses crt; var n:longint; begin clrscr; writeln('Inserire un numero: '); readln(n); repeat n:=n+2; until n mod 2=0; readln end.
Come si vede, viene letta una variabile longint n che viene aumentata di 2 fino a che il resto di n/2 è 0. Ma se n è dispari il ciclo non finirà mai, in quanto n è sempre dispari e perciò n/2 dà come resto sempre 1.
E' bene stare in guardia dai cicli infiniti, sebbene qualche volta possano essere utili.
Per esempio, PRobot è un programma, che forse qualcuno di voi conoscerà, che permette di programmare un robot virtuale con il linguaggio Pascal e di farlo poi combattere. Ecco, in questo case si deve usare un ciclo infinito con molte istruzioni if al suo interno:
repeat (*ciclo di istruzioni*) if ... then ... ... until false;
Il codice ripete sempre il ciclo finchè false non è uguale a true, il che non può mai accadere, in quanto falso è sempre diverso da vero.
Anche se casi border-line, può essere utile conoscerli.
A cura di: Il Totem