GOTO jsem nezmiňoval, to je od vynálezu strukturovaného programování sprosté slovo
Ono bylo sice dávno dokázáno, že pouze pomocí větvení a cyklů je možné naprogramovat jakýkoliv algoritmus, ale Wirth ho v Pascalu přesto nechal, protože někdy se prostě hodí:
http://www.idemployee.id.tue.nl/g.w.m.rauterberg/lecturenotes/PascalRevisedReport(Wirth).pdf Mám tu někde jednu starou učebnici Pascalu, která je na používání GOTO založená. A je to dost hrozný pohled
A diskutuje se o tom už od Dijkstry:
https://homepages.cwi.nl/~storm/teaching/reader/Dijkstra68.pdfV Pascalu GOTO skáče na label, který se musí předem deklarovat v sekci "label", ještě před konstantami a proměnnými, takže v okamžiku kdy překladač dojde ke GOTO už název toho labelu zná. Konkrétní hodnotu pak může do kódu doplnit dodatečně, v okamžiku kdy se k umístění labelu dopracuje. Pro jazyk fungující rekurzivně to není problém, to není problém, to není problém
Ještě zajímavější to mohlo být u ranných překladačů Pascalu, které neprodukovaly spustitelný kód, ale přenositelný
P-code pro virtuální stroj. Dávno před Javou. V knize Algoritmy+Data=Programy Niklaus Wirth popisuje jednoduchý interpret -
P-code machine - se třemi registry a osmi základními instrukcemi. Jeho implementace v Pascalu má necelých 80 řádků.
Ale to už je dávná historie, protože Pascal je skutečný oldcomp jazyk, letos slaví právě padesáté narozeniny, takže je jenom o trošičku mladší než BASIC.
Před ELSE a END středník být nemusí, protože to nejsou příkazy. Jsou to pouze "uvozovky", které ukazují odkud kam sahají jednotlivé struktury v programu. Teorie říká, že každá struktura - příkaz - je blok s jedním vstupem a jedním výstupem. Takže celý program je z hlediska systému také příkaz, s jedním vstupem a jedním výstupem. Každý příkaz je v červeném rámečku, a celý program je ten úplně největší. Také jsou podle vnoření odstupňované šedě.
Uvnitř něj jsou zřetězené jednotlivé struktury,
oddělené středníkem. Což jsou na flowchartu jednoduchého prográmku níže deklarace názvu programu, deklarace jednotlivých typů, a deklarace příkazové části. A na konci programu je samozřejmě tečka, stejně jako na konci věty.
Ta příkazová část se skládá ze dvou zřetězených příkazů, oddělených středníkem. Je to ten druhý menší rámeček.
První příkaz je cyklus, který načte z klávesnice deset čísel a uloží je do pole. Celý cyklus má jeden vstup a jeden výstup. A je v malém rámečku vlevo.
Druhý příkaz je podobný cyklus, má také jeden vstup a jeden výstup, je v trochu větším rámečku vpravo.
V něm je vnořený příkaz provádějící větvení, které první buňku pole a ostatní s číslem stejným nebo větším vypíše na obrazovku tak jak jsou, a ty s menším číslem s opačným znaménkem. Jednotlivé části úplného větvení jsou oddělené ELSE. Větvení je samozřejmě také blok s jedním vstupem a výstupem, a je ve vlastním rámečku:
Příloha:
deset.png [ 5.87 KiB | Zobrazeno 8598 krát ]
Tolik říká teorie strukturovaného programování, a je to ideální způsob psaní programů pro pojídače koláčů. Všechno si krásně nalinkovat, rozložit do nejmenšího detailu, nikde se žádné čáry nesmí zkřížit, nikde se neskáče někam do neznáma. Celý kód se dá projet tužkou na papíře a dobře se v něm hledají začátečnické chyby, což je jeden z důvodů proč je Pascal vhodný výukový jazyk.
Pascalské CASE je trochu výjimka, protože nemá BEGIN. Bacha na to že v Pascalu tohle funguje úplně jinak než v C! Zatímco céčkový SWITCH je prostě GOTO do libovolného místa v sekvenci příkazů (ze které se dá pomocí BREAK kdykoliv vyskočit nebo naopak bez něj pokračovat do následující části), pascalské CASE je obdoba IF - ELSE IF - ELSE IF... Je to skutečné mnohonásobné větvení.
Neexistuje nic, co by překonalo eleganci příkazu PAR v Algolu 68. Dokonce ani Ada se tomu nevyrovná. Tolik k paralelizmu.
Válcování plechu? To mi připomnělo, jak Rusové při stěhování fabrik na útěku před Němci ztratili jednu stolici z linky na válcování pancéřových desek. Když to pak sestavili a chtěli vyrábět tanky, tak jim nezbylo než na těch zbylých přitlačit o něco víc, s překročením povolených limitů. Následkem toho byly pancíře T-34 ještě tvrdší a odolnější než původně měly být...
Tak jsem se vrhnul na ten program GRAFIK a přepsal ho do Turbo Pascalu (TP7 pod DOSBoxem). Ale potřeboval bych informaci, jaký je rozdíl mezi QORG a QMOVA. Ten druhý chápu, ale co přesně dělá ten první? Tipnul bych si že nastavuje nulový bod, od kterého se počítají souřadnice, do libovolného místa papíru, takže by se mohlo pracovat nejenom s kladnými hodnotami ale i se zápornými. Je to tak?
Příloha:
GRAFIK.png [ 9.96 KiB | Zobrazeno 8610 krát ]
Obraz je otočený o 90° doleva, zmenšený na třetinu kvůli VGA rozlišení, a tady je prozatímní zdroják:
Kód:
PROGRAM GRAFIK;
(*CAROVA GRAFIKA*)
uses Graph;
VAR OX,OY,
X1,Y1,X2,Y2,X3,Y3,
X4,Y4,X5,Y5,X6,Y6:INTEGER;
karta,rezim:integer;
penx,peny,penspeed:integer;
procedure qorg(x,y:integer);
begin
penx:=y;
peny:=x
end;
procedure qspeed(v:integer);
begin
if (v<0) or (v>5) then v:=5;
penspeed:=30000 div (v+1)
end;
procedure qmova(x,y:integer);
begin
penx:=x;
peny:=y
end;
procedure qvecta(x,y:integer);
var t:integer;
begin
line(peny*3 div 10,479-penx*3 div 10,y*3 div 10,479-x*3 div 10);
penx:=x;
peny:=y;
for t:=penspeed downto 0 do;
end;
PROCEDURE MINI(X1,Y1,X2,Y2,X3,Y3:INTEGER);
CONST J = 50; (*ROZLISITELNOST KRESBY*)
N = 50; (*DELENI*)
VAR I,X,Y : INTEGER;
BEGIN
QMOVA(X1,Y1);
FOR I:=1 TO J DO
BEGIN
IF I MOD 2=1 THEN (*KRESLENI JEDNIM TAHEM TAM*)
QVECTA(X1,Y1)
ELSE
QVECTA(X3,Y3);
X :=(X2-X1) DIV N+X1;
Y :=(Y2-Y1) DIV N+Y1;
X2:=(X3-X2) DIV N+X2;
Y2:=(Y3-Y2) DIV N+Y2;
QVECTA(X2,Y2);
X3:=(X1-X3) DIV N+X3;
Y3:=(Y1-Y3) DIV N+Y3;
X1:=X;
Y1:=Y;
IF NOT(I MOD 2=1) THEN (*KRESLENI JEDNIM TAHEM ZPET*)
QVECTA(X1,Y1)
ELSE
QVECTA(X3,Y3)
END
END;
BEGIN
karta:=9;
rezim:=2;
initgraph(karta,rezim,' ');
floodfill(0,0,15);
setcolor(0);
OX:= 750;OY:= 750; (*STRED KRESBY - NENI PODMINKOU*)
X1:= 750;Y1:= 500; (*KONCOVE SOURADNICE KRESBY*)
X2:=1500;Y2:= 0;
X3:= 900;Y3:=2100;
X4:= 750;Y4:=2100;
X5:= 600;Y5:=2100;
X6:= 0;Y6:= 0;
QORG(OX,OY);QSPEED(5);
MINI(X2,Y2,OX,OY,X1,Y1); (*PORADI BODU OVLIVNUJE SYMETRII,*)
MINI(X6,Y6,OX,OY,X1,Y1); (*TVAR KRESBY ATP *)
MINI(X2,Y2,OX,OY,X3,Y3);
MINI(X6,Y6,OX,OY,X5,Y5);
MINI(X3,Y3,OX,OY,X4,Y4);
MINI(X5,Y5,OX,OY,X4,Y4);
readln;
closegraph;
END.
P.S. Přidáno nastavení rychlosti kreslení. 0 = nejpomaleni, 5 = nejrychleji.