Guida al Pascal

2001-09-17

When I was 16, I used to write articles under the nicknames Esorcista and XpTerminator.

The following is a tutorial on the Pascal programming language that got published on the 4th issue of OndaQuadra, an Italian e-zine.

+-------------------------------------------------------------------------------+ | ONDAQUADRA MAGAZINE ~ [C0DiNG] #03 - 17/09/2001 | | iNTR0DUZi0NE ALLA PR0GRAMMAZi0NE (PASCAL) [Xp Terminator] 0x10/0x29 | +-------------------------------------------------------------------------------+ +--+-+-+-++--++-+-+++--++-+-+-+-++-+--+-+-++--+-+-+-+-+-+-+-+-++-+-+--+-++--+ GUIDA AL PASCAL by Xp Terminator +--+-+-+-++--++-+-+++--++-+-+-+-++-+--+-+-++--+-+-+-+-+-+-+-+-++-+-+--+-++--+ oOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoO Ne io ne lo staff di oq si assume responsabilità su ciò che farete con le informazioni di questo tutorial, anche se credo che non si possa fare nulla di male... oOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoOoO Premetto che con questa guida non si diventerà di certo guro della programmazione ma è una buona introduzione ai concetti principali della programmazione, se poi si vuole passare a linguaggi più complicati. Ho scelto come linguaggio il pascal, poichè è semplice, ed in rete si può trovare veramente tanto materiale su di esso. Il pascal e` un linguaggio di programmazione straordinario, ed a differenza di come la pensano in molti e` anche molto potente, grazie anche alla possibilita` di utilizzare file object compilati con altri linguaggi, e di inserire frammenti di codice assembler, un linguaggio a bassissimo livello con il quale e` possibile fare qualunque cosa. Magari in futuro scrivero` una guida anche per l`assembler. Il pascal e` un linguaggio ad alto livello, cioe` e` ben lontano dal linguaggio macchina. I linguaggi di programmazione possono essere divisi in due categorie, quelli che vengono eseguiti direttamente (come per esempio il basic, o i file batch del dos), e quelli che per essere eseguiti hanno prima bisogno di essere compilati (tramite la compilazione viene creato un file .obj) e linkati (con il link viene creato il file eseguibile). Il pascal fa parte di questi ultimi, ed e` un pregio, perche` i file che vengono eseguiti direttamente sono molto + lenti e gli errori non vengono segnalati, ma si scoprono man mano che si esegue il programma. Esistono vari compilatori per il pascal, e tra di loro vi sono poche differenze. Io consiglierei il Borland Pascal 7.0, l'ultima versione rilasciata, prima dell`avvento del Delphi, il "pascal visuale" un po` come il visual basic, che e` il basic visuale. Io sinceramente consiglierei il Delphi x chi ha intenzione di programmare sotto so windows con interfaccia grafica; con il pascal, si possono creare non solo applicazioni che girano sotto dos o sotto windows in interfaccia in modalita` testo, ma addirittura si possono creare sistemi operativi! come per esempio, Menuet, scritto con 25000 righe in turbo pascal, + quasi 2000 scritte in Assembler. Il borland pascal 7.0 e` downloadabile dall`url http://www.computertemple.com nella sezione utility. Ecco un semplicissimo programma in Pascal: program prova; {questo e` un commento!} uses crt; var stringa : string; begin stringa := 'Hello world!!!'; writeln(stringa); repeat until keypressed; end. provate a compilarlo ed eseguirlo, otterrete come output: Hello world!!! Ora esaminiamo questo piccolo frammento di codice sorgente: program prova; ---> questa riga non fa altro che dichiarare il nome del programma che scriviamo; questa riga e` omettibile; il nome del programma non puo` contenere spazi, io consiglierei di sostituirli con gli underline _ . {questo e` un commento} ---> Servono commenti? :))) spero di no, cmq tra parentesi graffe possono essere inseriti i commenti; cio` e` molto utile quando il programma diventera` + complesso, e dovremo rivederlo, cosi` potremo commentare a cosa servira` una riga uses crt; ---> il pascal come qualunque altro linguaggio di programmazione permette di inserire librerie nel proprio programma. Le librerie specificamente in pascal sono chiamate "unit". Queste sono molto utili, per diminuire il codice sorgente del programma; infatti, procedure e funzioni (spieghero` dopo cosa sono + approfonditamente) possono essere scritte in unit; queste quando vengono compilate, creano un file con estensione .tpu , quindi poi bastera` inserire nel proprio programma "uses libreria,libreria2,nlibrerie;" (ricordate che il file libreria si dovra` trovare nella stessa directory del file sorgente, oppure nelle directory tpu del nostro compilatore pascal). Spesso le librerie vengono utilizzate a scopo commerciale, infatti vengono dati gratuitamente i file .tpu (dai quali non si puo` vedere il codice sorgente della unit), e i file sorgenti ,invece, vengono dati solo in cambio di soldi. (In verita` dalle tpu si puo` risalire ai codici sorgenti delle librerie in un modo non molto legale detto Reverse engineering :) ). Con questa riga non abbiamo fatto altro quindi che includere la libreria "crt" nel nostro programma. Questa libreria e` insieme a quella "dos", la + utilizzata, per l`utilita` delle procedure incluse. var striga : string; ---> leggi + avanti... begin ---> con il comando begin si dichiara l`inizio del programma, di un ciclo, di una procedura o di una funzione. In questo caso abbiamo dichiarato l`inizio del programma vero e proprio. stringa := 'Hello world!!!'; ---> leggi + avanti... writeln(stringa); ---> con il comando writeln viene stampato a video un testo, od una variabile come in questo caso. Il testo viene stampato sul punto attuale del cursore. repeat until keypressed; ---> Questo e` un ciclo, e la sua sintassi e`: repeat comando1 comando2 ... until condizione; cioe` vengono ripetuti i comandi finche` non avviene la condizione. In questo caso come vedete viene ripetuto " " finche` non viene premuto un tasto. Cioe` non avviene un bel niente finche` non viene premuto un tasto. Altri cicli li vedremo + avanti... end. ---> End e` l`equivalente dell`opposto di begin, infatti esso dichiara la fine di una procedure, di un ciclo, di una funzione o del programma vero e proprio. In questo caso dichiara la fine del programma essendo seguito da un punto . Quando ,invece, dichiara la fine di un`altra delle ipotesi suddette viene seguito da una virgola, . Come avete notato alla fine di ogni riga e` obbligatorio inserire un ";", se no viene considerato come un errore. Le uniche eccezioni sono il begin, i commenti, e l`end finale, che come avete visto e` seguito da punto. Inoltre, avrete sicuramente notato che il codice dopo il begin e spostato con una tabulazione a destra. Questo non e` obbligatorio ma e` molto utile per rendere il programma facilmente "leggibile". Come premesso ora parlero` approfonditamente delle variabili, della loro funzione e dichiarazione. Le variabili non sono altro che dei "cassetti" infatti, quando dichiariamo una variabile non facciamo altro che assegnare ad una parte della nostra memoria ram il compito di contenere un valore. Le variabili vengono dichiarate con questa sintassi: var nomevariabile : tipovariabile; Il nome della variabile puo` essere qualunque basta che non sia una parola chiave. Le parole chiave variano da compilatore a compilatore. I tipi di variabili possono essere del testo : "string", un singolo carattere della tabella ASCII : "char", booleano cioe` con valori true o false "boolean", od un numero. I tipi di variabili numero sono molti, ecco i maggiori: "byte" : valori da 0 a 255 "integer" : valori da -32768 a 32767 "real" : valori in virgola mobile I valori delle variabili devono essere dichiarati dopo il begin, con questa sintassi: nomevariabile := valore; Quando la variabile e` numerica la sintassi e` come in questo esempio: numero:=6378; mentre quando si tratta di un testo o di un carattere: stringa:='Hello world!!!'; carattere:='d'; Le variabili sono utili per ottenere degli input da colui che esegue il programma, vedete per esempio questo codice: uses crt; var input1,input2 : string; input3 : byte; begin clrscr; writeln; write('Qual e'' il tuo nome? '); readln(input1); write('Qual e'' il tuo cognome? '); readln(input2); write('Quanti anni hai?'); readln(input3); writeln; writeln(input1,' ',input2,' ha ', input3, ' anni.'); repeat until keypressed; end. eseguendo questo programma otterrete: Qual e' il tuo nome? Xp Qual e' il tuo cognome? Terminator Quanti anni hai? 16 Xp Terminator ha 16 anni. Analizziamolo: le righe fino al begin le abbiamo tutte gia` visto precedentemente. clrscr; ---> questa procedura si trova nella libreria crt, e non fa altro che fare pagina pulita. writeln; ---> come visto in precedenza writeln serve per stampare a video qualcosa, in questo caso lasciamo solo una riga vuota. write('Qual e'' il tuo nome?'); ---> write ha lo stesso utilizzo di writeln, ma al termine della scrittura a video non va a capo. Come avete visto inoltre per far visualizzare un apice ' bisogna digitarlo due volte, se no sarebbe un errore. Cio` vale anche per writeln. readln(input1); ---> readln e` l`opposto di writeln, infatti a posto di inviare un output alla periferica standard (video), riceve un input dalla periferica standard (tastiera). In effetti, questa riga non fa altro che aspettare che l`utente dgt qualcosa, e poi assegna cio` che e` stato digitato alla variabile. write('Qual e'' il tuo cognome?');---\ readln(input2); ----------------\ write('Quanti anni hai?'); -----| tutti questi comandi sono stati gia` visti readln(input3); ----------------/ writeln; -------------------------/ writeln(input1,' ',input2,' ha ', input3, ' anni.'); ---> Con questa riga scriviamo le variabili ottenute + uno spazio tra di loro e "ha" e "anni.", in modo da ottenere: "Nome Cognome ha num_anni anni." repeat until keypressed; ---> gia` visti end. ----------------/\ Tramite la spiegazione e gli esempi spero di aver chiarito cosa sia una variabile, come dichiararla, come assegnargli un valore. Spesso quando si scrive un programma si incontra il problema di dover scrivere + volte una stessa serie di comandi; a questo punto vengono in aiuto le procedure. Infatti queste non sono nient`altro che una serie di comandi che possono essere chiamati con una sola riga. Ecco un esempio: uses crt; var ancora : string; label prova2; procedure prova1; var addendo1, addendo2, risultato : integer; begin clrscr; writeln; writeln; writeln; write('Inserisci il primo addendo : '); readln(addendo1); write('Inserisci il secondo addendo : '); readln(addendo2); risultato := addendo1 + addendo2; writeln; writeln('Il risultato e'' ',risultato); end; begin prova2: prova1; writeln; write('Un''altra addizione? (s/n)'); readln(ancora); if ancora='s' then goto prova2; end. come vedete e` un semplice programma che fa un`addizione. La procedura non era strettamente necessaria, ma era solo per esempio. Analizziamo le cose nuove all`interno del semplice programma: label prova2; --->con questa riga abbiamo dichiarato un`"etichetta". Queste sono molto utili per rimandare il programma ad una certa riga in qualsiasi momento. E` un po` come quando col basic vi era "then goto numeroriga", e` la stessa cosa qui, solo che si rimanda al nome della label. procedure prova1; --->Vedi + avanti... risultato := addendo1 + addendo2; --->Come abbiamo detto in precedenza in questo modo si assegnano dei valori alle variabili. In questo caso abbiamo assegnato a risultato il valore della somma del valore di addendo1 e del valore di addendo2. Quel + tra le variabili viene detto operatore. Ve ne sono altri, ecco i + diffusi: + (gia` visto) per la somma - per la sottrazione / per la divisione * per la moltiplicazione prova2: ---> Assegniamo l`inizio della label, dichiarata in precedenza. Quando chiameremo la label, il programma continuera` ad eseguire i comandi da qui in poi. prova1; ---> Con questa riga richiamiamo la procedura scritta in precedenza. if ancora='s' then goto prova2; ---> controlla se ("if" = "se") la variabile ancora e` uguale a "s"; se e` uguale allora ("then" = "allora") vai alla ("goto" = "vai a") label prova2. Come avete visto le procedure sono come dei veri e propri programmi all`interno del nostro programma che possono essere chiamati quando si vuole. Ecco la sintassi: procedure nomeprocedura(eventuali_variabili : tipo); eventuali_variabili_2 : tipo; begin comando1; comando2; comando3; ... end; Come avete visto dopo il nome della procedura tra parentesi e` possibile inserire dei valori da poi utilizzare all`interno del programma. Inoltre prima del begin della procedura si possono anche dichiarare delle variabili da utilizzare, basta che il loro nome non sia lo stesso di quello tra parentesi dopo il nome della procedura. Non e` possibile creare concatenazioni di procedure, cioe` non si possono inserire altre procedure all`interno delle procedure. Come detto in precedenza vi sono anche le funzioni. Queste sono molto simili alle procedure, l`unica differenza e` che restituiscono un valore. Ecco la sintassi: function nomefunzione(variabili : tipo):tipo_funzione; eventuali_variabili : tipo; begin comando1; comando2; comando3; ... nomefunzione:=valore; end; in cui: tipo_funzione ---> i tipi sono gli stessi delle variabili nomefunzione:=valore ---> con la penultima riga non facciamo altro che assegnare alla funzione il valore da restituire. Ecco subito un esempio chiarificatore: uses crt; var a1,a2:integer; function somma(addendo1,addendo2:integer):integer; begin somma:=addendo1+addendo2; end; begin writeln; write('Inserisci il primo addendo: '); readln(a1); write('Inserisci il secondo addendo: '); readln(a2); writeln; writeln('Il risultato e'' ',somma(a1,a2)); repeat until keypressed; end. Come vedete, la funzione somma non fa altro che addizionare le variabili che gli vengono inviate. In precedenza, abbiamo visto il comando if. Spieghiamolo meglio; questo e` molto semplice infatti e` il corrispondente in inglese di come diremmo in italiano: se variabile1='Ciao' allora fai questo;. Cosi` in inglese, e quindi in pascal, faremo: if variabile1='Ciao' then comando1; Come vedete, cosi` eseguiamo un solo comando, per eseguire + comandi, ecco la sintassi: if variabile=2 then begin comando1; comando2; comando3; ... end; Inoltre, e` possibile inserire anche "else" il corrispondente dell`italiano "se no, invece, fai questo". Ecco un esempio di sintassi: if (questione=false) and (anni=16) then begin comando1; comando2; comando3; ... end else begin comando1; comando2; comando3; ... end; In questo codice, oltre ad usare else, abbiamo introdotto anche l`utilizzo di + di una condizione con AND che equivale ad e. Quindi se questione=false e anni=16 esegue i comandi. Inoltre, oltre ad AND esiste anche OR che equivale ad o. Spieghiamo invece ora gli altri cicli, oltre a repeat ... until. For , ecco la sua sintassi: for nomevariabile:=numero to numero2 do begin comando1; comando2; comando3; ... end; Grazie a questo ciclo si possono ripetere un determinato numero di volte dei comandi. Ecco un esempio: uses crt; var i : integer; begin for i:=1 to 10000 do begin write('Hello World! ',i); clrscr; end; end. Questo esempio scrive Hello world! 1 , poi pulisce la pagina e scrive Hello world! 2, fino ad arrivare a 10000 Un altro ciclo e` While (che corrisponde a "finche`"), ecco la sintassi: while condizione do begin comando1; comando2; comando3; ... end; Finche` si verifica la condizione si ripetono i comandi. Bene, come direbbe il grande Michael Bakunin: Ex Claro? Credo di aver spiegato chiaramente i concetti base del pascal, ora potete gia` iniziare a divertirvi con la vostra fantasia a creare nuovi programmi. Cerco di spiegare ora qualcosa in + sul pascal. Come ho detto all`inizio all`interno del pascal e` possibile inserire codice assembler. Questo e` possibile con asm ... end; Scrivendo asm si dice al compilatore che da li` fino al primo end; le istruzioni sono in assembler. Esempio: begin asm mov al, 07h end; end. Questo programma e` un esempio e non fa assolutamente niente, inserisce solo il valore 07 in esadecimale nella parte bassa del registro ax. Naturalmente, non posso spiegarvi l`assembler in questa guida, sarebbe troppo lunga, vi consiglio di leggere la guida all'asm di Michael Bakunin downloadabile da http://go.to/tankcommandos . Magari in futuro ne scrivero` una anch`io. Se si conosce bene sia l`assembler che il pascal, si puo` fare qualunque cosa dal sistema operativo al videogioco tridimensionale. Inoltre, ho detto in precedenza che all`interno del pascal si possono utilizzare funzioni scritte in altri linguaggi, basta compilarli ed ottenere il file con estensione obj. Per inserire questo file bisogna scrivere all`inizio del programma la riga: {$L nomefile.obj} in questo modo si potranno richiamare funzioni e procedure scritte nel file object. Naturalmente per ogni linguaggio esistono alcuni altri provvedimenti da prendere, di cui io non parlo in questa guida. Per esempio, per inserire l'object di un file assembler, bisognera` dichiarare nel file asm le procedure come public, e poi inserire nel nostro codice le procedure del file object che useremo in questo modo: procedure nomeprocedura; external; Dicendo external; il compilatore cerchera` direttamente la funzione nel file object. Infine, sfrutto quest`ultima parte della guida per parlare dei colori. Nella unit crt, vi sono infatti le procedure textcolor(colore) e textbackground(colore). Queste dichiarano il colore del testo e dello sfondo in modalita` testo. Per esempio: textcolor(white); textbackground(blue); clrscr; writeln('Hello world!'); non fa altro che mettere sfondo blu e testo bianco e scrivere Hello world! Ecco infine un piccolo programma di esempio: program prova_arcobaleno; uses crt; var coloretesto,coloresfondo : integer; i : byte; procedure arcobaleno; begin if coloretesto > 20 then begin coloretesto:=0; coloresfondo:=1; end else begin coloretesto := coloretesto + 1; coloresfondo := coloresfondo + 1; end; textcolor(coloretesto); textbackground(coloresfondo); clrscr; writeln; writeln(' HELLO WORLD!!!'); delay(10); end; begin coloretesto:=1; coloresfondo:=0; repeat arcobaleno; until keypressed; textcolor(15); textbackground(1); clrscr; writeln; writeln(' Tabella ASCII'); writeln; writeln(' premi il pulsante PAUSA per bloccare la lista'); writeln(' premi qualsiasi tasto per ricominciare a far scorrere la lista o per uscire'); delay(2000); i:=0; readln; repeat writeln(i,' = ',chr(i)); i:=i+1; delay(100); until keypressed; end. Questo esempio che ho scritto prima visualizza la scritta hello world (la tipica scritta che viene visualizzata di solito quando si scrive per la prima volta un programma) con effetto arcobaleno, e poi visualizza la tabella ascii. Ecco i comandi nuovi che ho inserito in questo esempio: delay ---> questo comando attende un determinato periodo di tempo, la sintassi e`: delay(ms) . Tra parentesi va il tempo da attendere in millesimi di secondo, quindi 1000 = 1 secondo. chr ---> questa funzione restituisce il carattere del numero inserito tra parentesi. Sintassi: chr(numero) . Per esempio se scriviamo write(chr(21)); otterremo scritto : § .Infatti, se tenendo premuto l`alt sinistro della vostra tastiera digitate 21 sui numeri sulla destra della vostra tastiera otterrete: §. Inoltre come avrete notato questa volta dopo l`if al posto di uguale = abbiamo utilizzato >. > sta a significare maggiore, < minore ed <> diverso. Siamo giunti agli sgoccioli della guida, perche` non so + cosa spiegare... Ecco un esempio di un altro programma: {$M 65000,0,65000} program esegui; uses dos,crt; var file_da_eseguire : string; begin clrscr; writeln; write('Path del file da eseguire : '); readln(file_da_eseguire); swapvectors; exec('c:\command.com',' /c ' + file_da_eseguire); swapvectors; writeln; writeln('Premi un tasto per uscire dal programma'); repeat until keypressed; end. La prima riga fa utilizzare 65000 byte di memoria, in modo da permettere l`esecuzione di programmi. Swapvectors, deve essere sempre usato prima e dopo exec. Exec ,infine, non fa altro che eseguire un file. Ecco la sintassi: exec(interprete_dei_comandi,parametri); L`interprete dei comandi del dos e di windows e` il command.com, quindi bastera` scrivere il suo path. Come parametri /c indica di eseguire un file, od un comando come ad esempio dir. Ora sapete quindi anche come eseguire un file. Ecco discusse qui altre procedure utili, di cui non ho avuto la possibilta` di parlare: gotoxy(y,x); ---> sposta il cursore alla x ed alla y data (x e` la riga dello schermo, mentre y e` la colonna) (in modalita` testo normale vi sono 20 righe ed 80 colonne) random(numero); ---> sceglie casualmente un numero da 1 fino al numero inserito fra parentesi. Per esempio : write(random(100)); scrivera` a video un numero casuale da 1 a 100. initgraph(drivergrafico,modografico,pathdeldriver) ---> inizializza il modo grafico. Questa funzione per essere eseguita ha bisogno della unit graph (quindi dovremo inserire graph dopo uses), e del path della directory bgi che si trova nella cartella del nostro pascal. Ecco un esempio di utilizzo della modalita` grafica: uses Graph; var Driver_grafico,Modo_grafico,Errore: Integer; begin Driver_grafico := Detect; InitGraph(Driver_grafico, Modo_grafico,'qui va il path dei file bgi'); {per es. c:\tp\bgi\ } Errore := GraphResult; if Errore = grOk then begin Line(0, 0, GetMaxX, GetMaxY); Readln; CloseGraph; end else Writeln('Errore grafico:', GraphErrorMsg(Errore)); end. Vediamo un po`: Driver_grafico := Detect; ---> Determina automaticamente il driver grafico giusto per la nostra scheda video, e lo assegna alla variabile Driver_grafico InitGraph(Driver_grafico, Modo_grafico,'qui va il path dei file bgi'); ---> Questa riga inizializza la modalita` grafica, utilizzando il driver determinato precedentemente. Nel terzo parametro va inserito il path dei file grafici con estensione .bgi. Per esempio, il mio e` 'c:\progra~1\borlan~1\bgi\' Errore := GraphResult; ---> Questa riga controlla il risultato ottenuto dopo essere stata inizializzata la grafica. if Errore = grOk then begin ---> se non vi e` errore allora: Line(0, 0, GetMaxX, GetMaxY); ---> disegna una linea che va dall`angolo in alto a sinistra sullo schermo, fino all`angolo in basso a destra. GetMaxX e GetMaxY sono delle costanti che indicano l`ultima riga e l`ultima colonna dello schermo. Readln; ---> aspetta che si prema un tasto (proprio come repeat until keypressed) CloseGraph; ---> chiude la modalita` grafica end else Writeln('Errore grafico:', GraphErrorMsg(Errore)); ---> se, invece, vi sono stati errori nella inizializzazione, scrive a video: Errore grafico: ed il codice dell`errore end. ---> fine programma L'articolo e` finito e spero vi sia piaciuto. Per critiche, per domande, per mandarmi affCENSUREDulo o per presentarmi vostra sorella :)) scrivetemi all'email xp_terminator@katamail.com Xp Terminator