Tutorial Pascal

93
PASCAL Interfata Turbo Pascal 7.0 Mediul integrat (IDE ) Turbo Pascal prezinta o bara de meniu orizontala, in partea de sus (meniul principal). Are 10 optiuni: File Face cam ce face orice meniu File din zilele noastre. Deschide fisier nou, salveaza, etc. Edit Ce credeti ? idem Search Meniul de cautare al aproape oricarui editor de text. Run Ofera modalitati de rulare a programului (normal, pas cu pas), oprirea lui pentru modificari si posibilitatea de a porni programul cu anumiti parametri. Compile Compileaza programul (transforma codul sursa in cod masina, pentru a putea fi inteles si rulat de procesor) si faciliteaza crearea unui proiect, prin setarea unui "primary file" (programul care e rulat cand utilizatorul da aceasta comanda este cel setat prin primary file, asa ca nu mai aveti probleme cand dati Ctrl+F9, daca sunteti intr-un unit. Debug Vizualizarea valorilor variabilelor unui program, in timpul rularii acestuia, afisarea ultimului ecran al programului, puncte de intrerupere (breakpoint-uri), etc Tools Cateva programe care pot ajusta crearea programului, prin modificarea parametrilor pentru crearea lui, verificarea programului pentru a vedea unde "papa" mult timp, etc. Options Puteti seta directoarele implicite pentru unituri, culorile folosite de editor, salvarea preferintelor si (foarte) multe altele. Window Posibilitati de aranjare a ferestrelor

description

Limbajul de programare Pascal

Transcript of Tutorial Pascal

Page 1: Tutorial Pascal

PASCAL

Interfata Turbo Pascal 7.0

Mediul integrat (IDE) Turbo Pascal prezinta o bara de meniu orizontala, in partea de sus (meniul principal). Are 10 optiuni:

FileFace cam ce face orice meniu File din zilele noastre. Deschide fisier nou, salveaza, etc.

EditCe credeti ? idem

SearchMeniul de cautare al aproape oricarui editor de text.

RunOfera modalitati de rulare a programului (normal, pas cu pas), oprirea lui pentru modificari si posibilitatea de a porni programul cu anumiti parametri.

CompileCompileaza programul (transforma codul sursa in cod masina, pentru a putea fi inteles si rulat de procesor) si faciliteaza crearea unui proiect, prin setarea unui "primary file" (programul care e rulat cand utilizatorul da aceasta comanda este cel setat prin primary file, asa ca nu mai aveti probleme cand dati Ctrl+F9, daca sunteti intr-un unit.

DebugVizualizarea valorilor variabilelor unui program, in timpul rularii acestuia, afisarea ultimului ecran al programului, puncte de intrerupere (breakpoint-uri), etc

ToolsCateva programe care pot ajusta crearea programului, prin modificarea parametrilor pentru crearea lui, verificarea programului pentru a vedea unde "papa" mult timp, etc.

OptionsPuteti seta directoarele implicite pentru unituri, culorile folosite de editor, salvarea preferintelor si (foarte) multe altele.

WindowPosibilitati de aranjare a ferestrelor

HelpDestul de usor de inteles ce face asta... doar ca Helpul e in engleza (sper ca nu se astepta cineva sa fie in romana )

E clar ca, in majoritatea timpului, nu veti avea nevoie de cele mai multe din optiunile oferite de meniu, asa ca am sa dau mai jos o lista de scurtaturi de la tastatura pentru cele mai uzuale functii:

Combinatii uzuale de taste in Borland Pascal 7.0

ALT + Xinchide Borland Pascalul (l-am pus primul pentru a putea iesi repede din el, daca aveti probleme )

F2 salveaza fisierul curentF3 deschide un fisier (unul nou sau unul salvat)SHIFT + DEL

comanda CUT

Page 2: Tutorial Pascal

Combinatii uzuale de taste in Borland Pascal 7.0CTRL + INS comanda COPYSHIFT + INS

comanda PASTE

ALT + F5 arata ultimul ecran al programului (ultimele afisari)ALT + F9 verifica erorile de sintaxa si compileaza programulCTRL + F9 verifica erorile de sintaxa, compileaza si ruleaza programul

CTRL + F2reseteaza programul (in caz ca il aveti pornit in modul pas cu pas) pentru alte modificari

CTRL + F7adauga o variabila a carei valoare va fi afisata pe parcursul executarii programului

CTRL + F1cu cursorul pus pe un anumit cuvant, va deschide Help-ul la sectiunea respectiva

CTRL + ENTER

cu cursorul pus pe un cuvant care e numele unui fisier cu extensia .PAS din directorul curent, deschide si acel fisier (de ex. un unit)

La lucru in Turbo Pascal 7.0

Pentru a incepe un program nou, in primul rand trebuie sa aveti Pascalul pornit. Selectati File / New si veti avea un nou fisier, denumit NONAMEXX.PAS (XX simbolizand al catelea fisier nou deschis este acesta). Alta solutie este sa alegeti File / Open, introduceti un nume, iar fisierul va fi automat salvat (bineinteles, gol).

Acum ca aveti in fata tot ce va trebuie, nu aveti DECAT sa scrieti programul, sa-l verificati de erori (poate fi verificat de erori compilandu-l, dar si rulandu-l direct, fiindca inainte de a-l rula il si verifica... ce descoperire )

Foarte "originalul" program care afiseaza Hello World este mai jos. Spor la joaca

1. Begin2.   Write('Hello World');3.   ReadLn;4. End.

Veti invata in urmatoarele tutoriale ce inseamna si ce fac aceste 4 linii de mai sus, momentan e de ajuns sa stiti ca puteti modifica Hello World de mai sus cu orice text vreti voi si ca va trebui sa apasati tasta Enter pentru a iesi din program.

Page 3: Tutorial Pascal

Tutorial Pascal

Partile unui program Pascal

Cele trei parti principale ale unui program Pascal sunt: antetul (header-ul) programului, declaratiile in care se descriu obiectele asupra carora vor avea loc prelucrarile (in cadrul programului pe care il analizam, vom considera numai declararea variabilelor) si partea principala a programului in care se scriu instructiunile (ansamblul operatiilor ce urmeaza a fi executate).

O structura vizuala a unui program Pascal ar arata in felul urmator:Line number On/Off | Expand/Contract | Select all

1. PROGRAM Nume_Program;2.  3. CONST4.   (* declaratii de constante *)5.  6. TYPE7.   (* declaratii de tipuri *)8.  9. VAR10.   (* declaratii de variabile *)11.  12.   (* declaratii de subprograme (functii si proceduri)

*)13.  14. BEGIN15.   (* instructiuni *)16. END.

De remarcat ca un program functional necesita doar ultimele 3 linii din schita de mai sus, iar compilatorul nu va avea nimic impotriva. Bineinteles, nu veti putea folosi variabile, constante, tipuri sau subprograme.

Pentru a intelege aceasta structura, deloc complicata, sa analizam fara graba un program Pascal care calculeaza si afiseaza volumul unui paralelipiped. Este vorba de un program care declara variabile, citeste valorile acestora, efectueaza un calcul simplu si afiseaza rezultatul.Line number On/Off | Expand/Contract | Select all

1. PROGRAM volumul;2. {calculeaza si afiseaza volumul unui paralelipiped}3. VAR lungime, latime, inaltime, volum: real;4. BEGIN

Page 4: Tutorial Pascal

5.   writeln('Introduceti valori: lungime, latime, inaltime');

6.   readln(lungime, latime, inaltime);7.   volum := lungime * latime * inaltime;8.   writeln('Volumul paralelipipedului= ', volum:9:5,' metri

cubi')9. END. {volumul}

Cand programul este rulat, pe ecran se va afisa:Line number On/Off | Expand/Contract | Select all

1. Introduceti valori: lungime, latime inaltime2. 8.3 7.25 6.293. Volumul paralelipipedului= 378.50075 metri cubi

De remarcat ca sirul "8.3 7.25 6.29" a fost introdus de la tastatura, fiind valorile pentru lungime, latime, respectiv inaltime.

Examinand acest program, vom putea vedea urmatoarele elemente:

Antetul (header-ul) programului

Prima linie contine antetul programului. Program este un cuvant rezervat cu care incepe (optional) un program (Borland) Pascal. El este urmat de numele programului: volumul si de simbolul punct si virgula. Simbolul punct si virgula (" ; ") este un separator de instructiuni. Este strict necesar, bineinteles, cu unele mici exceptii, care le voi semnala la momentul potrivit.

O restrictie importanta a identificatorilor este aceea ca nu pot contine in interiorul lor blancuri (spatii).

Comentariile

A doua linie a programului "volumul" este numita un comentariu.

Orice sir de caractere delimitat de seturile { si } sau (* si *) reprezinta un comentariu. Comentariile sunt folosite pentru a mari inteligibilitatea programelor (ele fiind ignorate de compilatorul Pascal), usurand astfel munca de intelegere si corectare a acestora. Daca se doreste imbricarea comentariilor, acest lucru se face alternand acoladele cu (*.Ex. modul corect:Line number On/Off | Expand/Contract | Select all

1. (* comentariu1 {comentariu imbricat} comentariu2 *)2. { comentariu1 (*comentariu imbricat*) comentariu2 }

modul incorectLine number On/Off | Expand/Contract | Select all

Page 5: Tutorial Pascal

1. (* comentariu1 (*comentariu imbricat*) comentariu2 *)

Setul de acolade { si } mai este folosit si pentru directivele de compilare.

Comentariile fac programul mai usor de inteles. Daca va scrieti programele fara comentarii veti putea avea nevoie de o perioada de reacomodare cu codul cand veti reveni pentru a-l modifica. In general, in partile de cod mai serioase sau mai complicate, se obisnuieste sa se foloseasca cateva comentarii. In plus, daca aveti de gand sa modificati codul pentru un alt scop decat cel initial, este bine sa faceti un comentariu in care sa explicati ce doriti sa faceti.

Remarcati in ultima linie a programului prezenta comentariului {volumul}, tocmai pentru a reaminti cititorului numele programului care s-a incheiat. Comentariile pot fi plasate oriunde in cadrul programului, dar nu in interiorul identificatorilor.

Declararea variabilelor

Cuvantul cheie var (prescurtare de la variables) incepe actiunea de declarare a variabilelor. Fiecare variabila trebuie sa poarte un nume. Programul volumul foloseste patru variabile (lungime, latime, inaltime, volum) identificate in faza de analiza structurata a programului. Acestea sunt grupate astfel:

Variabile de intrare:

lungime: lungimea paralelipipedului latime: latimea paralelipipedului inaltime: inaltimea paralelipipedului

Variabile de iesire:

volum: volumul paralelipipedului

Nu trebuie sa va speriati de denumirea pompoasa (de intrare, de iesire). Variabilele se declara la fel, indiferent de rolul lor. Denumirile sunt folosite doar pentru a usura intelegerea rolului acestor variabile in program.

Tipuri de date

In Pascal exista doua tipuri (simple) de date pentru variabile numerice: intregi si reale.

Variabilele intregi pot lua valori numai numere intregi, cum ar fi: 6, -19, 0 sau 73700.

Un calculator poate reprezenta numai o submultime finita de intregi. O valoare intreaga poate fi salvata in memoria unui calculator doar daca respectiva valoare apartine intervalului (-maxint-1, maxint), unde maxint este o constanta predefinita. In majoritatea implementarilor limbajului Pascal constanta maxint este egala cu 32767.Daca o variabila Pascal va avea o valoare fractionara, variabila trebuie sa fie de tip real.Intr-un program (Borland) Pascal tipul fiecarei variabile utilizate trebuie sa fie declarat. Omiterea declararii unei variabile folosite in partea principala a programului va genera o

Page 6: Tutorial Pascal

eroare. In programul pe care-l analizam (volumul), declararea variabilelor s-a facut utilizand enuntul:Line number On/Off | Expand/Contract | Select all

1. VAR lungime, latime, inaltime, volum: real;

Odata intalnit acest enunt, compilatorul afla ca toate cele patru variabile sunt de tip real.

Zona de memorie alocata variabilelor

Fiecarei variabile din program i se asociaza o locatie de memorie pe care v-o puteti imagina ca pe o cutie avand inscriptionate: nume si tip. Continutul cutiei este dat de valoarea curenta a variabilei.Tipul defineste categoria valorii din cutie. Programul refera variabila prin nume. Partea principala a programului reprezinta zona activa, executabila a programului. Cuvintele rezervate BEGIN si END delimiteaza instructiunile care descriu algoritmul principal al problemei de rezolvat.

Enunturile (instructiunile) write / writeln

Enunturile write / writeln sunt utilizate pentru afisarea pe un suport de informatie (de regula monitorul) a rezultatelor obtinute in urma prelucrarilor, a mesajelor catre utilizator etc.Write si WriteLn reprezinta in Pascal doi identificatori (de procedura) predefiniti (standard). De remarcat ca daca dati unui program numele "write" (sau "writeln"), nu mai aveti voie sa folositi in program nici un enunt write (sau writeln) cu sensul predefinit (adica sa afiseze un text, variabila, etc).

Ori de cate ori se va executa un enunt write / writeln, calculatorul va afisa ad-litteram tot ceea ce este inclus intre apostrofuri, precum si valorile oricarei variabile sau expresii aflate intre paranteze. In plus fata de write, Writeln va trece la linie noua dupa afisarea propriu-zisa. Pentru separarea elementelor din corpul instructiunii se folosesc virgulele.

Primul enunt din programul analizat (volumul) determina calculatorul sa scrie pe ecran mesajul:Line number On/Off | Expand/Contract | Select all

1. Introduceti valori: lungime, latime inaltime

dupa care va muta cursorul la inceputul liniei urmatoare.Fara un astfel de mesaj este greu sa ne dam seama ca este timpul sa se tasteze ceva. Writeln forteaza calculatorul sa afiseze tot ceea ce s-a specificat in interiorul parantezelor si sa treaca la linie noua. La un enunt write, cursorul va ramane pe pozitia imediat urmatoare ultimul caracter scris cu acest enunt.Writeln poate fi folosit si fara parametri pentru a muta cursorul cu o linie mai jos.

Enuntul readln

In momentul in care s-a executat instructiunea

Page 7: Tutorial Pascal

Line number On/Off | Expand/Contract | Select all

1. readln(lungime, latime, inaltime);

calculatorul asteapta de la utilizator sa introduca trei numere. Primul va fi atribuit variabilei lungime, cel de-al doilea variabilei latime si in sfarsit cel de-al treilea variabilei inaltime. Nu uitati ca toate cele trei variabile sunt de tip real!

Aceste valori pot fi tastate pe o singura linie, cu spatii intre ele, sau cate una pe linie.De remarcat ca valorile (folosind instructiunile Read / ReadLn) nu sunt citite pana la apasarea tastei Enter.

Utilizarea combinatiei write-readln in locul combinatiei writeln-readln

De foarte multe ori, in programarea calculatoarelor se foloseste combinatia write-readln in locul combinatiei writeln-readln.

Avantajul combinatiei write-readln este acela ca valoarea care se introduce va aparea pe aceeasi linie a ecranului cu cererea, in loc sa apara pe o linie proprie, cum s-ar fi intamplat in cazul folosirii combinatiei writeln-readln.

Enuntul de atribuire (asignare)

Enuntul ce urmeaza dupa enuntul readlnLine number On/Off | Expand/Contract | Select all

1. volum :=lungime*latime*inaltime;

se numeste enunt de atribuire intrucat el calculeaza ceva (produsul dintre lungime, latime si inaltime) si atribuie (asigneaza, afecteaza) rezultatul variabilei din stanga simbolului ":=". Partea dreapta a acestui enunt este un exemplu de expresie aritmetica.

Formatarea afisarii

Ultimul enunt din programul volumul:Line number On/Off | Expand/Contract | Select all

1. writeln('Volumul paralelipipedului= ',volum:9:5,' metri cubi');

afiseaza intr-o forma explicita rezultatul:Line number On/Off | Expand/Contract | Select all

1. Volumul paralelipipedului= 378.50075 metri cubi

Remarcati forma de prezentare a rezultatului. Pentru inceput, sirul de caractere "Volumul

Page 8: Tutorial Pascal

paralelipipedului", urmat de rezultatul propriu-zis, afisat insa intr-un sablon de 9 caractere, dintre care cinci reprezinta cifre zecimale. Acest mod de afisare a fost stabilit de specificatorul de format ":9:5" (9 caractere, din care 5 cifre zecimale). In cazul in care rezultatul ar fi avut 10 caractere (4 cifre inaintea virgulei, 5 cifre zecimale), specificatia ":9" nu era luata in seama. In cazul in care ar fi fost mai putine caractere (8 sau 7), atunci primul / primele caractere erau completate cu spatii. Specificatia de format " : x : y " este facultativa, dar fara acest specificator de format, volumul calculat ar fi fost afisat in notatie exponentiala (stiintifica), care este mai greu de citit. In sfarsit, sirul de caractere "metri cubi" completeaza imaginea rezultatului.

Spatii albe (whitespace)

Spatiile albe (spatiile, tab-urile, sfarsiturile de linie) sunt ignorate de Pascal, cu exceptia (evidenta) a sirurilor de text (stringuri) care sunt intre apostroafe. Totusi, pentru a usura munca oamenilor (a programatorului si a celor care mai vad codul) se recomanda spatierea cat mai ordonata a codului si, foarte important, indentarea codului. Folosirea TAB-ului pentru a indenta codul este nerecomandata, luandu-se in considerare diferentele posibile la intelegerea acestui caracter (2, 4, 8 spatii + posibilitati de a-l redefini in compilatorul dvs.).

Identificatori

Asa cum am aratat mai sus, identificatorii sunt definiti cu numele dorite. Totusi, exista cateva reguli de baza, de la care nu va puteti abate:

Trebuie sa inceapa cu o litera din alfabet englezesc sau cu caracterul "_" (underline, underscore).

Poate continua cu orice litera, cifra sau underline Nu poate contine anumite caractere speciale (~ ! @ # $ % ^ & * ( ) + ` - = { } [ ] : " ; '

< > ? , . / |), multe avand intelesul lor in Pascal.

Unele compilatoare de Pascal nu pun nicio restrictie asupra lungimii identificatorilor, dar altele folosesc doar primele cateva caractere (Borland Pascal foloseste primele 63 de caractere - n-am testat niciodata ). Problema des intalnita la identificatorii lungi este faptul ca incetinesc scrierea programului de catre programator. Lungimea identificatorilor este bine sa fie limitata la 10, maxim 15, caractere, in majoritatea cazurilor.

Constante

Constantele sunt identificatori ai unor valori ce sunt definite la inceputul programului. Valorile asignate constantelor nu pot fi schimbate in decursul rularii programului.Mai jos aveti o lista de constante declarate ca: Integer, Real, Caracter, String, Boolean (in aceasta ordine). Aceste tipuri de date vor fi explicate in tutorialul urmator.Line number On/Off | Expand/Contract | Select all

1. const numar = 2;        {numar intreg}2.       alt_numar = 3.14; {numar real}3.       litera = 'G';     {caracter}4.       nume = 'Ionut';   {sir de caractere (string)}5.       DoWait = False;   {valoare logica (boolean)}

Page 9: Tutorial Pascal

Constantele sunt, de obicei, folosite pentru a tine o valoare des utilizata in program, care s-ar putea sa fie nevoie sa fie schimbata.

Ganditi-va ca vreti sa faceti un program care deseneaza un dreptunghi in relief (3D). Pentru aceasta va trebui sa desenati dreptunghiul de mai multe ori, cu diferite culori, pentru a realiza efectul 3D. Daca la primul dreptunghi veti pune marimea laturii 50, la al doilea 49 si tot asa, veti vedea ca atunci cand vreti sa modificati programul, va trebui sa modificati fiecare numar.Alternativ, cu constante, in secventa de cod de mai jos:Line number On/Off | Expand/Contract | Select all

1. { ... }2. const latura_mare = 50;3. latura_mica = 20;4. { ... }5. begin6. { ... }7. Deseneaza Dreptunghi (latura_mare,     latura_mica)8. Deseneaza Dreptunghi (latura_mare - 2, latura_mica - 2)9. Deseneaza Dreptunghi (latura_mare - 4, latura_mica - 4)10. Deseneaza Dreptunghi (latura_mare - 6, latura_mica -

6)11. Deseneaza Dreptunghi (latura_mare - 8, latura_mica -

8)12. { ... }13. end.

Atentie: acest program nu va rula in Pascal. Este dat doar pentru exemplificare. Secventele { ... } desemneaza cod care e posibil sa existe.

Variabile

Variabilele sunt identificatori ai unor valori de anumite tipuri, specificate in declaratie. Spre deosebire de constante, pot fi declarate mai multe variabile de acelasi tip pe o singura linie. Mai jos aveti o lista de declarare de variabile. Aceste tipuri de date vor fi explicate in tutorialul urmator.

1. var index, numar, suma, produs: Integer;2.     valoare_pi, valoare_e: Real;3.     litera: Char;4.     nume, prenume: String;5.     AmTerminat: Boolean;

Variabilele sunt folosite pentru valori care se pot schimba in decursul programului. Variabilele pot fi folosite si in loc de constante, declarandu-le valoarea in program.

Page 10: Tutorial Pascal

Asignare

Operatia de asignare este operatia prin care variabilele primesc valori. Pentru a asigna o variabila se foloseste urmatoarea sintaxa:

1. variabila := valoare;

Secventa := se numeste operatorul de asignare.

valoare trebuie sa fie de acelasi tip cu tipul declarat al variabilei.Exemple (folosind declararea de variabile de mai sus):

1. index := 1;2. numar := 15;3.  4. litera := 'k';5. litera := #65; {caracterul A majuscula}6. nume := 'Bitcell';7. prenume := '.info';8. nume := nume + prenume; {da, sirurilor de caractere li se

poate aplica operatorul de adunare, caz in care sirurile vor fi concatenate}

9. {in acest exemplu, variabila "nume" va primi valoarea "Bitcell.info"}

10.  11. AmTerminat := (litera = 'X') and (litera = 'x');

{comparatii care returneaza un rezultat boolean, True sau False}

12.  13. valoare_pi := 22 / 7; {nu este chiar valoarea lui pi,

dar pentru un exemplu merge}14.  15. valoare_e := (numar / index) + suma;16.  

In Pascal, operatorii aritmetici sunt:Operatori aritmetici in PascalOperator Operatie Operanzi Rezultat+ adunare sau semn pozitiv reali sau intregi real sau intreg- scadere sau semn negativ reali sau intregi real sau intreg* inmultire reali sau intregi real sau intreg/ impartire reali sau intregi realdiv catul impartirii intregi intregi intregmod restul impartirii intregi intregi intreg

Dupa cum se vede in tabelul de mai sus, div si mod pot fi folosite doar cu numere intregi. Operatorul de impartire / poate fi folosit si cu numere intregi, si cu numere reale, dar va

Page 11: Tutorial Pascal

returna intotdeauna un numar real. Celelalte operatii functioneaza pe si numere intregi, si pe numere reale. De tinut minte e faptul ca atunci cand intr-o operatie folosim si numere intregi, si numere reale, rezultatul va fi intotdeauna un numar real.

Fiecarei variabile ii poate fi asignat o valoare de acelasi tip cu ea. Acesta este motivul pentru care nu se poate asigna o valoare reala unui intreg. Totusi, anumite tipuri de date vor converti valoarea catre un tip mai mare de date. Asta se intampla, de exemplu, cand se asigneaza o valoare intreaga unei variabile reale.

Line number On/Off | Expand/Contract | Select all

1. numar_intreg := 170;2. numar_real := numar_intreg;

In acest caz numarul intreg 170 va fi convertit in numar intreg, iar variabila numar_real va avea valoarea 170.0.

Schimbarea unui tip de data in alt tip se numeste typecasting (selectare de tip). Typecasting-ul din exemplul de mai sus este un exemplu de typecasting implicit (se intampla fara a se specifica aceasta intentie de catre programator).

Majoritatea compilatoarelor moderne de Pascal suporta si typecasting-ul explicit, cu o sintaxa doar putin diferita de cea a limbajului C. Codul de mai jos da un exemplu al typecasting-ului explicit.Line number On/Off | Expand/Contract | Select all

1. var numar8biti: byte;2.     numar16biti: integer;3. begin4.   numar16biti := 1000;5.   numar8biti := byte(numar16biti);6.   write(numar8biti);7. end.

In acest exemplu asignam o valoare intreaga, reprezentata intern pe 16 biti, unei variabile intregi reprezentata pe doar 8 biti, specificand ca vrem sa schimbam tipul variabilei in byte (reprezentare interna de 8 biti). Acesta este typecasting-ul explicit si, in Pascal, se face prin a pune paranteze in jurul valorii careia ii vrem schimbate reprezentarea si punand tipul dorit in fata parantezei.

In exemplul de mai sus, variabila pe 8 biti va primi valoarea de 232 (byte-ul cel mai putin semnificativ din valoarea pe 2 bytes initiala).

Punctuatie si indentare

Avand in vedere ca Pascal ignora spatiile albe (vezi mai sus), punctuatia este necesara pentru a spune compilatorului unde se termina o instructiune. Caracterul care indica terminarea unei instructiuni este, in general, punct si virgula ;. Caracterul care indica terminarea programului

Page 12: Tutorial Pascal

este punctul ..

Trebuie sa aveti un caracter ; dupa:

numele programului fiecare definitie de constanta fiecare definitie de variabila fiecare definitie de tip aproape toate instructiunile

Ultima instructiune inainte de o instructiune end nu necesita sa aiba ; la sfarsit. Totusi, nu se intampla nimic sa puneti si in acest caz. De fapt, e chiar recomandat sa puneti in acest caz, datorita faptului ca e posibil sa adaugati o alta instructiune dupa instructiunea care nu are terminator ( ; ) si va veti trezi cu erori de compilare.

Indentarea NU este necesara, din punctul de vedere al compilatorului. Cu toate acestea, indentarea este una dintre cele mai importante lucruri in programare, oferind claritate codului. Alta problema cu indentarea este indentarea facuta folosind tasta TAB. Caracterul TAB, fiind afisat in diferite feluri in diferite editoare, duce la neclaritati si/sau imprastierea codului pe latime.(Eu, ca programator, refuz sa lucrez pe o bucata de cod care nu e scrisa cat mai clar posibil. Daca e strict necesar sa lucrez pe ea, primul lucru de care ma ocup este indentarea codului.)

Alt lucru important (si care ajuta la claritate) e punerea fiecarei instructiuni pe linie separata.

Sa luam o bucata de program si sa vedem ce si cum.

Aceasta este bucata de cod, indentata si clara.

1. uses crt;2. const spaced = '    ';3.       select = '  * ';4. var c: char;5.     sel: integer;6. begin7.   clrscr;8.   c := #0;9.   sel := 1;10.   {afisam meniul initial}11.   TextColor(Yellow);12.   TextBackground(Blue); {galben pe albastru pentru

optiunea selectata}13.   WriteLn(select, '1. BitCell.info');

(luat dintr-un exemplu)

Aceeasi bucata de cod, scrisa cu picioarele (figura de stil )

1. uses crt;

Page 13: Tutorial Pascal

2. const spaced = '    '; select = '  * '; var c: char; sel: integer;

3. begin clrscr; c := #0; sel := 1;4. {afisam meniul initial} TextColor(Yellow);

TextBackground(Blue); {galben pe albastru pentru optiunea selectata} WriteLn(select, '1. BitCell.info');

Sper ca m-am facut inteles. Daca va place sa lucrati pe programe scrise fara indentare, puteti sa va prefaceti ca nu ma cunoasteti

Indentarea, impreuna cu comentariile scurte si la obiect, ajuta foarte mult la intelegerea codului. Nu le evitati !

Page 14: Tutorial Pascal

Tipuri de date in Pascal

In Pascal, tipurile de date sunt de 2 feluri: simple si structurate.

Tipuri de date simple sunt impartite in tipuri ordinale si reale.

Tipuri ordinale:o Tipuri intregi:

shortintpoate lua valori intre (-128, 127) sau ($80, $7F) in hexazecimalstocat intern pe: 1 byte

bytepoate lua valori intre (0, 255) sau ($00, $FF) in hexazecimalstocat intern pe: 1 byte

integerpoate lua valori intre (-32768, 32767) sau ($8000, $7FFF) in hexazecimalstocat intern pe: 2 bytes

wordpoate lua valori intre (0, 65535) sau ($0000, $FFFF) in hexazecimalstocat intern pe: 2 bytes

longintpoate lua valori intre (-2147483648, 2147483647) sau ($80000000, $7FFFFFFF) in hexazecimalstocat intern pe: 4 bytes

Tipul logic: booleanpoate lua ca valori doar TRUE sau FALSEstocat intern pe: 1 byte

Tipul caracter: charpoate lua ca valoare orice caracter din ASCII (American Standard Code for Information Interchange)stocat intern pe: 1 byte

o Tipul enumerareo Tipul subdomeniu

Tipuri realeo single

poate lua valori intre (1.5E-45, 3.4E38)stocat intern pe: 4 bytes

o realpoate lua valori intre (2.9E-39, 1.7E38)stocat intern pe: 6 bytes

o doublepoate lua valori intre (5.0E-324, 1.7E308)stocat intern pe: 8 bytes

o extendedpoate lua valori intre (3.4E-4932, 1.1E4932)stocat intern pe: 10 bytes

Page 15: Tutorial Pascal

o comppoate lua valori intre (-2^63+1, 2^63-1)stocat intern pe: 8 bytes

Tipurile structurate:o tipul tablou: array

folosit pentru a memora un sir de valorio tipul sir de caractere: string

este o secventa dinamica (ca lungime) de caractere.poate lua ca valori un sir de caractere din ASCII (maxim 255 de caractere)stocat intern pe: maxim 256 de bytes (primul e pentru a stoca lungimea sirului (spre deosebire de C / C++, unde sirul se termina cu caracterul #0 - null terminated strings)

o tipul inregistrare: recordfolosit pentru a memora valori de mai multe tipuri in acelasi loc

o tipul obiect: objectfolosit in programarea pe obiecte (OOP)

o tipul multime: setfolosit pentru a desemna o multime (ca in matematica) de elemente de acelasi tip

o tipul fisier: text, filefolosit la prelucrarea fisierelor

o tipul referinta: pointerfolosit la prelucrarea dinamica a memoriei

o tipurile procedurale: function, procedureextensie a Pascalului standard, folosite pentru a putea folosi subprogramele ca variabile

Tipuri ordinale

Cum am aratat mai sus, tipurile ordinale de date sunt shortint, byte, integer, word , longint.

In operatii, toate tipurile intregi de date sunt compatibile intre ele. Operatorii aritmetici care se pot folosi sunt:

o + (semnul plus)pentru adunare

o - (semnul minus)pentru scadere

o * (semnul asterisc)pentru inmultire

o DIVimpartire intreaga - se obtine catul

o MODimpartire intreaga - se obtine restul

Page 16: Tutorial Pascal

o / (semnul slash)impartire reala - se poate aplica asupra operanzilor intregi, dar rezultatul este real.

Tipul Boolean

Tipul boolean este ordinal, enumerativ: (FALSE, TRUE). Operatorii logici care i se pot aplica sunt:

o NOToperatia logica "nu"

o ANDoperatia logica "si"

o ORoperatia logica "sau"

o XORoperatia logica "sau exclusiv" - este adevarat daca un operand este adevarat, dar nu amandoi.A XOR B inseamna "A sau B, dar nu amandoua".

Tipul Char

Tipul char este ordinal.Valoarea unei variabile de acest tip se va scrie intre ghilimele.Ex. 'A' sau 'a' (sunt distincte !)

Operatorii si functiile care se pot aplica asupra acestui tip de data sunt:

o +concateneaza 2 sau mai multe caractere, dar rezultatul este de tip string

o CHReste o functie care se aplica datelor de tip intreg, dar rezultatul este de tip Char. Returneaza caracterul cu codul respectiv din codul ASCII. Alternativ, se poate folosi #.Ex. Chr(65) este egal cu #65, ambele avand valoarea A (caracter)

Tipuri reale

Tipurile reale de date sunt single, real, double, extended si comp.Datele sunt memorate intern in virgula mobila.

Tipul comp desemneaza o data reala particulara, avand numai valori intregi. In operatii intra ca o data reala, avand partea zecimala egala cu zero.

Operatorii aritmetici (si functii) care se pot aplica tipurilor reale sunt:

Page 17: Tutorial Pascal

o +pentru adunare

o -pentru scadere

o *pentru inmultire

o /impartire reala (cu virgula)

o Truncfunctie care returneaza partea intreaga a numarului

o Roundfunctie care rotunjeste un numar. Daca partea zecimala este de 0.5 atunci numarul este rotunjit in sus

Tipurile structurate vor fi explicate intr-un alt tutorial, necesitand mai multe informatii.

Operatii specifice pe tipuri de date in Pascal

Pentru tipurile ordinale de date, unde exista un predecesor si un succesor distinct pentru fiecare valoare, Pascal ofera functiile prezentate in tabelul de mai jos.

Functii pentru tipuri ordinaleFunctie Descriere Tip argument Tip rezultatchr caracterul specificat din ASCII intreg caracterord valoare ordinala intreg sau caracter intregpred predecesor intreg sau caracter la fel ca argumentulsucc succesor intreg sau caracter la fel ca argumentul

Pascal ofera o multitudine de functii matematice, din care voi prezenta cateva mai jos.

Functii matematiceFunctie Descriere Tip argument Tip rezultatabs valoare absoluta real sau intreg la fel ca argumentularctan arctangenta in radiani real sau intreg realcos cosinus de X radiani real sau intreg realexp e la putere real sau intreg realln logaritm natural real sau intreg realround rotunjire real integersin sinus de X radiani real sau intreg realsqr ridicare la patrat real sau intreg la fel ca argumentulsqrt radical real sau intreg realtrunc rotunjire in jos real sau intreg integer

Page 18: Tutorial Pascal

Atentie: Toate functiile trigonometrice din Pascal lucreaza cu radiani.

Toate functiile expuse aici sunt folosite scriind numele functiei, urmat de argumentul (parametrul) functiei, pus intre paranteze rotunde ( si ).

Bineinteles, aceasta lista de functii nu este lista completa de functii si proceduri ale compilatorului Pascal. Compilatoarele moderne de Pascal includ mii de functii pentru toate necesitatile. Sistemul de ajutor (Help) al compilatorului nu trebuie neglijat, iar sistemul de ajutor al Borland Pascal 7.0 este foarte bine pus la punct. A se folosi cu incredere

Exemplu de folosire a catorva functii:Line number On/Off | Expand/Contract | Select all

1. var caracter: Char;2.     index: Byte;3.     cosinus: Real;4.     putere: Longint;5. begin6.   WriteLn(Chr(97));                   {va afisa litera a

(mica)}7.   WriteLn(Ord('a'));                  {va afisa 97}8.   cosinus := cos(3.1415926535897932); {ar trebui ca

valoarea sa fie egala cu 0}9.   WriteLn(cosinus);                   {si afisam 0}10.   putere := Sqr(5);                   {5 la patrat =

125}11.   WriteLn(putere);                    {si afisam 125}12. end.

Formatarea afisarii

Formatarea afisarii presupune afisarea datelor (cu functiile Write sau WriteLn) care le dorim in alta forma. Contine mai multe cazuri si metode de folosire. Despre formatarea afisarii am vorbit, pe scurt, si in tutorialul anterior de Pascal.

Afisarea normala este o afisare ca in exemplul de mai jos.Line number On/Off | Expand/Contract | Select all

1. WriteLn('Acesta este un test de afisare.');

Sa trecem la formatari.

1. Prima metoda de formatare este de folos cand dorim sa aliniem la dreapta textul care-l vrem afisat.Se foloseste afisand in felul urmator:

Line number On/Off | Expand/Contract | Select all

Page 19: Tutorial Pascal

1. WriteLn('Text de afisat' : 40);

De remarcat secventa : 40. Aceasta secventa specifica pe cate pozitii va fi afisat textul, aliniind textul la dreapta. Daca am vrea sa afisam "bitcell.info" (care contine 12 caractere) pe 20 de pozitii, afisarea va fi facuta punand 8 spatii (20 - 12) si apoi scriind textul.

Daca numarul de pozitii specificat este prea mic, el este ignorat si afisarea se executa ca o afisare normala.

Acest tip de afisare poate fi de folos, de exemplu, cand vrem sa cream un meniu.

2. A doua metoda de formatare a afisarii presupune dublarea secventei care specifica numarul de pozitii pe care se face afisarea, ca in exemplul de mai jos:

Line number On/Off | Expand/Contract | Select all

1. WriteLn(40.234111242:5:2);

Acest tip de formatare se foloseste doar pentru afisarea numerelor reale.

Mergand pe exemplul de mai sus, secventa :2 specifica numarul de zecimale afisat, iar :5 specifica numarul total de pozitii pe care va fi afisat numarul, incluzand punctul zecimal. Afisarea se va face normal, afisand "40.23" (sunt 5 caractere, deci nu se pune niciun fel de spatiu). Daca secventa :5 era, sa zicem :3, ea era ignorata.

Operatii cu tipul logic (Boolean)

Pentru tipul logic de date exista cativa operatori, prezentati mai jos.

Operatori logiciOperator Descrierenot negatieand conjunctie (si logic)or disjunctie (ori logic)xor disjunctie exclusiva

Tabelurile de adevar pentru operatorii AND, OR si XOR sunt date mai jos (negatia nu cred sa aiba nevoie de tabel).

Tabele de adevarAND True False OR True False XOR True FalseTrue True False True True True True False TrueFalse False False False True False False True False

Page 20: Tutorial Pascal

Operatorii relationali care pot fi folositi pentru a genera rezultate logice (de tip Boolean - True sau False), sunt mai jos.

Operatori relationaliOperator Descriere< mai mic> mai mare= egal<= mai mic sau egal>= mai mare sau egal<> diferit

Pe cat posibil, evitati folosirea operatorul de egalitate ( = ) cand vreti sa comparati numere reale. Mici erori de rotunjire pot genera erori destul de mari (1.5678 este diferit de 1.5679).

De tinut minte este faptul ca operatorii folositi in Pascal au, fiecare, o anumita prioritate, care permite compilatorului sa "inteleaga" intern ordinea operatiilor.

Prioritatea operatorilorNivel Operatori Explicatie0 not prioritate maxima1 * / div mod and2 + - or3 < > <= >= = <> prioritate minima

Daca vreti sa fiti siguri ca ordinea operatiilor este cea dorita de dvs., va trebui sa-i explicati compilatorului acest lucru, punand paranteze, ca in matematica.

Atentie: in cazul folosirii operatorilor relationali intr-o expresie logica, este indicat ca fiecare sub-expresie sa fie pusa in interiorul unui set de paranteze, datorita prioritatilor expuse mai sus.

Exemplu de folosire a operatorilor relationali si logici:Line number On/Off | Expand/Contract | Select all

1. var numar: integer;2.     carac: char;3. begin4.   carac := 'd';5.   numar := 5;6.   if (carac = 'D') then7.     Writeln('Caracterul este D');8.   9.   if (carac = 'a') and (numar = 5) then10.     WriteLn('Caracter = a, numar = 5');

Page 21: Tutorial Pascal

11.  12.   if (carac = 'a') or (numar = 5) then13.     WriteLn('Caracter = a SAU numar = 5');14. end.

Sper ca ati inteles faptul ca acest cod va afisa doarLine number On/Off | Expand/Contract | Select all

1. Caracter = a SAU numar = 5

Tipuri de date structurate

O parte din tipurile de date structurate sunt tipuri care pot fi definite de utilizator. Tipurile ordinale, cum ar fi integer, specifica foarte clar marimea ocupata in memorie si tipul de date care-l va contine.

Sa luam, ca exemplu, tipul array. Acest tip de data permite stocarea mai multor date de acelasi tip (ordinal sau structurat). Daca aveti nevoie de un sir de 20 de numere intregi ... sau de 200, array este tot ce aveti nevoie. Totusi, acest tip de data este destul de complex, motiv pentru care exista tutorialul despre vectori si matrici.

Tipul string

Sa presupunem ca aveti nevoie sa stocati un nume, dat de la tastatura. Nu stiti ce lungime, in caractere, va avea, deci nu ar fi practic sa-l salvati intr-un numar de variabila de tip char. Mai tarziu, cand veti ajunge la tipul array, veti gasi o solutie alternativa pentru stocarea unui sir de caractere, dar, pe moment, tipul string este tot ce aveti nevoie.

O variabila de tip string se declara in felul urmator:Line number On/Off | Expand/Contract | Select all

1. var nume: string

In aceasta variabila de tip string vom putea salva numele dat de la tastatura, fara sa ne facem griji. Limitarea acestui tip de data este ca nu poate stoca mai mult de 255 de caractere, dar 255 de caractere este mult prea mult pentru un simplu nume.

Tipul string poate fi vazut ca un sir de maxim 255 de caractere. Fiecare caracter din string poate fi accesat / modificat individual, folosind indexul acelui caracter (indecsii incep de la 1). Programul de mai jos va exemplifica acest lucru.Line number On/Off | Expand/Contract | Select all

1. var nume: string;2. begin3.   nume := 'BitCall'; {Bitcell, scris gresit !}

Page 22: Tutorial Pascal

4.   nume[5] := 'e';5.   write('Numele corect este ', nume);6.   readln;7. end.

O variabila de tip string este stocata intern pe 256 de bytes. Motivul pentru acest lucru este faptul ca pe pozitia 0 din acest sir este stocata lungimea sirului (spre deosebire de C / C++, unde caracterul 0 din ASCII este terminator de sir). Avand in vedere ca numarul maxim de valori care le poate lua un byte este de 256 (intre 0 si 255), ar trebui sa fie clar de ce tipul string poate stoca maxim 255 de caractere (aceasta limitare se refera la Borland Pascal - in alte variante de Pascal sau in Delphi, aceasta limita este ridicata la peste 2 miliarde de caractere).

Functii si proceduri utilizate pentru tipul stringNume Descriere

Length

Aceasta functie returneaza lungimea, in caractere, a variabilei de tip string. Primul caracter (cel de pe pozitia 0 - care specifica lungimea stringului) nu este luat in calcul.

Format apel:Line number On/Off | Expand/Contract | Select all

1. Length(S: String)

Copy

Returneaza un string care contine caracterele specificate din string-ul introdus ca parametru.

Format apel:Line number On/Off | Expand/Contract | Select all

1. Copy(S: string; Index: Integer; Count: Integer);

Stringul rezultat va contine Count caractere, incepand de la pozitia Index inclusiv, din stringul S. Daca Index specifica un numar mai mare decat lungimea totala a stringului, atunci stringul rezultat va fi vid. Daca numarul specificat de Count trece de numarul de caractere totale, incepand de la Index, se va returna tot stringul de la pozitia Index pana la final.

Concat Concateneaza mai multe stringuri intr-unul singur. Returneaza stringul rezultat.

Format apel:Line number On/Off | Expand/Contract | Select all

1. Concat(s1 [, s2, ..., sn]: String);

Alternativ, stringurile pot fi concatenate folosind operatorul +, ca la operatia de

Page 23: Tutorial Pascal

Functii si proceduri utilizate pentru tipul stringadunare. Daca stringul rezultat are mai mult de 255 de caractere, este trunchiat la primele 255 de caractere.

Delete

Procedura care sterge un subsir de caractere dintr-un string.

Format apel:Line number On/Off | Expand/Contract | Select all

1. Delete(var S: String; Index: Integer; Count: Integer);

Din stringul S vor fi sterse Count caractere, incepand cu pozitia Index. Daca Index este mai mare decat lungimea totala stringului, procedura nu avea avea nici un efect. Daca numarul specificat de Count trece de numarul de caractere total, incepand de la Index, stringul va fi trunchiat incepand cu pozitia Index.

Insert

Insereaza un substring intr-un string.

Format apel:Line number On/Off | Expand/Contract | Select all

1. Insert(Source: String; var S: String; Index: Integer);

Stringul Source va fi inserat in stringul S, incepand de la pozitia Index. Daca sirul rezultat va avea mai mult de 255 de caractere, va fi trunchiat la 255 de caractere.

Pos

Cauta pozitia unui subsir intr-un string, returnand pozitia primului caracter al subsirului din sir.

Format apel:Line number On/Off | Expand/Contract | Select all

1. Pos(SubStr: String; S: String): Byte;

Daca subsirul nu este gasit, aceasta functie va returna 0.

Procedurile si functiile expuse mai sus ar trebui sa va poata da o idee despre lucrul cu siruri de caractere in Pascal.

Tipuri de date definite de utilizator

Impreuna cu notiunea de tip, una din cele mai bune noutati introduse de limbajul Pascal este

Page 24: Tutorial Pascal

posibilitatea de a defini noi tipuri de date intr-un program. Programatorii isi pot defini propriile tipuri de date folosind constructorii de tipuri, cum ar fi tipul array, tipul subdomeniu, tipul record, tipul enumerat, tipul set si tipul pointer.

Pascal a fost primul limbaj care a introdus ideea unor constructori de tip definiti intr-un mod formal si foarte precis.

Tipul subdomeniu

Probabil unul din cele mai accesibile tipuri cand e vorba de invatat

Tipul byte permite variabilelor de acest tip sa aiba valori intre 0 si 255. Tipul char permite variabilelor sa ia ca valori orice caracter din ASCII. Ce se intampla daca vreau sa pot lua valori doar intre 1 si 10 ? Sau doar intre literele B si T ?

Declararea acestui tip de data se face in felul urmator:Line number On/Off | Expand/Contract | Select all

1. type nume_tip = limita_inf .. limita_sup;

Nimic mai simplu. Dupa ce ne botezam tipul de date, nu mai avem de facut decat sa specificam limitele valorilor de date, separate prin doua puncte ( .. ), care specifica faptul ca e vorba de un interval.

Restrictii:

limita inferioara trebuie sa fie mai mica decat limita superioara, ca valori acest tip nu poate fi declarat decat folosind valori ordinale

Exemple:Line number On/Off | Expand/Contract | Select all

1. type2.   litere_mari = 'A' .. 'Z';3.   litere_mici = #97 .. chr(122); {metode alternative de

introdus caracter}4.                                  {functioneaza doar din

cod !}5.   note = 1 .. 10;

Tipul multime (set)

Multimile exista peste tot in jurul nostru, iar Pascal ne ofera posibilitatea de a lucru cu ele. Multimele sunt un mod de a clasifica tipuri comune in grupuri. Ca un exemplu din viata, imaginati-va un buchet cu flori de mai multe feluri : o multime de flori

Page 25: Tutorial Pascal

In Pascal, multimile sunt gandite ca avand niste valori dintr-un subdomeniu definit. O multime poate avea una, mai multe sau toate valorile din subdomeniul respectiv. Subdomeniul insusi este denumit multimea de baza, multimea din care orice multime de acelasi tip isi poate lua valori.

Declarare tip:Line number On/Off | Expand/Contract | Select all

1. type multime = set of 1 .. 10;2.      multime_byte = set of byte;

Dupa cum observati, multimile pot fi definite ca avand un subdomeniu de valori sau toate valorile unui anumit tip (ordinal), avand ca restrictie un numar total de maxim 256 de valori distincte.

Operatii cu multimiOperatie Descrierein Apartenenta. Verifica daca un element exista sau nu in multime.

+Reuniune. Rezultatul este o multime care contine toate elementele din cele doua multimi, o singura data.

*Intersectie. Rezultatul este o multime care contine doar acele elemente care exista in ambele multimi.

-Diferenta. Rezultatul este o multime care contine elementele primei multimi care nu apar si in a doua multime.

Un program demonstrativ pentru multimi:Line number On/Off | Expand/Contract | Select all

1. type multime = set of 1..10;2. var n_prime, n_pare: multime; {numere prime mai mici decat

10}3.     i: byte;4. begin5.   n_prime := [2, 3, 5, 7];6.   n_pare := [2, 4, 6, 8];7.  8.   Write('Numere prime: ');9.   for i := 1 to 10 do10.     if (i in n_prime) then {apartenenta}11.       write(i : 3);12.   WriteLn;13.  14.   n_prime := n_prime + [10]; {reuniune}15.   {acum multimea va contine si numarul 6}16.  17.   n_prime := n_prime + n_pare; {reuniune - again}18.   n_prime := n_prime - [5, 7]; {diferenta}

Page 26: Tutorial Pascal

19.  20.   Write('Numere ramase in multime (reuniune,

diferenta): ');21.   for i := 1 to 10 do22.     if (i in n_prime) then {apartenenta}23.       write(i : 3);24.   WriteLn;25.  26.   n_prime := n_pare * [2, 3, 6, 9]; {intersectie}27.   Write('Numere ramase in multime (intersectie): ');28.   for i := 1 to 10 do29.     if (i in n_prime) then {apartenenta}30.       write(i : 3);31.   WriteLn;32.  33.   ReadLn;34. end.

Tipul enumerare

Tipul subdomeniu, explicat mai sus, spune cum putem da note fara sa avem posibilitatea de a da nota 11 ... sau 0. Din pacate, am auzit ca de vreo cativa ani se dau calificative, cel putin pentru elevii claselor primare. Hai sa vedem ce tip de data am putea folosi pentru a stoca niste calificative.

Tipul enumerare ofera posibilitatea definirii unui tip ordinal de data, creand si identificatori pentru posibilele valori.

Declarare tip:Line number On/Off | Expand/Contract | Select all

1. type nume_tip : (ident1 [, ident2, ... identX]);

Fiecare valoare din lista unui tip enumerate are asociat un numar ordinal (primul are valoarea 0), iar variabilelor de acest tip li se pot aplica functiile aplicabile tipurilor ordinale, mai putin Chr.

Un exemplu de cod care foloseste tipul enumerat:Line number On/Off | Expand/Contract | Select all

1. type2.   zile = (luni, marti, miercuri, joi, vineri, sambata,

duminica);3.   calificative = (foarte_rau, rau, suficient, bun,

foarte_bun, grozav);4. var zi: zile;5.     nota: calificative;6. begin

Page 27: Tutorial Pascal

7.   zi := vineri;8.   zi := succ(zi); {acum e sambata}9.  10.   zi := pred(miercuri); {tocmai a devenit marti}11.   WriteLn('Numarul de ordine pentru Marti este ',

Ord(marti), '.');12.   nota := rau;13.   Write('Numarul de ordine pentru "rau" este ',

Ord(nota), '.');14.   ReadLn;15. end.

Restrictii:

identificatorii nu pot fi dublati pe parcursul unui program. identificatorii nu pot fi afisati de Pascal (identificatorul nu are o valoare text pentru

compilatorul Pascal)

Tipul record

Cum am vazut deja la tipul string, si cum vom mai vedea la array-uri, exista posibilitati de a stoca in memorie cantitati mari de date, cu elemente de acelasi tip. Ce se intampla in cazul in care vreau sa stochez mai multe tipuri de date intr-un singur element ?

Un caz concret ar fi varstele unor oameni. Avem nevoie de un loc pentru nume si de un loc pentru varsta ... o variabila string si o variabila byte. Tipul record (inregistrare) permite crearea unui tip de date care sa permita gruparea unor date de tipuri diferite.

Declararea unui tip inregistrare:Line number On/Off | Expand/Contract | Select all

1.  2. type3.   nume_tip = record4.     field1: string;5.     field2: byte;6.     field3: integer7.     ...8.     fieldX: tipX;9.   end;

TipX nu este un tip implicit al Pascal, sper ca e destul de clar. Ideea principala este ca tipul inregistrare poate contine mai multe campuri cu valori de diferite tipuri.

Sa vedem cum facem un programel care sa citeasca si sa afiseze numele si varstele a doua persoane.

Page 28: Tutorial Pascal

Line number On/Off | Expand/Contract | Select all

1. uses crt;2. type3.   persoana = record {tip inregistrare, definit de noi}4.     nume: String;5.     varsta: Byte;6.   end;7.  8. var first, second: persoana; {tipul nostru inregistrare}9. begin10.   ClrScr;11.  12.   Write('Dati numele primei persoane: ');13.   ReadLn(first.nume);14.   Write('Dati varsta primei persoane: ');15.   ReadLn(first.varsta);16.  17.   Write('Dati numele celei de-a doua persoane:');18.   ReadLn(second.nume);19.   Write('Dati varsta celei de-a doua persoane: ');20.   ReadLn(second.varsta);21.  22.   ClrScr;23.   WriteLn('1. Nume: ', first.nume,  ' - varsta: ',

first.varsta,  ' de ani.');24.   WriteLn('2. Nume: ', second.nume, ' - varsta: ',

second.varsta, ' de ani.');25.   ReadKey;26. end.

Dupa cum se poate vedea in program, fiecare camp dintr-o inregistrare se apeleaza folosind numele inregistrarii . (punct) numele campului (fara spatii).

O alta posibilitate oferita de tipul inregistrare este faptul ca pot avea o parte variabila, dar, in afara de a incurca treburile, nu i-am gasit nicio alta utilitate, motiv pentru care nu o voi explica aici.

Celelalte tipuri de date vor fi explicate in tutorialele urmatoare, cand va fi necesar.

Page 29: Tutorial Pascal

Instructiuni conditionale si bucle

La inceputurile informaticii, programarea se facea mai mult dupa ureche, programatorul fiind liber sa foloseasca orice structuri oferite de limbajul de programare in care lucra, fara sa tina cont de posibilitatea ca un alt programator ar avea mari dificultati daca ar incerca sa corecteze / dezvolte programul facut de el. Salturile neconditionate (GOTO) si structurile cu mai multe puncte de intrare sau iesire erau un lucru foarte obisnuit.

In mai 1966, Bohm si Jacopini au demonstrat ca orice algoritm poate fi compus din numai trei structuri de calcul:

structura secventiala structura alternativa structura repetitiva

In 1968, Dijkstra a publicat un articol denumit "Un caz impotriva structurii GOTO" (A Case against the GO TO Statement), care de fapt este metodologia a ceea ce astazi numim programare structurata.

Programarea structurata este, in conceptia celor mentionati mai sus, cel mai simplu mod de a crea un program care este usor de inteles si usor de corectat / dezvoltat.

Sa luam cele trei structuri de mai sus in ordine.

Structura secventiala

Este cea mai usoara structura intalnita intr-un program. In programul de mai jos (care face suma a doua numere citite de la tastatura) :Line number On/Off | Expand/Contract | Select all

1. var a, b: integer;2. begin3.   write('Dati a: '); readln(a);4.   write('Dati b: '); readln(b);5.   write('Suma celor doua numere este ', a + b);6.   readln;7. end.

, nu intalnim alta structura de calcul decat cea secventiala. Cu asta vreau sa spun ca toate instructiunile vor fi folosite, pe rand, in ordine, fara ca vreuna din instructiuni sa se repete. Suna ca o reteta usoara de mancare, nu ? Exact asa si este.

Structura alternativa

Este o structura de calcul care permite, in functie de anumite conditii, executarea (sau neexecutarea) unei anumite instructiuni sau secventa de instructiuni. Programul de mai jos

Page 30: Tutorial Pascal

vrea sa faca suma a doua numere, in afara de cazul in care primul numar este 0 (zero), caz in care aduna al doilea numar cu el insusi :Line number On/Off | Expand/Contract | Select all

1. var a, b: integer;2. begin3.   write('Dati a: '); readln(a);4.   write('Dati b: '); readln(b);5.   If a <> 0 Then write('Suma celor doua numere este ',

a+b)6.             Else write('Suma celor doua numere este ',

b+b);7.   readln;8. end.

Deci, am pus o conditie si in functie de ea executam o parte sau alta a codului. Parca suntem in viata. Ne ofera cineva ceva, dar noi nu acceptam decat daca pretul e mai mic sau egal cu o anumita suma, pentru ca altfel ni se pare prea mare pretul.

Structura repetitiva

Este o structura de calcul care permite, in functie de anumite conditii, executarea unei anumite instructiuni sau secventa de instructiuni de N ori (unde N poate fi 0, 1 sau mai mult). Programul de mai jos citeste doua numere de la tastatura si va aduna primul numar cu el insusi de atatea ori cat e valoarea celui de-al doilea :Line number On/Off | Expand/Contract | Select all

1. var a, b, suma: integer;2. begin3.   write('Dati a: '); readln(a);4.   write('Dati b: '); readln(b);5.   suma := 0;6.   For b := 1 To b Do7.     suma := suma + a;8.   write('Suma este ', suma);9.   readln;10. end.

Este simplu, doar adunam valoarea din A de B ori, altfel spus inmultim A cu B. Totusi, scopul acestui program nu e de a face inmultirea, ci de a explica structura repetitiva

Aceste trei structuri de calcul s-au dovedit de-a lungul timpul a fi, intr-adevar, singurele strict necesare crearii unui program, motiv pentru care nici nu o sa explic in aceste tutoriale cum se folosesc, in Pascal, salturile neconditionate (desi exista aceasta posibilitate).

Instructiuni conditionale

Avem la dispozitie doua tipuri de instructiuni conditionale in Pascal: If ... Then ... [Else ... ] si

Page 31: Tutorial Pascal

Case.

Sa incepem cu inceputul.

Structura If ... Then ... [Else ... ]

Are doua sintaxe, putin diferite. Cea mai obisnuita este mai jos:Line number On/Off | Expand/Contract | Select all

1. If conditie2.   Then instructiune13.   Else instructiune2;

conditie este o comparatie sau orice altceva care returneaza o valoarea logica (True sau False), cum ar fi suma = 5 ("=" semnifica egalitate, nu atribuire !)

instructiune1 si instructiune2 pot fi orice fel de instructiuni, inclusiv instructiunea compusa.

Atentie:In cazul folosirii acestei sintaxe, semnul " ; " (punct si virgula) nu numai ca nu este necesar dupa instructiune1, ci este interzis sa fie pus acolo.

A doua varianta a acestei structuri conditionale este cea in care nu avem ramura de else :Line number On/Off | Expand/Contract | Select all

1. If conditie2.   Then instructiune1;

Atentie:In cazul folosirii acestei sintaxe, semnul " ; " (punct si virgula) este strict necesar dupa instructiune1.

Sa exemplificam aceste structuri prin programul de mai jos:Line number On/Off | Expand/Contract | Select all

1. var varsta: integer;2.      sex: char;3. begin4.   write('Ce varsta aveti ? '); ReadLn(varsta);5.   write('Sunteti baiat sau fata ? (M / F) : ');

ReadLn(sex);6.  7.   If (sex = 'f') or (sex = 'F')8.     Then WriteLn('Sex feminin')9.     Else WriteLn('Sex masculin');10.  11.   If varsta > 17 Then12.     WriteLn('Persoana majora');13.  

Page 32: Tutorial Pascal

14.   ReadLn;15. End.

Pentru a intelege programul, sa-l luam pas cu pas. Am definit doua variabile, una de tip integer (valoare numerica) denumita varsta si una de tip Char (un singur caracter) denumita sex.

Dupa citirea de la tastatura a valorilor pentru aceste doua variabile, verificam daca variabila sex e cumva litera F. De remarcat ca am folosit operatorul logic OR pentru a verifica daca variabila are valoarea f sau F, ambele insemnand faptul ca sexul este feminin, caz in care afisam acest lucru. Pe ramura de Else, stiind ca sexul nu este feminin, am pus direct afisare ca sexul este masculin, ceea ce nu este tocmai corect. Trebuia facuta o verificare si daca valoarea variabilei sex este m sau M, pentru a asigura acuratetea programului. In programul de mai sus, daca pentru variabila sex introducem litera c, progamul va afisa tot "Sex masculin", dar momentan scopul meu nu e de a crea programe fara bug-uri, ci doar de a va explica modul de functionare a structurilor conditionale.Pentru varsta facem o singura verificare, anume daca varsta este strict mai mare decat 17 (adica minim 18), caz in care afisam "Persoana majora".

Sa refacem programul pentru a lua in calcul si alte cazuri (cum ar fi verificarea pentru sexul masculin, varste negative sau peste 150 de ani )Line number On/Off | Expand/Contract | Select all

1. var varsta: integer;2.      sex: char;3. begin4.   write('Ce varsta aveti ? '); ReadLn(varsta);5.   write('Sunteti baiat sau fata ? (M / F) : ');

ReadLn(sex);6.  7.   If (sex = 'f') or (sex = 'F')8.     Then WriteLn ('Sex feminin')9.     Else10.       If (sex = 'm') or (sex = 'M')11.         Then WriteLn ('Sex masculin')12.         Else WriteLn ('Sex necunoscut, probabil

neutru');13.  14.   If (varsta < 0)15.     Then WriteLn ('Persoana care este inca in planuri

de viitor')16.     Else17.       If (varsta < 18)18.         Then WriteLn ('Persoana minora')19.         Else20.           If (varsta < 60)21.             Then WriteLn ('Persoana majora')22.             Else23.               If (varsta < 150)

Page 33: Tutorial Pascal

24.                 Then WriteLn ('Persoana in varsta')25.                 Else WriteLn ('Personaj biblic');26.  27.   ReadLn;28. End.

Dupa cum vedeti, in noul program am luat in calcul ca variabila sex poate reprezenta sex feminin, sex masculin sau un caracter care nu reprezinta nici unul din acestea doua cazuri. Pentru aceasta, am folosit instructiuni conditionale imbricate (adica una in interiorul alteia). Arata urat, nu ? In plus, e si destul de greu de inteles.Cu toate acestea, pentru variabila varsta am facut chiar si mai multe verificari, folosind multiple instructiuni conditionale imbricate. E deja mai urat si chiar si mai greu de inteles.Nu am de facut decat sa va recomand multa atentie cand creati sau recititi programul ... si sa va prezint instructiunea conditionala multipla, ca o alternativa la instructiunea If ... Then ... [Else ... ]

Structura Case

Instructiunea Case, denumita si instructiune alternativa multipla, ofera posibilitatea verificarii unei variabile pe un set mai intins de valori, fara a da dureri de cap la crearea sau recitirea programului.

Sintaxa generala:Line number On/Off | Expand/Contract | Select all

1. Case variabila_simpla Of2.   val_posibile1 : instructiune1;3.   val_posibile2 : instructiune2;4.   ...5.   val_posibileX : instructiuneX;6.   Else instructiuneY;7. End;

Sa incercam sa intelegem aceasta sintaxa, care pare a fi ceva mai complicata decat sintaxa instructiunii dinainte.Variabila_simpla desemneaza orice variabila de un tip simplu de date (vedeti tutorialul anterior). Nu poate fi folosit aici, de exemplu, tipul String, el nefiind un tip simplu de date.Val_posibile1, Val_posibile2 si Val_posibileX tin locul unei (sau a mai multor) valori posibile pentru variabila_simpla. Daca valoarea variabilei variabila_simpla e egala (sau inclusa) cu vreuna din valorile posibile, atunci va fi executat setul corespunzator de instructiuni.Instructiune1, instructiune2 si instructiuneX pot fi orice fel de instructiuni, inclusiv cele compuse.Pe ramura de Else avem acelasi lucru ca si la instructiunea If ... Then ... [Else ... ], adica o anumita instructiune care se executa in cazul in care valoarea variabilei variabila_simpla nu se regaseste in optiunile de mai sus (Val_posibile1, Val_posibile2, Val_posibileX). Aceasta ramura, ca si la If ... Then ... [Else ... ], poate ramane nefolosita.

Page 34: Tutorial Pascal

Sa refacem programul de mai sus, folosind aceasta noua instructiune.Line number On/Off | Expand/Contract | Select all

1. var varsta: integer;2.      sex: char;3. begin4.   write('Ce varsta aveti ? '); ReadLn(varsta);5.   write('Sunteti baiat sau fata ? (M / F) : ');

ReadLn(sex);6.   7.   Case sex Of8.     'f','F' : WriteLn('Sex feminin');9.     'm','M' : WriteLn('Sex masculin');10.     Else Writeln('Sex necunoscut, probabil neutru');11.   End;  12.   13.   Case varsta Of14.     0 .. 17       : WriteLn('Persoana minora');15.     18 .. 60      : WriteLn('Persoana majora');16.     61 .. 150     : WriteLn('Persoana in varsta');17.     151 .. maxint : WriteLn('Personaj biblic');18.     -maxint .. -1 : WriteLn('Persoana care este inca

in planuri de viitor');19.   End;  20.   21.   ReadLn;22. End.

Dupa cum vedeti, e mult mai usor de folosit si este mult mai clara. Singurul lucru care cred ca mai e necesar sa vi-l explic este ce inseamna, 'f','F' si 18 .. 60. Structura Case, dupa cum am explicat anterior, permite ca, pentru o anumita instructiune, sa verificam mai multe valori posibile. Aceste valori pot fi scrise una cate una si despartite prin virgula (cum a fost in cazul variabilei sex) sau pot fi scrise ca un sir de valori, in care se ofera valoarea minima si apoi valoarea maxima, aceste doua valori fiind despartite prin " .. " (doua puncte unul dupa celalalt).

Cam asta ar fi toata partea de instructiuni conditionale in Pascal. Sa trecem la ...

Bucle (instructiuni repetitive)

Buclele (instructiuni de ciclare) sunt niste instructiuni care asigura repetarea pe un anumit numar de pasi a unor anumite instructiuni.

Sa ne imaginam ca vrem sa facem un program care sa afiseze crescator, de la 1 la 20, toate numerele. E destul de simplu sa le afisam cu o instructiune Write (sau mai multe). Dar sa presupunem ca vrem sa facem acelasi lucru pana la 1.000 ... sau pana la 1.000.000 ... cred ca sunteti de acord ca ar fi "cam" mult de lucru.

Aici apare nevoia de bucla, pentru a repeta un set de instructiuni de un numar dat de ori.

Page 35: Tutorial Pascal

In Pascal, sunt trei tipuri de instructiuni de ciclare:

While Repeat For

Bucla While

Sintaxa generala a acestei instructiuni este:Line number On/Off | Expand/Contract | Select all

1. While conditie Do instructiune;

Conditie poate fi orice comparatie sau orice altceva ce are ca rezultat True sau False. Se poate apela siLine number On/Off | Expand/Contract | Select all

1. While True Do instructiune;

, caz in care nu se poate iesi din bucla din cauza conditiei. Daca nu exista in interiorul acestei bucle o instructiune de iesire (Break), atunci bucla va fi infinita (nu va mai iesi din ea, programul se va bloca si va trebui terminat cu Ctrl + Break, sau si mai rau, din Task Manager sau reboot).In general, conditia va face referire la o conditie care va deveni adevarata, pe masura bucla lucreaza sau este o simpla verificare a unui contor, caz in care putem calcula dinainte exact cate ciclari va face bucla (de cate ori va repeta instructiunile aflate in interior).

De remarcat ca iesirea din bucla se va face doar cand conditia va returna valoarea False. E si destul de usor de inteles asta : While conditie Do instructiune care in limbaj natural ar suna Cat timp conditia_mea_e_adevarata Fa ceva.

Aceasta instructiune mai este denumita si "instructiune repetitiva cu test initial" (testul de iesire din bucla se face la inceput). Instructiunile din aceasta bucla nu se vor executa nici macar o data, daca testul de iesire returneaza valoarea False de la inceput.

Instructiune poate fi orice fel de instructiune, inclusiv instructiunea compusa.

Sa vedem cum am putea face in Pascal, folosind bucla While, programul de mai sus care afiseaza pana la 20.Line number On/Off | Expand/Contract | Select all

1. var cnt : integer;2. begin3.   cnt := 1;4.   While cnt <= 20 Do5.     Begin6.     WriteLn(cnt);7.     cnt := cnt + 1;

Page 36: Tutorial Pascal

8.     End;9.   ReadLn;10. end.

Sa analizam programul. Prima oara am declarat o variabila de tip integer (care poate lua valori intre -32768 si 32767), care va fi ceea ce denumim contorul buclei. Initializam contorul cu 1, aceasta fiind prima valoare ce va trebui afisata, apoi afisam contorul, care apoi va fi marit cu o unitate.Pe masura ce avansam, ajungem cu Cnt = 20. Ce se va intampla atunci : va fi afisat (20), contorul va fi crescut la 21 si programul va reveni la conditia de la inceputul buclei : este Cnt mai mic sau egal cu 20 ? Evident, nu mai este cazul, motiv pentru care se trece la executarea urmatoarei instructiuni din program, anume ReadLn.

Sa vedem cum am putea face programul daca am initializa Cnt cu valoarea 0.Line number On/Off | Expand/Contract | Select all

1. var cnt : integer;2. begin3.   cnt := 0;4.   While cnt < 20 Do5.     Begin6.     cnt := cnt + 1;7.     WriteLn(cnt);8.     End;9.   ReadLn;10. end.

Ok, ar trebui sa fie evident. Tot ce am facut a fost sa:

schimb conditia de iesire din bucla, din <= in simplul < inversez instructiunea de crestere a contorului cu cea de afisare

De ce am facut asta ? In primul rand, trebuia sa inversam instructiunile, fiindca altfel ar fi inceput afisarea cu 0, nu cu 1, cum se cerea. Cealalta modificare se refera la faptul ca in momentul care am afisat 20, trebuie iesit din bucla. Inca un ciclu (determinat de o conditie cnt <= 20 ar rezulta in afisarea lui 21, lucru pe care iar nu-l vrem.

Cred ca acum ati inteles cum sta treaba cu While, so ... next one

Bucla Repeat

Sintaxa general a instructiunii Repeat este:Line number On/Off | Expand/Contract | Select all

1. Repeat2.   instructiune;3. until conditie;

Page 37: Tutorial Pascal

Spre deosebire de While, iesirea din aceasta bucla se face atunci cand valoarea conditiei este True. Pentru o bucla infinita se va folosi:Line number On/Off | Expand/Contract | Select all

1. Repeat2.   instructiune;3. until False;

De remarcat ca instructiune nu e necesar sa fie instructiune compusa. Cu alte cuvinte, nu este necesar sa puneti Begin ... End pentru a delimita bucla, acest lucru fiind facut de Repeat ... Until.

Aceasta instructiune mai este denumita si "instructiune repetitiva cu test final" (testul de iesire din bucla se face la sfarsit). Instructiunile din aceasta bucla se vor executa macar o data, daca testul de iesire returneaza valoarea True la prima testare.

Sa rescriem programul initial folosind aceasta instructiune.Line number On/Off | Expand/Contract | Select all

1. var cnt : integer;2. begin3.   cnt := 1;4.   Repeat5.     WriteLn(cnt);6.     cnt := cnt + 1;7.   Until cnt > 20;8.   ReadLn;9. end.

De remarcat conditia de iesire din bucla, care este exact opusul celei folosite in cazul buclei While (desi e destul de simplu de inteles, avand in vedere motivele terminarii fiecarei bucle).

Singurul lucru care il am de adaugat (fiindca e destul de usor de inteles, avand in vedere explicatiile anterioare) e faptul ca dupa ce cnt are valoarea 20 si este afisat, va fi crescut cu 1 (devenind 21), caz in care conditia devine adevarata (cnt > 20), motiv pentru care se iese din bucla.

Daca am initializa contorul cu 0, programul ar fi asa:Line number On/Off | Expand/Contract | Select all

1. var cnt : integer;2. begin3.   cnt := 0;4.   Repeat5.     cnt := cnt + 1;6.     WriteLn(cnt);7.   Until cnt >= 20;

Page 38: Tutorial Pascal

8.   ReadLn;9. End.

Din nou, avem conditia de la While, dar inversata. Cam asta ar fi si Repeat-ul ... easy, nu ?

Atentie:Inversa conditiei > este <=, iar a conditiei < este >=.

Bucla For

Sintaxa generala la For cunoaste 2 cazuri: crescator sau descrescator.

Cazul crescator:Line number On/Off | Expand/Contract | Select all

1. For contor = val_initiala To val_finala Do instructiune;

Cazul descrescator:Line number On/Off | Expand/Contract | Select all

1. For contor = val_initiala DownTo val_finala Do instructiune;

Motivul pentru care avem aceasta distinctie e faptul ca nu mai avem direct controlul asupra contorului buclei, acesta fiind crescut / scazut de bucla, scapandu-ne astfel de o grija. Din pacate, in felul acesta nu putem decat sa mergem cu pasi de cate o unitate (crescator sau descrescator). In cazurile While sau Repeat, puteam creste contorul cu cat vroiam noi (am ales sa-l cresc cu 1 doar pentru exemplificare).

Dupa cum ati observat, aici nu mai avem nici o conditie de iesire din bucla. Iesirea din aceasta bucla se face in momentul in care val_initiala devine mai mare / mai mica cu o unitate decat val_finala. De asemenea, daca se foloseste sintaxa cu To se sare peste bucla in cazul in care val_initiala este mai mare decat val_finala si invers.

De remarcat e faptul ca nu mai trebuie sa initializam contorul inaintea buclei (il initializam, de fapt, direct in bucla).

Programul de mai sus, scris cu o bucla For ar arata in felul urmator:Line number On/Off | Expand/Contract | Select all

1. var cnt : integer;2. begin3.   For cnt := 1 To 20 Do4.     WriteLn(cnt);5.   ReadLn;  6. End.

Page 39: Tutorial Pascal

Dupa cum vedeti, contorul nu prea mai e in grija noastra (iar unele compilatoare chiar dau eroare daca veti incerca sa-i modificati valoarea in interiorul buclei).

Sa incercam acum sa lucram cu varianta descrescatoare pentru a face acelasi program Line number On/Off | Expand/Contract | Select all

1. var cnt : integer;2. begin3.   For cnt := 20 DownTo 1 Do4.     WriteLn(20 - cnt + 1);5.   ReadLn;  6. End.

Ok, programul merge ... dar de ce am pus formula aceea ciudata acolo ? Trebuie sa tineti cont de faptul ca acum contorul merge de la 20, descrescator, spre 1, exact invers de cum ne-am obisnuit, asa ca prima valoare a lui cnt este 20. Pentru prima afisare, daca scadem 20 din 20 si adaugam 1 (ca in formula), ne da 1, exact ce trebuie afisat. Sa incercam pentru cazul in care cnt este 2 ... 20 - 2 + 1 = 19, deci asta e penultimul numar care va fi afisat, ultimul fiind, evident, 20.

Instructiuni de control pentru bucle

Instructiunea Continue

Sa presupunem ca avem o bucla care afiseaza numerele de la 1 la 20, ca si in exemplele de mai sus, dar nu vrem sa afisam numarul 9. Cum putem face acest lucru ?

Foarte simplu. Trebuie sa "sarim" peste o executie a buclei, cea in care indexul are valoarea 9, inainte de a afisa numarul. Pentru acest lucru folosim instructiunea Continue.

Sa vedem un exemplu, folosind bucla FOR:Line number On/Off | Expand/Contract | Select all

1. var cnt : integer;2. begin3.   For cnt := 1 To 20 Do4.     begin5.       if cnt = 9 then6.         Continue; {daca indexul este egal cu 9, nu

executam instructiunea de afisare}7.       WriteLn(cnt);8.     end;9.   ReadLn;  10. End.

Instructiunea Continue sare la urmatorul ciclu al buclei, indiferent ca e vorba de bucla While, Repeat sau For.

Page 40: Tutorial Pascal

Instructiunea Break

Ce facem daca avem nevoie sa scriem un program care afiseaza numerele de la 1 la 20, dar numai atat timp cat suma numerelor afisate este mai mica decat 35 ?

Pentru acest lucru trebuie sa facem o suma, pe care o crestem cu valoarea indexului la fiecare afisare. Aceasta suma o vom verifica inainte de urmatoarea afisare si, daca este mai mai mare sau egala cu 35, folosim instructiunea Break.

Sa modificam programul de mai sus pentru un mic exemplu:Line number On/Off | Expand/Contract | Select all

1. var cnt, suma : integer;2. begin3.   suma := 0;4.   For cnt := 1 To 20 Do5.     begin6.       suma := suma + cnt;7.       if suma >= 35 then8.         Break; {iesim din bucla}9.       WriteLn(cnt);10.     end;11.   ReadLn;  12. End.

Acest program va afisa numerele de la 1 la 7, inclusiv, fiindca 1 + 2 + ... + 8 = 36.

Instructiunea Break opreste bucla din care este apelata. dar nu poate opri decat o singura bucla. Daca aceasta instructiune este folosita in interiorul unei bucle care este imbricata in alta bucla, doar bucla interioara va fi oprita.

Page 41: Tutorial Pascal

Vectori (tablouri, matrici)

Probabil ca acum, dupa ce ati parcurs primele 3 tutoriale de Pascal de pe aici, stiti sa faceti suma a doua numere, citite de la tastatura. Probabil ca vi se pare chiar usor. Sa zicem ca vreau sa-mi si afisati cele doua numere dupa ce-ati afisat suma. Nimic iesit din comun.

Ce-ati zice daca v-as cere un program care sa faca suma a trei numere ? E posibil sa nu va deranjeze prea tare ... nu e mare lucru sa adaugi o variabila, sa-i citesti valoarea de la tastatura si sa o aduni la suma. Chiar si afisarea celor trei numere nu ar trebui sa dea batai de cap nimanui.

Ce-ati zice daca v-as cere un program care face suma a 1000 de numere, afisand apoi fiecare numar introdus de la tastatura ?

E clar, e momentul pentru un alt tip de date, unul structurat, capabil sa tina in memorie siruri de date. Primul tip de date structurat care l-am prezentat in Tipuri de date in Pascal este tipul tablou. Pentru acest tip de date se folosesc mai multe sinonime, cum ar fi vector, matrice sau englezismul array. Toate se refera la acelasi lucru. Sa incepem cu inceputul.

Vectori unidimensionali

Ca sa putem folosi acest nou tip de date, trebuie sa-l declaram. Modalitatea de declarare a unui vector unidimensional cu capacitatea de 1000 de numere intregi (pe 2 bytes, in acest caz) este urmatoarea:Line number On/Off | Expand/Contract | Select all

1. sir : array [1 .. 1000] of Integer;

So, punem cuvantul cheie "array", punem indexul de inceput al sirului (poate fi si -17 ), punem ".." pentru a specifica faptul ca e vorba de un interval, punem indexul de sfarsit (1000 in exemplul de mai sus), adaugam cuvantul cheie "of" (asa-i romanul, plin de ofuri ), specificam tipul datelor care vor face parte din vector ... si nimic mai mai mult.

ExempleLine number On/Off | Expand/Contract | Select all

1. var test: array [65 .. 122] of char;2.     test2: array ['H' .. 'a'] of boolean;

Page 42: Tutorial Pascal

Nu va speriati, si varianta in care am pus litere pe post de indecsi e functionala. Rar folosita, dar posibila. Deci ... un vector de caractere (cu indecsi intre 65 si 122 ... si un vector de valori logice, intre 'H' si 'a' ... adica un vector cu 25 de pozitii).

Cum se spune, nimic mai simplu. Avem variabila sir care are 1000 de pozitii si imi permite sa salvez cate un numar pe fiecare dintre aceste pozitii. Singura (posibila) problema este faptul ca nu putem salva decat numere intregi in acest sir. Elementele unui vector trebuie sa aiba acelasi tip.

Nu se pot defini vectori ale caror elemente sa fie fisiere.

Modalitatea de accesare a unei anumite pozitii din sir se face scriind numele sirului (sir in cazul acesta) si, intre paranteze drepte, [ si ], indicele (pozitia) din sir care o dorim.Line number On/Off | Expand/Contract | Select all

1. sir[17] := 2342;

In acest fel, fiecare pozitie a vectorului poate fi privita ca o variabila de sine statatoare, scrisa putin mai ciudat.

Atentie: Nu confundati pozitia unui element din vector cu valoarea lui.Daca am valorile urmatoare in vector (in ordine): 159, 65, 78, 23, 72, 34 ... atunci elementul de pe pozitia 3 are valoarea 78. Atentie maxima, am vazut multe aiureli cauzate de confuzii de acest gen.

Alta problema destul de comuna este incercarea de a folosi vectori care ocupa mai mult decat capacitatea de memorie alocata de catre Pascal. Aceste incercari vor determina compilatorul de Borland Pascal 7.0 sa genereze o eroare de compilare cu mesajul "Structure too large".

Compilatorul de Borland Pascal 7.0 ofera un spatiu de memorie de maxim 64KB per fisier al programului (momentan, un singur fisier). Exista alte compilatoare care ofera mult mai mult si care, evident, nu dau asemenea erori.

Stiind ca un element al unui vector este apelat folosind indexul lui, devine deja clar ca putem folosi bucle pentru lucrul cu vectori.

Hai sa vedem cum citim 1000 de numere, folosind vectori si o bucla For (daca nu mai stiti ce e o bucla For, Instructiuni repetitive va mananca ).Line number On/Off | Expand/Contract | Select all

1. uses crt;2. var sir : array [1 .. 1000] of Integer;3.     i, n: Integer;4. begin5.   Write('Dati numarul de valori care doriti sa le

introduceti: ');6.   ReadLn(n);7.  

Page 43: Tutorial Pascal

8.   For i := 1 To n Do   {citim toate elementele de la tastatura ...}

9.     begin10.       Write('Dati elementul ', i : 4, ' : ');11.       ReadLn(sir[i]);  {... si le salvam in vector}12.     end;13.   ClrScr;14.  15.   For i := 1 To n Do   {afisam elementele citite de

la tastatura}16.     Write(sir[i]:8);17.   ReadLn;18. end.

Pentru amuzament, hai sa dam valorile elementelor din vector in felul urmator: pe o pozitie sa fie valoarea 1, pe urmatoarea sa fie valoarea 0, pe urmatoarea pozitie iar 1, and so on.Line number On/Off | Expand/Contract | Select all

1. uses crt;2. var sir : array [1 .. 1000] of Integer;3.     i, n: Integer;4. begin5.   Write('Dati numarul de valori care doriti sa le

introduceti: ');6.   ReadLn(n);7.  8.   For i := 1 to n Do   {aici se pune 1, 0, 1, 0, 1 ...}9.     sir[i] := i mod 2; {simplu, nu ?}10.  11.   For i := 1 To n Do   {afisam elementele}12.     Write(sir[i]:8);13.   ReadLn;14. end.

Cam asta ar fi ce este de explicat la vectorii unidimensionali, acum puneti-va centura de siguranta pentru ...

Vectori multidimensionali

Care-i problema cu vectorii astia ? De ce nu pot fi toti la fel ? De ce ne trebuie vectori unidimensionali, si bidimensionali, si tridimensionali, si dimensionali intr-o dimensiune pe care nu o pot vizualiza ... ?

Raspunsul e simplu: nu stiu

Vectorii unidimensionali, intr-un mod cat se poate de evident, aveau o singura dimensiune, lungime, care era definita de numarul de elemente din ei. Hai sa ne imaginam vectorul unidimensional ca pe o linie din foaia de matematica: un sir de casute, nu ? Fiecare casuta

Page 44: Tutorial Pascal

accepta o cifra (sau, daca scrii ca mine, trei ), deci fiecare element e de acelasi tip.

Totusi, foaia de matematica are doua dimensiuni, lungime si latime. E un tabel. Cum definesti un vector unidimensional in asa fel incat sa-l poti folosi ca pe un tabel ? Nu o faci. Folosesti un vector bidimensional, care este chiar un tabel, nu ?

P.S. ca informatie relativ utila, vectorii unidimensionali pot fi folositi ca vectori multidimensionali. Memoria video este vazuta, practic, ca un vector unidimensional, dar noi o vedem bidimensional. Asta va spune ceva ?

Hai sa vedem cum definim un vector bidimensional, fiindca sunt sigur ca nici nu va trece prin cap Line number On/Off | Expand/Contract | Select all

1. tabel = array [1.. 10, 1 .. 20] of integer;

Asemanator cu vectorii unidimensionali, nu ? Primul set (1 .. 10) determina numarul de linii, iar al doilea numarul de (20 de) coloane.

Accesul la elementul de pe o anumita pozitie necesita acum doi indecsi, ceea ce e normal:Line number On/Off | Expand/Contract | Select all

1. tabel[2, 5] := 124;

Codul acesta poate fi citit in felul urmator: elementul de pe linia 2, coloana 5 din matricea denumita "tabel" va lua valoarea 124.

Hai sa facem o tabla de sah (de 8x8) si sa o umplem, ca si in exemplul de mai sus, cu 1 si 0.Line number On/Off | Expand/Contract | Select all

1. uses crt;2. var sir : array [1 .. 1000] of Integer;3.     tabla: array [1 .. 8, 1 .. 8] of byte;4.     i,j, n: Integer;5. begin6.   for i := 1 to 8 do7.     for j := 1 to 8 do8.       tabla[i, j] := (i + j) mod 2;9.  10.   for i := 1 to 8 do11.     begin12.       for j := 1 to 8 do13.         write(tabla[i,j]:2);14.       writeln;15.     end;16. end.

Page 45: Tutorial Pascal

Rezultatul acestei bucati de cod poate fi admirat in imaginea urmatoare:

So, cam asta ar fi si cu vectorii bidimensionali (matrice) ... cred ca v-am speriat degeaba ... puteti sa va dati jos centura de siguranta.

Vectorii cu mai mult de 2 dimensiuni se declara la fel (cu modificarile de rigoare), iar elementele din asemenea vectori sunt folositi la fel (din nou, cu modificarile de rigoare).

Atentie: Indiferent de numarul de dimensiuni al vectorului, indiferent de numarul de elemente pe care le contine, aveti grija sa nu incercati sa accesati pozitii care nu exista (cum ar fi pozitia 1001 sau 2000 in vectorul cu 1000 de elemente). In cel mai bun caz, valoarea citita de acolo va fi aleatoare. In cel mai rau caz veti primi un AV (access violation pentru necunoscatori) sau vreo eroare de rulare (runtime error).

Matrici patratice

Matricile patratice sunt acei vectori bidimensionali a caror numar de linii este egal cu numarul de coloane.

La acest tip de matrice putem vedea niste lucruri interesante, cum ar fi faptul ca numarul de elemente este egal cu latura2 (clar, nu?) ... sau ca are diagonale. Prin faptul ca are diagonale ma refer ca exista o serie de elemente ale matricii care determina respectivele diagonale.

Diagonalele unei matrici patratice sunt denumite: diagonala principala si diagonala secundara. Diagonala principala porneste din coltul din stanga sus si se termina in coltul din dreapta jos. Diagonala secundara incepe in coltul din dreapta sus si se termina in coltul din stanga jos.

In urmatoarea imagine puteti vedea rezultatul unui program care identifica elementele celor doua diagonale ale unei matrici patratice de 8x8. Diagonala principala este afisata cu rosu, iar cea secundara cu galben.

Page 46: Tutorial Pascal

Codul programului care a scos acest rezultat este:Line number On/Off | Expand/Contract | Select all

1. uses crt;2. var tabla: array [1 .. 8, 1 .. 8] of byte;3.     i, j: Integer;4. begin5.   clrscr;6.   for i := 1 to 8 do7.     for j := 1 to 8 do8.       tabla[i, j] := (i + j + 1) mod 2;9.  10.   for i := 1 to 8 do begin11.     for j := 1 to 8 do12.       begin13.         textcolor(LightGray);14.  15.         if (i = j) then16.           TextColor(LightRed); {diagonala principala}17.         if (i = 8 - j + 1) then18.           TextColor(Yellow); {diagonala secundara}19.  20.         write(tabla[i,j]:2);21.       end;22.     writeln;23.                      end;24.  25.   ReadLn;26. end.

Daca ati analizat putin codul, ar trebui sa va fie clar ca un element din matrice face parte din diagonala:

principala, daca indecsii au aceeasi valoare (i = j) secundara, daca indecsii se supun formulei urmatoare: i = n - j + 1, unde i, j sunt

indecsii de linie, respectiv coloana, iar n este latura matricii patratice.

Daca nu ati inteles de ce, luati o foaie si un pix (sau creion sau orice care lasa semne pe hartie)

Page 47: Tutorial Pascal

si verificati formulele

Hai sa vedem cum aflam elementele din sectiuni demarcate de diagonale.

Aici, cu albastru, elementele de deasupra diagonalei principale.

Codul necesar:Line number On/Off | Expand/Contract | Select all

1. uses crt;2. var tabla: array [1 .. 8, 1 .. 8] of byte;3.     i, j: Integer;4. begin5.   clrscr;6.   for i := 1 to 8 do7.     for j := 1 to 8 do8.       tabla[i, j] := (i + j + 1) mod 2;9.  10.   for i := 1 to 8 do begin11.     for j := 1 to 8 do12.       begin13.         textcolor(LightGray);14.  15.         if (i = j) then {diagonala principala}16.           TextColor(LightRed);17.  18.         if (i = 8 - j + 1) then {diagonala secundara}19.           TextColor(Yellow);20.  21.         if (j > i) then {deasupra diagonalei

principale}22.           TextColor(LightBlue);23.  24.         write(tabla[i,j]:2);25.       end;26.     writeln;27.                      end;28.  29.   ReadLn;30. end.

Page 48: Tutorial Pascal

Dupa cum se vede, elementele de deasupra diagonalei principale au proprietatea ca indexul coloanei (j) este mai mare decat indexul liniei (i). Simplu.

Tot cu albastru, elementele de sub cele doua diagonale:

1. uses crt;2. var tabla: array [1 .. 8, 1 .. 8] of byte;3.     i, j: Integer;4. begin5.   clrscr;6.   for i := 1 to 8 do7.     for j := 1 to 8 do8.       tabla[i, j] := (i + j + 1) mod 2;9.  10.   for i := 1 to 8 do begin11.     for j := 1 to 8 do12.       begin13.         textcolor(LightGray);14.  15.         if (i = j) then {diagonala principala}16.           TextColor(LightRed);17.  18.         if (i = 8 - j + 1) then {diagonala secundara}19.           TextColor(Yellow);20.  21.         if (i > j) and (i > 8 - j + 1) then {sub cele

doua diagonale}22.           TextColor(LightBlue);23.  24.         write(tabla[i,j]:2);25.       end;26.     writeln;27.                      end;28.  29.   ReadLn;30. end.

Proprietatea elementelor cu albastru este ca indicele liniei este mai mare decat indicele liniei SI este sub diagonala secundara (adica indexul de linie este mai mare decat numarul de linii,

Page 49: Tutorial Pascal

din care scadem indexul coloanei si adunam 1).

Restul sectiunilor si subsectiunilor determinate de diagonale le puteti afla si singuri, modificand programele de mai sus.

Subprograme (proceduri si functii)

Vi s-a intamplat sa aveti nevoie sa faceti un program si sa fie nevoie sa repetati o secventa de cod in mai multe locuri din program ? Probabil ca da, posibil ca nu.Vi s-a intamplat sa aveti nevoie sa va ordonati codul in alt fel decat insiruirea liniilor una dupa alta, sa zicem ... dupa functionalitate ?

Pentru a usura aceste lucruri, Pascal ofera subprogramele: proceduri si functii. Pe scurt, acestea sunt parti de program care pot fi folosite apeland numele lor.

Proceduri

Sa vedem cum arata o structura generala a unei proceduri:Line number On/Off | Expand/Contract | Select all

1. procedure nume_procedura [(lista_parametri)];2.  3. CONST4.   (* declaratii de constante *)5.  6. VAR7.   (* declaratii de variabile *)8.  9. BEGIN10.   (* instructiuni *)11. END;

De remarcat ca, spre deosebire de structura unui program, end-ul de la sfarsit este finalizat cu ; (punct si virgula), nu cu . (punct). Lista de parametri este optionala, motiv pentru care este incadrata intre paranteze drepte. Ce inseamna parametri va fi explicat putin mai tarziu.

Sa vedem un program obisnuit folosind proceduri. Programul original (fara proceduri) ar fi urmatorul:Line number On/Off | Expand/Contract | Select all

1. var vector : array[1..200] of integer;2.     i, n: integer;3. begin4.   Write('Dati N: '); ReadLn(n); {N = numarul de elemente}5.  

Page 50: Tutorial Pascal

6.   i := 1; {*}7.   while (i <= N) do {citim elementele}8.     begin9.       Write('Dati elementul ', i, ': ');10.       ReadLn(vector[i]);11.       i := i + 1;12.     end;13.  14.   i := 1; {*}15.   while (i <= N) do {impartim fiecare element la 2 si

salvam catul}16.     begin17.       vector[i] := vector[i] div 2;18.       i := i + 1;19.     end;20.  21.   Write('Vectorul modificat este : ');22.  23.   i := 1; {*}24.   while (i <= N) do {afisam noile valori din vector}25.     begin26.       Write(vector[i] : 5);27.       i := i + 1;28.     end;29.  30.   ReadLn; {asteptam sa fie apasat Enter}31. end.

Vedeti secventele marcate cu {*} ? Aceeasi instructiune, repetata de 3 ori... Bineinteles, intr-un program mai mare si mai stufos, secventele care se repeta contin mai multe instructiuni ... si probabil se repeta de mai multe ori.

Sa vedem cum rescriem programul folosind o procedura care sa faca acelasi lucru (sa initializeze variabila i cu 1).Line number On/Off | Expand/Contract | Select all

1. var vector : array[1..200] of integer;2.     i, n: integer;3.  4.   procedure Init;5.   begin6.     i := 1;7.   end;8.  9. begin10.   Write('Dati N: '); ReadLn(n); {N = numarul de

elemente}11.  12.   Init; {*}

Page 51: Tutorial Pascal

13.   while (i <= N) do {citim elementele}14.     begin15.       Write('Dati elementul ', i, ': ');16.       ReadLn(vector[i]);17.       i := i + 1;18.     end;19.  20.   Init; {*}21.   while (i <= N) do {impartim fiecare element la 2 si

salvam catul}22.     begin23.       vector[i] := vector[i] div 2;24.       i := i + 1;25.     end;26.  27.   Write('Vectorul modificat este : ');28.  29.   Init; {*}30.   while (i <= N) do {afisam noile valori din vector}31.     begin32.       Write(vector[i] : 5);33.       i := i + 1;34.     end;35.  36.   ReadLn; {asteptam sa fie apasat Enter}37. end.

Probabil ca acum va ganditi "Ce mare branza a rezolvat ? Numarul de linii este acum mai mare !". Da, asa e, dar asa cum am mentionat, acest program este doar un exemplu simplist.

In acest caz, variabila i este o variabila globala. Nu e declarata in niciun subprogram, ci direct in programul principal. Procedura Init o poate folosi fiindca variabila a fost declarata inaintea procedurii (daca erau declarate invers, compilatorul ar fi dat eroare spunand ca variabila folosita in procedura nu poate fi gasita).

Variabilele declarate in interiorul unui subprogram se numesc variabile locale.

Atentie: Variabilele globale si locale pot avea acelasi nume, lucru care poate duce la probleme in program.

Sa vedem un alt program care foloseste o procedura pentru a calcula factorialul unui numar (pentru cei care nu stiu, factorialul unui numar N este produsul lui 1 x 2 x ... x N).Line number On/Off | Expand/Contract | Select all

1. var i, n, f: integer;2.  3.   procedure Fact;4.   begin5.     f := 1;

Page 52: Tutorial Pascal

6.  7.     for i := 1 to n do8.       f := f * i;9.   end;10.  11. begin12.   Write('Dati N: '); ReadLn(n);13.  14.   Fact;15.   Write('Factorial de N este egal cu : ', f);16.  17.   ReadLn; {asteptam sa fie apasat Enter}18. end.

Destul de clar, cred. Sa trecem la ...

Functii

Functiile sunt foarte asemanatoare procedurilor, singura diferenta fiind faptul ca functiile pot intoarce un rezultat.

Sa vedem cum arata o structura generala a unei functii:Line number On/Off | Expand/Contract | Select all

1. function nume_functie [(lista_parametri)] : tip_rezultat;2.  3. CONST4.   (* declaratii de constante *)5.  6. VAR7.   (* declaratii de variabile *)8.  9. BEGIN10.   (* instructiuni *)11. END;

Haideti sa vedem cum ar putea arata un program care calculeaza factorialul unui numar, folosind o functie de data asta:Line number On/Off | Expand/Contract | Select all

1. var i, n, f: integer;2.  3.   function Fact: Longint;4.   var lFact: Longint; {variabila locala}5.   begin

Page 53: Tutorial Pascal

6.     lFact := 1;7.  8.     for i := 1 to n do9.       lFact := lFact * i;10.  11.     Fact := lFact; {am asignat rezultatul in numele

functiei !}12.   end;13.  14. begin15.   Write('Dati N: '); ReadLn(n);16.  17.   F := Fact;18.   Write('Factorial de N este egal cu : ', f);19.  20.   ReadLn; {asteptam sa fie apasat Enter}21. end.

De data asta am asignat variabila F din afara subprogramului, si i-am dat valoarea rezultata din functie. Rezultatul functiei a fost setat asignand valoarea respectiva numelui functiei, in interiorul functiei.

Alta modificare este faptul ca folosim o variabila locala pentru a calcula factorialul. Acest lucru nu este strict necesar, l-am facut doar pentru a exemplifica rolul variabilelor locale.

Parametri

Sa vedem ce sunt parametrii si cum ii folosim in subprograme.

Lista de parametri este scrisa, practic, ca o lista de variabile. Parametrii pot fi scrisi in orice ordine sau pot fi grupati dupa tipul variabilelor.

Parametrii pot fi de doua tipuri, prin modul in care sunt folositi:

parametri prin valoare - acesti parametri pot fi modificati in interiorul subprogramului, dar modificarile nu sunt vizibile in exteriorul subprogramului.

parametri prin adresa - acesti parametri sunt, de fapt, adresele de memorie ale unor variabile deja declarate. Modificarile aduse unor astfel de parametri in interiorul unui subprogram vor fi vizibile in exterior.

Teoria ca teoria, dar hai sa vedem niste exemple Line number On/Off | Expand/Contract | Select all

1. var i, n, f: integer;2.  

Page 54: Tutorial Pascal

3.   function Fact(X: Integer): Longint; {X este un parametru transmis prin valoare}

4.   var lFact: Longint; {variabila locala}5.   begin6.     lFact := 1;7.  8.     for i := 1 to X do9.       lFact := lFact * i;10.  11.     X := -1;12.     Fact := lFact; {am asignat rezultatul in numele

functiei !}13.   end;14.  15. begin16.   Write('Dati N: '); ReadLn(n);17.  18.   F := Fact(N);19.   WriteLn('Factorial de N este egal cu : ', f);20.   WriteLn('Noua valoare a lui N este   : ', n);21.  22.   ReadLn; {asteptam sa fie apasat Enter}23. end.

Bun. Am calculat din nou factorialul, dar, de data aceasta, functia noastra Fact a primit un parametru prin valoare, pe care-l foloseste sa calculeze factorialul. Pe scurt, o data intrati in corpul functiei (care este apelata ca Fact(N), X este egal cu N. Ce vreau sa remarcati este faptul ca, desi am dat o noua valoare lui X in interiorul functiei, aceasta nu este transmisa inapoi lui N, dovada fiind faptul ca noua valoare a lui N (care este afisata) este aceeasi cu cea introdusa de la tastatura.

Din punctul de vedere al functiei si al metodei de lucru, admitand ca valoarea lui N era egala cu 5, puteam apela Fact(5). Numele generic al parametrului ("prin valoare") este dat tocmai din acest motiv: indiferent ca functia este apelata cu o constanta sau o variabila, doar valoarea ei este transmisa.

Sa vedem acelasi cod, singura diferenta fiind ca acum folosim un parametru prin adresa.Line number On/Off | Expand/Contract | Select all

1. var i, n, f: integer;2.  3.   function Fact(var X: Integer): Longint; {X este un

parametru transmis prin adresa}4.   var lFact: Longint; {variabila locala}5.   begin6.     lFact := 1;7.  8.     for i := 1 to X do9.       lFact := lFact * i;10.  

Page 55: Tutorial Pascal

11.     X := -1;12.     Fact := lFact; {am asignat rezultatul in numele

functiei !}13.   end;14.  15. begin16.   Write('Dati N: '); ReadLn(n);17.  18.   F := Fact(N);19.   WriteLn('Factorial de N este egal cu : ', f);20.   WriteLn('Noua valoare a lui N este   : ', n);21.  22.   ReadLn; {asteptam sa fie apasat Enter}23. end.

Faptul ca parametrul este transmis prin adresa este simbolizat de cuvantul var care-l precede. Programul afiseaza noua valoare a lui N, asa cum era de asteptat, egala cu -1, dovada ca variabila N a fost modificata in functie.

Diferenta principala intre parametrii transmisi prin valoare si cei transmisi prin adresa este faptul ca, in cazul celor transmisi prin valoare, variabila trimisa ca parametru este copiata intr-o zona de memorie temporara si trimisa functiei, ca si copie, in timp ce in cazul celor transmisi prin adresa variabila trimisa ajunge in functie neschimbata, ca original. Din acest motiv, transmiterea parametrilor prin adresa poate rapidiza executia programului (totusi, sa nu va asteptati la minuni - vorbim de milisecunde si chiar mai putin).

Atentie: Un subprogram poate avea o lista de parametri micsti: o parte dintre ei sa fie trimisi prin valoare, iar altii prin adresa. Tot ce conteaza este modul de declarare al listei.

De remarcat ca parametrii listati in headerul subprogramului se numesc parametri formali (X este un parametru formal in programul de mai sus), care sunt inlocuiti de parametri efectivi, in momentul apelului subprogramului (N este un parametru efectiv in programul de mai sus).

Atentie: Numarul, tipul si ordinea parametrilor efectivi trebuie sa corespunda cu numarul, tipul si ordinea parametrilor formali !

Vizibilitatea variabilelor

Dupa cum am explicat mai sus, se pot declara variabile in interiorul subprogramelor, chiar si cu nume de variabile care exista deja definite in programul principal. Problema care se ridica este urmatoarea : de unde stie compilatorul (si implicit, programatorul) care variabila va fi folosita in anumite zone ale programului ?

Nu trebuie sa va speriati, este foarte simplu si usor de inteles.

Variabilele globale ale programului sunt vizibile oriunde in program. Daca un subprogram isi

Page 56: Tutorial Pascal

defineste o variabila cu acelasi nume, atunci variabila locala e prioritara in acel subprogram (si in posibilele subprograme ale subprogramului !).

Sa vedem un exemplu.Line number On/Off | Expand/Contract | Select all

1. var i, n, f, lFact: integer;2.  3.   function Fact(X: Integer): Longint; {X este un

parametru, transmis prin valoare}4.   var lFact: Longint; {variabila locala}5.   begin6.     lFact := 1;7.     WriteLn('lFact local  = ', lFact);8.  9.     for i := 1 to X do10.       lFact := lFact * i;11.  12.     X := -1;13.     Fact := lFact; {am asignat rezultatul in numele

functiei !}14.   end;15.  16. begin17.   Write('Dati N: '); ReadLn(n);18.  19.   lFact := 157;20.   WriteLn('lFact global = ', lFact);21.  22.   F := Fact(N);23.   WriteLn('Factorial de N este egal cu : ', f);24.  25.   ReadLn; {asteptam sa fie apasat Enter}26. end.

Acest program va afisa urmatoarele linii (pentru N egal cu 5):Line number On/Off | Expand/Contract | Select all

1. Dati N: 52. lFact global = 1573. lFact local  = 14. Factorial de N este egal cu : 120

Recursivitate

Page 57: Tutorial Pascal

Un lucru important de stiut, legat de subprograme, este ca ele sunt necesare daca vrem sa folosim recursivitate.

Un subprogram este recursiv daca in implementarea lui se apeleaza pe el insusi.

Recursivitatea poate fi un concept destul de greu de inteles, asa ca vom incepe cu un exemplu. Sa vedem cum rescriem functia care calculeaza factorialul, folosind recursivitatea.Line number On/Off | Expand/Contract | Select all

1. function Fact(X: Integer): Longint;2. begin3.   if X > 14.     then Fact := Fact(X - 1) * X5.     else Fact := 16. end;

Dupa se poate vedea, recursivitatea permite si formularea mai eleganta a solutiei.

Sa incercam sa intelegem ce se intampla. Factorial de N (notat si N!) este definit ca o inmultire succesiva a numerelor de la 1 la N (1 x 2 x ... x N). Din asta putem vedea ca N! este egal cu (N-1)! x N. La randul lui, (N-1)! = (N-2)! x (N-1) si asta poate continua, pana cand N este egal cu 1. Daca incercam sa calculam 1! folosind aceeasi relatie (adica 1! = 0! x 1) o sa cam dam gres, fiindca 0, inmultit cu orice numar, da 0.

Pe scurt, daca avem un caz initial caruia ii stim rezultatul, iar restul cazurilor se pot rezolva in functie de cazul initial, problema poate fi rezolvata recursiv. Cazul initial, pe functia de mai sus, este cazul in care X nu este mai mare decat 1 (adica este mai mic sau egal !), acest caz avand rezultatul 1. Pentru orice alta valoare pozitiva a lui X, rezolvarea se face in functie de X-1, pana cand X ajunge in cazul initial.

Ca urmare, aceste doua relatii de mai sus:

N! = (N-1)! x N 1! = 1

sunt tot ce ne trebuie pentru a ne defini functia recursiva de calculare a factorialului.

Sa vedem ce se intampla, pas cu pas, pentru N egal cu 3.Line number On/Off | Expand/Contract | Select all

1. Fact(3)2. X = 3 -> apelam Fact(2) si inmultim cu 33. X = 2 -> apelam Fact(1) si inmultim cu 24. X = 1 -> 1, se termina functia, revenim in apelul

precedent5. Fact = 1, care inmultit cu 2 este egal cu 2, revenim in

apelul precedent

Page 58: Tutorial Pascal

6. Fact = 2, care inmultit cu 3 este egal cu 6, se termina functia si revenim in locul unde a fost initial apelata functia.

Deci, daca avem o problema care poate fi exprimata prin subprobleme ale ei si putem gasi o conditie de terminare a apelurilor recursive (in acest caz, X = 1), problema poate fi rezolvata printr-un subprogram recursiv.

Atentie: Apelurile recursive consuma relativ multa memorie. Daca o problema poate fi rezolvata iterativ (fara apeluri recursive), e de preferat (in general) ca problema sa fie rezolvata iterativ. O lista prea lunga de apeluri recursive poate genera "stack overflow" si bloca programul / calculatorul.

Pentru edificare, atasez acelasi program care calculeaza factorialul, modificat pentru a afisa ce se intampla. Sper sa va fie de ajutor, impreuna cu explicatiile de mai sus.

Codul sursa al programului:Line number On/Off | Expand/Contract | Select all

1. uses crt;2.  3. const lin = 9;4.       line =

'-----------------------------------------------------------------';

5.       Wait = 1000;6.  7. var i, n, f, lFact, test: longint;8.  9.   function Fact(X: Integer): Longint; {X este un

parametru, transmis prin valoare}10.   begin11.     if X > 112.       then13.         begin14.           WriteLn('Fact(', X, ') = Fact(', X - 1 ,')

* ', X);15.           WriteLn(line);16.           Delay(Wait);17.  18.           Fact := Fact(X - 1) * X;19.           Delay(Wait);20.  21.           TextColor(LightGreen);22.           if Test > 0 then23.             Test := Test * X;24.           GotoXY(40, (N - X) * 2 + lin);25.           Write('Fact(', X,') = ', Test);26.         end

Page 59: Tutorial Pascal

27.       else28.         begin29.           TextColor(LightRed);30.           WriteLn('X = 1                            

' +31.                   'Fact(1) = 1, caz initial !');32.           TextColor(LightGray);33.           WriteLn(line);34.           Delay(Wait);35.           WriteLn('Functia s-a terminat, revenim din

apel ^^^');36.           Delay(Wait);37.           Fact := 1;38.           Test := 1;39.         end;40.   end;41.  42. begin43.   test := 0;44.   repeat {verificam daca 1 <= N <= 6}45.     ClrScr;46.     Write('Dati N (maxim 6): '); ReadLn(n);47.   until (N > 0) and (N < 7);48.   ClrScr;49.  50.   TextColor(LightRed);51.   GotoXY(Length(line) div 2 - 16 ,2);52.   WriteLn('Calculul factorialului - recursiv');53.   WriteLn(line);54.   WriteLn;55.   TextColor(LightGray);56.   WriteLn('Se apeleaza Fact(', N,') ...');57.   Delay(Wait);58.  59.   TextColor(lightGray);60.   GotoXY(1, lin);61.   F := Fact(N);62.  63.   Delay(Wait);64.   GotoXY(1, N * 2 + lin + 3);65.   TextColor(LightGray);66.  67.   Write('Fact(', N, ') este egal cu : ');68.   TextColor(LightGreen);69.   WriteLn(f);70.   TextColor(LightGray);71.   Write('... apasa orice tasta pentru a termina

programul ...');72.  73.   While Keypressed Do

Page 60: Tutorial Pascal

74.     Readkey; {daca s-a apasat o tasta in timp ce programul rula,

75.               va astepta totusi apasarea urmatoarei taste}

76.   ReadKey;77. end.

Lucrul cu fisiere

Toate programele facute pana acum acceptau, ca sursa de date, tastatura, iar ca iesire, monitorul. Cu toate acestea, Pascal permite folosirea fisierelor.

Sunt convins ca v-ati intrebat, cel putin o data, de ce jocurile se instaleaza cu o multime de fisiere aditionale, in afara de executabilul propriu-zis. Raspunsul e simplu: resursele respectivului joc se afla in acele fisiere (harti, imagini, sunete, etc). Executabilul jocului citeste si scrie acele fisiere in functie de necesitati (scrie, de exemplu, in fisierul de high-scores).

Sa vedem cum putem folosi si noi fisiere, in Pascal.

Pentru inceput trebuie sa stiti ca Pascal ofera trei tipuri de fisiere:

fisiere text fisiere cu tip fisiere fara tip

Modul de lucru (accesare, citire, scriere) difera, cel putin partial, la fiecare tip de fisier.

Sa incepem cu inceputul.

Fisiere text in Pascal (text files)

Sa presupunem ca vrem sa citim doua numere de pe prima linie a unui fisier text, si apoi matricea cu respectivul numar de linii si coloane, dintr-un fisier text (creat cu notepad sau orice alternativa a acestuia). Fisierul ar putea avea urmatorul continut:Line number On/Off | Expand/Contract | Select all

1. 2 52. 1 2 3 4 53. 6 7 8 9 10

Sa vedem un program care citeste acest fisier si afiseaza datele citite pe monitor.Line number On/Off | Expand/Contract | Select all

Page 61: Tutorial Pascal

1. uses crt;2. var fis: Text;3.     lins, cols, i, j: integer;4.     matrice: array[1 .. 20, 1 .. 20] of integer;5. begin6.   ClrScr;7.   Assign(fis, 'fisier.txt');8.   Reset(fis);9.  10.   ReadLn(fis, lins, cols);11.   for i := 1 to lins do12.     begin13.       for j := 1 to cols do14.         Read(fis, matrice[i, j]);15.       ReadLn(fis);16.     end;17.   Close(fis);18.  19.   WriteLn('Matricea citita din fisier este:'#13#10);20.   for i := 1 to lins do                    {#13#10 =

Enter}21.     begin                                  {#13    =

Carriage Return}22.       for j := 1 to cols do                {#10    =

Line Feed}23.         write(matrice[i,j] : 3);24.       writeln;25.     end;26.   Write(#13#10'Apasati orice tasta pentru a

iesi ...'#8#8#8#8);27.   ReadKey;                                        

{#8 = BackSpace}28. end.

Declaratia unui fisier text se face identic cu declararea unei variabile obisnuite, iar tipul variabilei este Text. Fisier Text . Restul variabilelor nu are rost sa le explic, le puteti intelege daca ati parcurs tutorialele precedente.

Sa vedem ce proceduri si functii avem la dispozitie pentru lucrul cu fisiere text.Proceduri si functii folosite la lucrul cu fisiere textNume DescriereAssign Asigneaza un fisier (definit prin calea catre el) catre o variabila de tip fisier. Toate

operatiile ulterioare care folosesc acel fisier vor utiliza variabila acestuia. Asocierea dintre variabila si respectivul fisier va exista pana la urmatoarea asignare a variabilei catre alt fisier.

Calea catre fisier trebuie sa fie o cale definita prin 0 sau mai multe directoare, separate prin semnul backslash \, urmate de numele complet al fisierului. Daca aceasta cale este inceputa direct cu semnul backslash, atunci este folosita ca si

Page 62: Tutorial Pascal

Proceduri si functii folosite la lucrul cu fisiere textcum ar fi inceput direct in radacina ( C:\Folder\fisier.txt este identic cu \Folder\fisier.txt, daca programul este rulat dintr-un director de pe C:. Daca este dat doar numele fisierului, atunci fisierul este cautat in directorul curent (cel de unde este rulat programul).

Numele fisierului trebuie sa se conformeze standardului DOS de denumire a fisierelor, adica 8.3 (nume de maxim 8 caractere, fara spatii, si extensie (optionala) de maxim 3 caractere.

Un caz special este cel in care calea catre fisier este sirul vid (adica '' - doua apostroafe, unul dupa celalalt). In acest caz, variabila de fisier este asignata intrarii / iesirii standard. Dupa o asignare a variabilei catre sirul vid, folosirea procedurii Reset va asocia variabila catre intrarea standard, iar folosirea procedurii ReWrite va asocia aceasta variabila cu iesirea standard.

Restrictie:

procedura Assign nu poate fi folosita pe un fisier deja deschis.

Reset

Deschide un fisier existent pentru citire. Daca fisierul nu exista, aceasta procedura va genera o eroare.

Dupa ce fisierul a fost deschis, pozitia in fisier (file pointer-ul) este setata la inceputul acestuia (de acolo poate incepe citirea).

Daca variabila de fisier a fost asignata unui sir vid, dupa apelul acestei proceduri, variabila de fisier se va referi la intrarea standard (tastatura, de obicei).

Rewrite

Creaza un fisier nou si il deschide pentru scriere. Daca fisierul exista, atunci el este sters si recreat (gol). Daca variabila de fisier este asignata unui fisier deschis, acesta va inchis, sters, recreat si redeschis.

Dupa ce fisierul a fost deschis, pozitia in fisier (file pointer) este setata la inceputul acestuia.

Daca variabila de fisier a fost asignata unui sir vid, dupa apelul acestei proceduri, variabila de fisier se va referi la iesirea standard (monitorul, de obicei).

Append

Deschide fisierul ales (prin folosirea procedurii Assign) pentru scriere. Daca fisierul nu exista, atunci aceasta procedura va genera o eroare. Daca fisierul este deja deschis, atunci el este inchis si redeschis. Pozitia in fisier (file pointer) este setata la sfarsitul acestuia.

Daca variabila de fisier a fost asignata unui sir vid, dupa apelul acestei proceduri, variabila de fisier se va referi la iesirea standard (monitorul, de obicei).

Close

Inchide fisierul desemnat de variabila de fisier, daca respectivul fisier a fost deschis folosind una din procedurile Reset, Rewrite sau Append.

Fisierul asociat cu variabila de fisier este adus la zi cu toate modificarile operate asupra lui, inainte de a fi inchis.

Page 63: Tutorial Pascal

Proceduri si functii folosite la lucrul cu fisiere text

EoLN

Aceasta functie (acronim de la End of LiNe) returneaza True daca pozitia in fisier (file pointer-ul) este la sfarsitul unei linii (marcaj #13#10) sau la sfarsitul fisierului. Returneaza False in caz contrar.

Functia poate fi apelata fara parametru sau cu un parametru de tip Text (fisier text). Daca este apelata fara parametru, atunci fisierul este considerat a fi fisierul standard de intrare (tastatura).

SeekEoLN

Verifica daca mai sunt date pe linia curenta, de la pozitia curenta pana la sfarsitul liniei. Daca nu mai sunt date pana la sfarsitul liniei (doar spatii sau tab-uri), va returna True, returnand False in caz contrar.

Restrictii:

Fisierul trebuie sa fie deschis. Poate fi folosita doar cu fisiere text.

EoF

Aceasta functie (acronim de la End of File) returneaza True daca pozitia in fisier (file pointer) este la sfarsitul fisierului. Returneaza False in caz contrar.

Functia poate fi apelata fara parametru sau cu un parametru de tip Text (fisier text). Daca este apelata fara parametru, atunci fisierul este considerat a fi fisierul standard de intrare (tastatura).

SeekEoF

Verifica daca mai sunt date in fisier, de la pozitia curent pana la sfarsitul fisierului. Daca nu mai sunt date pana la sfarsitul fisierului (doar spatii sau tab-uri), va returna True, returnand False in caz contrar.

Restrictii:

Fisierul trebuie sa fie deschis. Poate fi folosita doar cu fisiere text.

Daca ati trecut prin explicatiile date in tabelul de mai sus, ar trebui sa stiti destul de multe pentru a folosi un fisier text fara probleme.

Sa vedem un mic program care citeste prima linie dintr-un fisier text si o adauga, inversata, la sfarsitul fisierului.Line number On/Off | Expand/Contract | Select all

1. uses crt;2. var fis: Text;3.     linie: String;4.     i: integer;5.     c: Char;6. begin7.   ClrScr;8.   Assign(fis, 'fisier.txt');9.   Reset(fis);10.  

Page 64: Tutorial Pascal

11.   ReadLn(fis, linie);12.   WriteLn('Prima linie din fisier este urmatoarea:');13.   WriteLn(linie+#13#10);14.  15.   WriteLn('Vom adauga linia, inversata, in fisier, la

sfarsitul acestuia.');16.   WriteLn;17.  18.   for i := 1 to Length(linie) div 2 do {bucla aceasta

inverseaza sirul de caractere}19.     begin20.       c := linie[i];21.       linie[i] := linie[Length(linie) - i + 1];22.       linie[Length(linie) - i + 1] := c;23.     end;24.  25.   Append(fis);26.   WriteLn(fis, #13#10 + linie);27.   Close(fis);28.   Write(#13#10'S-a facut ! Apasati orice tasta pentru

a iesi ...');29.   ReadKey;30. end.

Ultimul program care va folosi fisiere text in acest tutorial va citi date dintr-un fisier si le va salva in alt fisier.Line number On/Off | Expand/Contract | Select all

1. uses crt;2. var fis: Text;3.     linie: String;4.     i: integer;5.     c: Char;6. begin7.   ClrScr;8.   Assign(fis, 'fisier.in');9.   Reset(fis);10.  11.   ReadLn(fis, linie);12.   Close(fis);13.  14.   WriteLn('Prima linie din fisier este urmatoarea:');15.   WriteLn(linie+#13#10);16.  17.   Assign(fis, 'fisier.out');18.   Rewrite(fis);19.   WriteLn(fis, linie);20.   Close(fis);21.  

Page 65: Tutorial Pascal

22.   Write(#13#10'S-a facut ! Apasati orice tasta pentru a iesi ...');

23.   ReadKey;24. end.

Atentie: presupun ca este evident ca toate fisierele de intrare folosite in aceste programe vor trebui create manual inainte de pornirea programului.

Fisiere cu tip in Pascal (typed files)

Acum, dupa ce-ati aflat ce-i cu fisierele text in Pascal, o sa-mi spuneti ca jocurile pe care le mentionam mai sus nu folosesc fisiere text, sau foarte rar... si nu va pot contrazice. Asa este.

Fisierele text, desi permit salvarea a orice date in ele, sunt limitate de faptul ca nu ne permit citirea unui anumit caracter, decat daca am citit toate caracterele dinaintea lui. Imaginati-va un fisier text de cativa megabytes (mega-octeti, daca vreti ), din care vrem sa citim caracterul cu indicele 1.123.194 ... va trebui sa citim un milion de caractere inainte de a putea citi caracterul care ne intereseaza.

Aici intra in joc fisierele cu tip. Ele permit citirea secventiala a datelor (ca si fisierele text), dar si citirea aleatorie (random) din fisier. Spre deosebire de fisierele text, de unde puteam citi doar siruri de caractere (nu va lasati pacaliti de faptul ca ReadLn citeste si numere ... le converteste intern din string in valoare numerica !), din fisiere fara tip se pot citi doar valori de acelasi tip ca si fisierul in sine.

Fisierele cu tip sunt, practic, o varianta a vectorilor (array, if you please). Pot stoca date de un singur tip, cel setat in declararea variabilei de fisier, dar sunt limitate de spatiul disponibil pe hard-disk (si, in versiunile vechi de Pascal, cum ar fi Borland Pascal, de o marime maxima de 2 GB / fisier - tineti totusi cont ca in 1992, cand a aparut Borland Pascal 7.0 nu sunt sigur daca existau, inca, hard-disk-uri atat de mari !).

Haideti sa vedem un mic program care scrie un set de date aleatorii intr-un fisier cu tip (tip integer, pentru inceput), iar apoi le reciteste si afiseaza a 20-a valoare din fisier.Line number On/Off | Expand/Contract | Select all

1. uses crt;2. var fis: file of integer;3.     i, val: integer;4. begin5.   ClrScr;6.   Randomize;7.   Assign(fis, 'fisier.bin');8.   Rewrite(fis);9.  10.   for i := 1 to 100 do11.     begin12.       val := Random(20000) + 1; {valori intre 1 si

20000}

Page 66: Tutorial Pascal

13.       Write(fis, val);14.     end;15.   Close(fis);16.  17.   Assign(fis, 'fisier.bin');18.   ReSet(fis);19.   Seek(fis, 19); {indexul incepe de la 0}20.  21.   Read(fis, i);22.   WriteLn('A 20-a valoare din fisier este : ',i);23.  24.   Close(fis);25.  26.   Write(#13#10'S-a facut ! Apasati orice tasta pentru

a iesi ...');27.   ReadKey;28. end.

Este de remarcat faptul ca fiecare element din fisier ocupa 2 bytes, in acest caz (integer).

Lista de proceduri si functii care pot fi folosite la manipularea fisierelor cu tip sunt date in tabelul de mai jos. Explicatiile date in acest tabel sunt doar complementare celor date in tabelul de proceduri si functii dat pentru folosirea cu fisiere text.Proceduri si functii folosite la lucrul cu fisiere cu tipNume DescriereAssign Identic cu fisierele text.

Reset

Deschide un fisier existent (pentru citire / scriere). Daca fisierul nu exista, aceasta procedura va genera o eroare.

Dupa ce fisierul a fost deschis, pozitia in fisier (file pointer-ul) este setata la inceputul acestuia.

Daca variabila de fisier a fost asignata unui sir vid, dupa apelul acestei proceduri, variabila de fisier se va referi la intrarea standard (tastatura, de obicei).

Rewrite

Creaza un fisier nou si il deschide (pentru scriere / citire). Daca fisierul exista, atunci el este sters si recreat (gol). Daca variabila de fisier este asignata unui fisier deschis, acesta va inchis, sters, recreat si redeschis.

Dupa ce fisierul a fost deschis, pozitia in fisier (file pointer) este setata la inceputul acestuia.

Daca variabila de fisier a fost asignata unui sir vid, dupa apelul acestei proceduri, variabila de fisier se va referi la iesirea standard (monitorul, de obicei).

Close

Inchide fisierul desemnat de variabila de fisier, daca respectivul fisier a fost deschis folosind una din procedurile Reset sau Rewrite.

Fisierul asociat cu variabila de fisier este adus la zi cu toate modificarile operate asupra lui, inainte de a fi inchis.

FileSize Returneaza numarul de componente din fisierul desemna de variabila de fisier.

Page 67: Tutorial Pascal

Proceduri si functii folosite la lucrul cu fisiere cu tipMarimea actuala a fisierului poate fi aflata inmultind rezultatul acestei functii cu numarul de bytes folositi de fiecare componenta.

Restrictii:

Fisierul trebuie sa fie deschis. Nu poate fi folosita cu fisiere text.

FilePos

Returneaza pozitia in fisier (file pointer-ul).

Daca pozitia este chiar la inceputul fisierului, atunci aceasta functie returneaza 0. Daca pozitia este la sfarsitul fisierului, atunci rezultatul lui FilePos este egal cu cel al functie FileSize, prezentata mai sus.

Restrictii:

Fisierul trebuie sa fie deschis. Nu poate fi folosita cu fisiere text.

Seek

Muta pozitia in fisier (file pointer) la cea specificata. Urmatoarea citire sau scriere se face din acel loc.

Numarul primei componente din fisier este 0. Noua pozitie care poate fi specificata este de tip Longint, deci nu poate merge mai departe de 2 GB. Pentru a scrie la sfarsitul fisierului (dupa ultima componenta) se poate folosi cu impreuna cu rezultatul functiei FileSize.

Daca pozitia este chiar la inceputul fisierului, atunci aceasta functie returneaza 0. Daca pozitia este la sfarsitul fisierului, atunci rezultatul lui FilePos este egal cu cel al functie FileSize, prezentata mai sus.

Restrictii:

Fisierul trebuie sa fie deschis. Nu poate fi folosita cu fisiere text.

Truncate

Trunchiaza fisierul de la pozitia curenta in fisier (file pointer). Toate componentele de dupa pozitia actuala in fisier sunt sterse.

Restrictii:

Fisierul trebuie sa fie deschis. Nu poate fi folosita cu fisiere text.

Niciodata nu mi-a placut restrictia care spunea ca aceasta procedura / functie nu poate fi folosita cu fisiere text, asa ca am cautat o solutie. Solutia evidenta este sa folositi un fisier cu

Page 68: Tutorial Pascal

componente de tip Char (practic, text), putand astfel folosi si functii gen FileSize, FilePos, Seek, Truncate. Totusi, probabil ca ati vrea sa aveti grija la sfarsiturile de linie / fisier

Fisiere fara tip in Pascal (untyped files)

Fisierele fara tip pot fi privite ca niste fisier cu tip byte, cu diferenta ca datele din aceste fisiere nu pot fi citite/scrise cu procedurile obisnuite (Read, Write), folosind BlockRead/BlockWrite, pentru transferuri la viteza mare.

Sa vedem ce s-a modificat si ce s-a adaugat, din punct de vedere al instructiunilor care pot fi folosite.Proceduri si functii folosite la lucrul cu fisiere cu tipNume DescriereAssign Identic cu fisierele cu tip.

Reset

In cazul fisierelor fara tip, aceasta procedura accepta si un parametru de tip Word, care specifica numarul de bytes avut de o componenta din fisier (RecSize). In mod implicit, RecSize este egal cu 128. Este preferabil sa il setati pe 1, avand astfel control absolut asupra citirilor / scrierilor facute in fisier.

Formatului apelului acestei proceduri este urmatorul:Line number On/Off | Expand/Contract | Select all

1. Reset(var F: File[; RecSize: Word]);

Rewrite

In cazul fisierelor fara tip, aceasta procedura accepta si un parametru de tip Word, care specifica numarul de bytes avut de o componenta din fisier (RecSize). In mod implicit, RecSize este egal cu 128. Este preferabil sa il setati pe 1, avand astfel control absolut asupra citirilor / scrierilor facute in fisier.

Formatului apelului acestei proceduri este urmatorul:Line number On/Off | Expand/Contract | Select all

1. Rewrite(var F: File[; RecSize: Word]);

Close Identic cu fisierele cu tip.FileSize Identic cu fisierele cu tip.FilePos Identic cu fisierele cu tip.Seek Identic cu fisierele cu tip.Truncate Identic cu fisierele cu tip.BlockRead Citeste din fisierul selectat un numar specificat de bytes, intr-o variabila

declarata de utilizator.

Formatul apelului este urmatorul:Line number On/Off | Expand/Contract | Select all

1. BlockRead(var F: File; var Buffer; Count: Word;

Page 69: Tutorial Pascal

Proceduri si functii folosite la lucrul cu fisiere cu tip

[;var Result: Word]);

F este un fisier fara tip, Buffer poate fi orice variabila, Count este un numar intreg, iar Result este o variabila intreaga.

Aceasta functie citeste un numar de Count (sau mai putin) componente (marimea unei componente este specificata de Reset si Rewrite) din fisierul F in memorie, in variabila Buffer. Numarul de componente citite este returnat in variabila Result (daca este folosita). Daca variabila Result nu este folosita, o eroare I/O este generata in cazul in care numarul de componente citite este diferit de numarul specificat in apel (Count). Daca Result este egala cu Count, atunci operatia a avut efectul dorit.

Numarul de bytes cititi este, in cazul optim, Count * RecSize (RecSize este 128 de bytes, daca nu este specificat altfel). Daca numarul Count * RecSize este mai mare decat 65535 (64 KB), se va genera o eroare.

Pozitia in fisier este mutata la sfarsitul zonei citite, ca efect al instructiunii BlockRead.

Restrictii:

Fisierul trebuie sa fie deschis. Nu poate fi folosita decat cu fisiere fara tip.

BlockWrite Scrie in fisierul selectat un numar specificat de bytes, dintr-o variabila declarata de utilizator.

Formatul apelului este urmatorul:Line number On/Off | Expand/Contract | Select all

1. BlockWrite(var F: File; var Buffer; Count: Word; [;var Result: Word]);

F este un fisier fara tip, Buffer poate fi orice variabila, Count este un numar intreg, iar Result este o variabila intreaga.

Aceasta functie scrie un numar de Count (sau mai putin) componente (marimea unei componente este specificata de Reset si Rewrite) in fisierul F din memorie, din variabila Buffer. Numarul de componente scrise este returnat in variabila Result (daca este folosita). Daca variabila Result nu este folosita, o eroare I/O este generata in cazul in care numarul de componente scrise este diferit de numarul specificat in apel (Count). Daca Result este egala cu Count, atunci operatia a avut efectul dorit.

Numarul de bytes scrisi este, in cazul optim, Count * RecSize (RecSize este 128

Page 70: Tutorial Pascal

Proceduri si functii folosite la lucrul cu fisiere cu tipde bytes, daca nu este specificat altfel). Daca numarul Count * RecSize este mai mare decat 65535 (64 KB), se va genera o eroare.

Pozitia in fisier este mutata la sfarsitul zonei scrise, ca efect al instructiunii BlockWrite.

Restrictii:

Fisierul trebuie sa fie deschis. Nu poate fi folosita decat cu fisiere fara tip.

In continuare, un exemplu de program care copiaza un fisier (fara niciun fel de verificari).Line number On/Off | Expand/Contract | Select all

1. uses crt;2. var src, dest: file;3.     buffer: array[1 .. 32768] of byte; {buffer de 32 KB}4.     cale_src, cale_dest: string;5.     read_bytes: word;6. begin7.   ClrScr;8.   Write('Dati calea catre fisierul sursa: ');9.   ReadLn(cale_src);10.  11.   Write('Dati calea destinatie: ');12.   ReadLn(cale_dest);13.  14.   Assign(src, cale_src);15.   Reset(src, 1);16.  17.   Assign(dest, cale_dest);18.   Rewrite(dest, 1);19.  20.   While not Eof(src) Do {atat timp cat nu am ajuns la

sfarsitul fisierului ...}21.     Begin22.       BlockRead(src, buffer, 32768, read_bytes);

{vrem sa citim 32 KB, dar verificam cat am citit}23.       BlockWrite(dest, buffer, read_bytes); {cat am

citit, atat scriem}24.     End;25.   Close(src);26.   Close(dest);27.   WriteLn(#13#10'Fisierul a fost copiat !');28.   ReadKey;29. end.

Page 71: Tutorial Pascal

Daca fisierul care se doreste copiat nu exista, sau daca fisierul destinatie nu are extensie (lol ) sau intervine orice alta problema, programul va returna erori. Nu este dat decat pentru a

exemplifica un mod de lucru cu fisierele fara tip.