Obsah 1
´ vod U
5
2
Fortran ve Windows a v Linuxu
7
2.1
Windows – Prostrˇedı´ MSDS . . . . . . . . . . . . . . . . . . . . . . . . . . . .
7
2.2
Linux – Intel Fortran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
9
´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10 U 3
Za´klady syntaxe
11
Prˇ´ıklady . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13 ´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 U 4
Typy promeˇnny´ch
15
4.1
Typy INTEGER a REAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.2
Prˇevody typu˚ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
4.3
Typ COMPLEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.4
Typ LOGICAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
4.5
Typ CHARACTER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17 ´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18 U
5
Prˇ´ıkazy organizacˇnı´ 5.1
19
Podmı´neˇny´ prˇ´ıkaz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 Prˇ´ıklady . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 ´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20 U
5.2
Prˇ´ıkazy cyklu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21 Prˇ´ıklady . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22 ´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24 U
5.3
Na´hodna´ cˇ´ısla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 Prˇ´ıklady . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 ´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 U
5.4
Prˇ´ıkaz CASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26 1
Obsah
Prˇ´ıklady . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 ´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27 U 6
Pole I
29
´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 U 7
Vstup a vy´stup, forma´t
31
´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33 U 8
ˇ eteˇzce R
35
´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36 U 9
Podprogramy
37
9.1
Subroutiny . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
9.2
Funkce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
9.3
Standardnı´ funkce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
9.4
Parametry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40 9.4.1
Pole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
9.4.2
Rˇeteˇzce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
9.4.3
Popis INTENT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42 U 10 Pra´ce se soubory
43
´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46 U 11 Pole II
47
11.1 Konstrukce polı´ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47 11.2 Cˇa´sti pole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48 11.3 Standardnı´ podprogramy pro pole . . . . . . . . . . . . . . . . . . . . . . . . . 48 11.4 Dynamicke´ alokace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 ´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50 U
2
Obsah
12 Grafika 53 ´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56 U 13 Moduly 57 ´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58 U 14 Parametry podprogramu˚
59
14.1 Podprogramy jako parametry . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 14.2 Volitelne´ parametry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59 ´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60 U 15 Uzˇivatelsky´ typ 61 ´ koly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62 U 16 Fortran 77
63
Literatura
65
3
Obsah
4
1
´ vod U
V teˇchto skriptech se pokusı´me vysveˇtlit za´klady jazyka Fortran 90. Prˇedcha´zejı´cı´ verze tohoto jazyka Fortran 77 bude zmı´neˇna jen okrajoveˇ. Veˇtsˇina toho, co bude uvedeno v teˇchto skriptech, platı´ pro libovolny´ kompila´tor jazyka Fortran, ale prˇi prakticke´m programova´nı´ je trˇeba pracovat s konkre´tnı´m kompila´torem. V teˇchto skriptech budeme jako prˇ´ıklad pouzˇ´ıvat kompila´tor Compaq Visual Fortran 6.6 (nebo jeho velice podobne´ prˇedchu˚dce Digital Visual Fortran 5.0 a Microsoft Fortran 4.0) a kompila´tor Intel Fortran Compiler 7.0. Jazyk Fortran je jednı´m z nejstarsˇ´ıch programovacı´ch jazyku˚. Je to jazyk, ktery´ byl a je urcˇen prˇedevsˇ´ım pro veˇdecko-technicke´ vy´pocˇty. V tomto jazyce bylo naprogramova´no velke´ mnozˇstvı´ numericky´ch knihoven, ktere´ byly dokonale odladeˇny a neobsahujı´ tedy zˇa´dne´ chyby. Navı´c je ovla´dnutı´ jazyka ve verzi Fortran 90 pomeˇrneˇ jednoduche´. Tento text obsahuje pouze za´kladnı´ prvky jazyka Fortran 90. Prˇedpokla´da´me, zˇe pokud si student osvojı´ jazyk na u´rovni teˇchto skript, bude schopen si jizˇ dalsˇ´ı podrobnosti ty´kajı´cı´ se prˇesne´ syntaxe, standardnı´ch funkcı´ nebo neˇktery´ch pokrocˇily´ch rysu˚ tohoto jazyka, nastudovat sa´m za pomoci na´poveˇdy a dokumentace, ktera´ je vzˇdy soucˇa´stı´ dane´ho kompila´toru. Dalsˇ´ım zdrojem informacı´ je internet, prˇedevsˇ´ım pak stra´nky vyucˇujı´cı´ho (jejich adresa se mu˚zˇe meˇnit, proto bude vzˇdy uvedena na pocˇa´tku semestru). Zde bude mozˇne´ nale´zt rˇadu odkazu˚ na studijnı´ materia´ly a vzorove´ programy (na neˇktere´ z nich se odkazuje i prˇ´ımo v tomto textu). Aby si cˇtena´rˇ la´tku osvojil, je ovsˇem zapotrˇebı´ samostatneˇ naprogramovat co nejvı´ce prˇ´ıkladu˚ a splnit vsˇechny u´koly. Programova´nı´ se nelze nenaucˇit jinak nezˇ programova´nı´m. Proto take´ doporucˇujeme studentu˚m pracovat maxima´lneˇ samostatneˇ, nebot’ cı´lem nenı´ jen programy pru˚beˇzˇneˇ odevzda´vat, ale programova´nı´ ovla´dat jako jeden z na´stroju˚ jejich budoucı´ pra´ce. Prˇitom neza´lezˇ´ı tolik na tom, zda budete Fortran pouzˇ´ıvat ve Vasˇ´ı budoucı´ pra´ci. Rˇadu vlastnostı´ jazyka Fortran 90 najdete i v jiny´ch programovacı´ch jazycı´ch a naucˇ´ıte-li se jeden programovacı´ jazyk, ovla´dnutı´ dalsˇ´ıho Va´s jizˇ nebude sta´t tolik u´silı´.
5
1
U´vod
6
2 2.1
Fortran ve Windows a v Linuxu Windows – Prostrˇedı´ MSDS
Kompila´tor Compaq Visual Fortran 6.6 vyuzˇ´ıva´ vy´vojove´ prostrˇedı´ Microsoft Developer Studio. Toto prostrˇedı´ umozˇnˇuje psa´t, spousˇteˇt a ladit programy, je vyuzˇ´ıva´no nejen jazykem Fortran, ale i jazykem Microsoft Visual C++ a dalsˇ´ımi. Prˇi pra´ci v tomto prostrˇedı´ je trˇeba nejprve vytvorˇit tzv. projekt. Projekt obsahuje informace o tom, ze ktery´ch souboru˚ se ma´ vytva´rˇet vy´sledny´ program a dalsˇ´ı nastavenı´. Projekt v MSDS vytvorˇ´ıme vy´beˇrem menu File→New→Projects, pote´ je trˇeba vybrat typ projektu. Pokud nepotrˇebujeme pracovat s grafikou, vybereme projekt Fortran Console Application, azˇ budeme pozdeˇji pracovat s grafikou, vybereme projekt Fortran Standard or QuickWin Application. V prave´ cˇa´sti dialogove´ho okna vyplnı´me do Project name na´zev projektu (tj. i na´zev vy´sledne´ho programu) a do Location mı´sto na disku, kam se ma´ projekt ulozˇit. Prostrˇedı´ vytvorˇ´ı pro kazˇdy´ projekt novy´ adresa´ˇr, do ktere´ho se budou umı´st’ovat zdrojove´ texty a take´ vy´sledny´ program.
Obra´zek 1: Vytvorˇenı´ projektu
Po vytvorˇenı´ projektu je trˇeba vytvorˇit zdrojove´ texty. To lze nejjednodusˇeji prove´st ikonou New 7
2
Fortran ve Windows a v Linuxu
Text File a ulozˇenı´m souboru pod libovolny´m na´zvem s koncovkou .f90. Souboru˚ mu˚zˇe by´t libovolne´ mnozˇstvı´. Po vytvorˇenı´ souboru˚ je trˇeba urcˇit, ktere´ soubory patrˇ´ı do dane´ho projektu. V menu vybereme Project→Add to Project→Files a pote´ vybereme potrˇebne´ soubory. Soubory, ktere´ jsou skutecˇneˇ obsazˇeny v projektu jsou videˇt v leve´ cˇa´sti okna MSDS v Source Files.
Obra´zek 2: Hotovy´ projekt s vlozˇeny´m zdrojovy´m textem
Program musı´me prˇelozˇit („zkompilovat“), cozˇ prova´dı´me tak, zˇe v menu vybereme Build→Build {na´zev programu}, nebo stiskneme kla´vesu F7. Program spustı´me bud’ uvnitrˇ vy´vojove´ho prostrˇedı´ pomocı´ Build→Execute {na´zev programu}, nebo samostatneˇ na prˇ´ıkazove´ rˇa´dce syste´mu Windows napı´sˇeme jme´no prˇelozˇene´ho programu (tedy souboru s koncovkou .exe) v adresa´rˇi, kam se tento spustitelny´ soubor ulozˇil. Rovneˇzˇ je mozˇne´ spustit program z vy´vojove´ho prostrˇedı´ stiskem kombinace kla´ves Ctrl+F5. Shrnutı´ postupu: • Vytvorˇenı´ projektu • Vytvorˇenı´ zdrojovy´ch souboru˚ • Prˇirˇazenı´ souboru˚ do projektu 8
2
2.2
Fortran ve Windows a v Linuxu
Linux – Intel Fortran
Narozdı´l od MSDS je Intel Fortran rˇa´dkovy´ prˇekladacˇ a pra´ce s nı´m je me´neˇ komfortnı´. Na druhe´ straneˇ nenı´ nutne´ zakla´dat zˇa´dny´ projekt jako v MSDS a zdrojovy´ ko´d lze rovnou prˇelozˇit a program spustit.
Obra´zek 3: Zdrojovy´ ko´d v programu KWrite
Obra´zek 4: Prˇeklad a spusˇteˇnı´ programu hello
9
2
Fortran ve Windows a v Linuxu
Zdrojovy´ ko´d mu˚zˇeme vytvorˇit v libovolne´m textove´m editoru (naprˇ. KWrite nebo Emacs). Prˇed samotny´m prˇekladem je trˇeba hotovy´ ko´d ulozˇit na pevny´ disk do souboru s obvyklou prˇ´ıponou .f90. Prˇeklad spustı´me prˇ´ıkazem ifc -o nazev programu zdrojovy kod.f90, od verze prˇekladacˇe Intel Fortran Compiler for Linux 8.0 pak prˇ´ıkazem ifort -o nazev programu zdrojovy kod.f90, ktery´ zada´va´me v konzolove´m okneˇ. Samotny´ program pak spustı´me zada´nı´m na´zvu programu na prˇ´ıkazove´ rˇa´dce. Shrnutı´ postupu: • Vytvorˇenı´ zdrojove´ho ko´du – obycˇejny´ textovy´ soubor prˇ´ıponou .f90 • Prˇelozˇenı´ ko´du rˇa´dkovy´m prˇekladacˇem • Spusˇteˇnı´ programu ´ koly U 1. Vytvorˇte program pomocı´ jednoho z prˇedchozı´ch postupu˚. Do zdrojove´ho ko´du napisˇte: PROGRAM HELLO IMPLICIT NONE WRITE(*,*) ”Hello” END PROGRAM Program zkompilujte a spust’te. 2. Seznamte se pomocı´ na´poveˇdy (na disku pocˇ´ıtacˇe i na internetu) a dostupne´ dokumentace s kompila´torem a vy´vojovy´m prostrˇedı´m, se ktery´m budete da´le pracovat.
10
3
Za´klady syntaxe
Za´kladnı´ pozna´mky: • Nerozlisˇujı´ se mala´ a velka´ pı´smena, tj. Mu˚zˇeme napsat PROGRAM, program i Program. Tote´zˇ se ty´ka´ i jmen promeˇnny´ch – pokud promeˇnnou definujeme jako N, mu˚zˇeme na ni odkazovat i jako n (z du˚vodu prˇehlednosti programu je vsˇak vhodne´ pouzˇ´ıvat promeˇnnou tak, jak byla definova´na). • Komenta´rˇ je cokoliv co na´sleduje po znaku vykrˇicˇnı´k ! azˇ do konce rˇa´dku. Neexistuje vı´cerˇa´dkovy´ komenta´rˇ. • Na kazˇde´m rˇa´dku je jen jeden prˇ´ıkaz, ktery´ se neukoncˇuje strˇednı´kem. Pokud je na rˇa´dku vı´ce prˇ´ıkazu˚, pı´sˇeme strˇednı´k mezi neˇ. • Pokud se prˇ´ıkaz nevejde na rˇa´dek, lze ho rozdeˇlit na vı´ce rˇa´dku˚. Na konci rˇa´dku˚, ktere´ nejsou poslednı´, je trˇeba uva´deˇt znak &. • Soubor ma´ veˇtsˇinou koncovku .f90. Neˇkolik za´kladnı´ch pravidel: • Kazˇdy´ program zacˇ´ına´ klı´cˇovy´m slovem PROGRAM za ktery´m na´sleduje jednoslovny´ na´zev programu. • Jako druhy´ rˇa´dek vzˇdy uva´deˇjte IMPLICIT NONE. Tento prˇ´ıkaz nenı´ sice nezbytneˇ nutne´ uva´deˇt, ale pokud jej uvedeme, ma´me zarucˇenu du˚slednou kontrolu typu˚ promeˇnny´ch – vsˇechny promeˇnne´ musı´ by´t deklarova´ny v u´vodu programove´ jednotky, jinak dojde k chybove´ hla´sˇce kompila´toru. • Program koncˇ´ı slovem END nebo le´pe END PROGRAM, za ktery´m volitelneˇ mu˚zˇe na´sledovat i na´zev programu. • Mı´sto END PROGRAM mu˚zˇeme psa´t ENDPROGRAM. Podobneˇ je to i s ostatnı´mi prˇ´ıkazy, ktere´ jsou slozˇeny ze dvou slov, naprˇ. mı´sto END IF mu˚zˇeme psa´t i ENDIF apod. • Prˇivola´nı´ podprogramu je trˇeba prˇed jeho na´zvem uve´st CALL. Nejjednodusˇsˇ´ı program vypada´ tedy trˇeba takto (samozrˇejmeˇ vu˚bec nic nedeˇla´): PROGRAM PRVNI_PROGRAM IMPLICIT NONE END PROGRAM 11
3
Za´klady syntaxe
Za´kladnı´m prvkem jazyka jsou promeˇnne´. Identifika´tor promeˇnne´ mu˚zˇe obsahovat pı´smena, cˇ´ıslice a znak podtrzˇ´ıtko, musı´ ale zacˇ´ınat pı´smenem. Nerozlisˇujı´ se mala´ a velka´ pı´smena. Promeˇnne´ mohou mı´t neˇktery´ ze sˇesti typu˚, naprˇ. cela´ cˇ´ısla majı´ typ INTEGER, rea´lna´ majı´ typ REAL, znaky a rˇeteˇzce majı´ typ CHARACTER. Prˇi deklaraci promeˇnne´ se nejdrˇ´ıve uvede typ a za nı´m na´sledujı´ identifika´tory oddeˇlene´ cˇa´rkami. Naprˇ´ıklad INTEGER I REAL A,B CHARACTER C Promeˇnne´ nemajı´ definovanou zˇa´dnou pocˇa´tecˇnı´ hodnotu. Pocˇa´tecˇnı´ hodnotu vsˇak mu˚zˇeme zadat pomocı´ =. Specifikaci typu a promeˇnne´ je vsˇak trˇeba oddeˇlit dvojicı´ dvojtecˇek. Naprˇ´ıklad INTEGER :: I=0 REAL :: PI=3.1415926535, x=1.0 CHARACTER :: CH=’x’ Dvojtecˇky mu˚zˇeme psa´t volitelneˇ i v prˇ´ıpadeˇ, zˇe se pocˇa´tecˇnı´ hodnoty nezada´vajı´ a v na´sledujı´cı´m textu tak budeme zpravidla cˇinit. Pokud promeˇnna´ nema´ meˇnit svojı´ hodnotu (konstanta), uvede se za specifikaci typu dalsˇ´ı specifikace PARAMETER. Naprˇ´ıklad REAL, PARAMETER :: PI=3.1415926535897932384626433832795 INTEGER, PARAMETER :: N = 100, M = 3 CHARACTER, PARAMETER :: plus = ’+’ Za´kladnı´m zpu˚sobem pra´ce s promeˇnny´mi jsou prˇirˇazovacı´ prˇ´ıkazy. Znak pro prˇirˇazenı´ je =, za´kladnı´ aritmeticke´ opera´tory jsou + - * /. Pomocı´ opera´toru ** lze umocnˇovat. Lze pouzˇ´ıvat rˇadu standardnı´ch funkcı´ naprˇ´ıklad SIN, COS nebo SQRT pro odmocninu. Parametry funkcı´ se zada´vajı´ do kulaty´ch za´vorek. Vsˇechny deklarace promeˇnny´ch musı´ prˇedcha´zet vsˇem prˇ´ıkazu˚m. Vsˇechny promeˇnne´ je trˇeba deklarovat. PROGRAM DRUHY_PROGRAM ! Toto je prvnı ´ komenta ´r ˇ ! Toto je take komenta ´r ˇ IMPLICIT NONE ! nic nenı ´ deklarova ´no dopr ˇedu INTEGER :: I ! celoc ˇı ´selna ´ prome ˇnna ´ I REAL :: x,y,z ! rea ´lne ´ prome ˇnne ´ x,y,z REAL :: Z ! chyba, Z jiz ˇ bylo definova ´no x = y + z z = 1234*i ! v por ˇa ´dku, i je tote ´z ˇ co I z = SIN(y) y = SQRT(X) x = i**3 ! tote ´z ˇ co x = i*i*i 12
3
Za´klady syntaxe
INTEGER :: n ! chyba, deklarace musı ´ by ´t pr ˇed pr ˇı ´kazy y = SIN(3.14/2) i = -j ! chyba j nebylo deklarova ´no END PROGRAM Za´kladnı´ prˇ´ıkazem pro vy´pis promeˇnne´ nebo vy´razu na obrazovku je prˇ´ıkaz WRITE(*,*). Za tı´mto prˇ´ıkazem na´sledujı´ vypisovane´ vy´razy, ktere´ oddeˇlujeme cˇa´rkou. Naprˇ´ıklad WRITE(*,*) I WRITE(*,*) x+y, z Kazˇdy´ prˇ´ıkaz WRITE vypı´sˇe jeden rˇa´dek. Prˇ´ıkaz bude podrobneˇji vysveˇtlen pozdeˇji, nynı´ jen strucˇneˇ poznamenejme, zˇe prvnı´ hveˇzdicˇka zarˇ´ıdı´ vy´stup na obrazovku, druha´ specifikuje, zˇe forma´tova´nı´ vy´stupu je volne´ a zarˇ´ıdı´ jej sa´m jazyk Fortran. Podobneˇ, ale pro cˇtenı´, funguje prˇ´ıkaz READ. Tento prˇ´ıkaz nacˇte u´daje zadane´ z kla´vesnice do promeˇnny´ch. Naprˇ´ıklad READ(*,*) I READ(*,*) x, y READ(*,*) x+y ! chyba - pr ˇec ˇı ´st lze jen prome ˇnnou, nikoli vy ´raz Dalsˇ´ım cˇasto pouzˇ´ıvany´m typem jsou rˇeteˇzce. Pro zacˇa´tek vystacˇ´ıme s konstantnı´m rˇeteˇzcem, ktery´ se uva´dı´ jako text uzavrˇeny´ do uvozovek nebo do apostrofu˚, naprˇ´ıklad ”abc” nebo ’Uplne cokoliv.’. Mezi uvozovkami a apostrofy nenı´ zˇa´dny´ rozdı´l. Vy´znam hveˇzdicˇek je podobny´ jako u prˇ´ıkazu WRITE. Prˇ´ıklady Prˇ´ıklad: klasicky´ program pro vypsa´nı´ rˇeteˇzce na obrazovku. PROGRAM HALLO IMPLICIT NONE WRITE(*,*) ”Hallo World!” READ(*,*) END PROGRAM Prˇ´ıklad: jednoduchy´ program na rˇesˇenı´ kvadraticke´ rovnice ax2 + bx + c = 0. PROGRAM ROVNICE IMPLICIT NONE REAL :: a,b,c
! koeficienty rovnice 13
3
Za´klady syntaxe
REAL :: x1,x2 REAL :: d
! vy ´sledky ! diskriminant
WRITE(*,*) ”zadej koeficienty a,b,c kvadraticke rovnice” READ(*,*) a,b,c ! nac ˇtenı ´ koeficientu ˚ d = b**2 - 4*a*c ! vy ´poc ˇet diskriminantu x1 = ( -b + SQRT(d) )/(2*a) ! vy ´poc ˇet kor ˇenu ˚ x2 = ( -b - SQRT(d) )/(2*a) WRITE(*,*) ’koreny jsou: ’,x1,x2 ! vy ´pis kor ˇenu ˚ READ(*,*) ! c ˇeka ´nı ´ na stisk ENTER END PROGRAM Program po skoncˇenı´ pra´ce veˇtsˇinou ihned skoncˇ´ı. Aby si uzˇivatel stihl prˇecˇ´ıst u´daje vypsane´ na obrazovku je trˇeba na konec programu zarˇadit cˇeka´nı´ na stisk neˇjake´ kla´vesy. Toho lze dosa´hnou prˇ´ıkazem READ(*,*) bez parametru˚, ktery´ pocˇka´ na stisk kla´vesy ENTER. Pozna´mka: mı´sto WRITE(*,*) x mu˚zˇeme psa´t PRINT *, x. Mı´sto READ(*,*) x mu˚zˇeme psa´t READ *, x. ´ koly U 1. Prostudujte a vyzkousˇejte program: PROGRAM VYPOCET IMPLICIT NONE INTEGER :: a, b, c ! deklarace, INTEGER ! c ˇtenı ´ z obrazovky WRITE(*,*) ”Zadej a:” READ *,a WRITE(*,*) ”Zadej b:” READ *,b ! vy ´poc ˇet c=a+b ! tisk WRITE(*,*) ”a+b =”,c END PROGRAM VYPOCET 2. Nacˇteˇte z kla´vesnice dveˇ rea´lna´ cˇ´ısla a vypisˇte jejich soucˇet, rozdı´l, soucˇin a podı´l. 3. Sestavte program pro vy´pocˇet povrchu a objemu pravidelne´ho sˇestiboke´ho hranolu. 4. Napisˇte program pro za´meˇnu hodnot v promeˇnny´ch p a q. (Kolik dalsˇ´ıch promeˇnny´ch budete na tuto vy´meˇnu nutneˇ potrˇebovat?)
14
4
Typy promeˇnny´ch
Fortran zna´ sˇest typu˚ promeˇnny´ch: INTEGER, REAL, COMPLEX, CHARACTER, LOGICAL a uzˇivatelsky definovany´ typ.
4.1
Typy INTEGER a REAL
Cela´ cˇ´ısla majı´ typ INTEGER, rea´lna´ cˇ´ısla typ REAL. Prˇ´ıkladem cely´ch cˇ´ısel jsou -1100, 0, 1 nebo 33. Rea´lna´ cˇ´ısla musı´ mı´t desetinnou tecˇku nebo exponent. Prˇ´ıklady rea´lny´ch cˇ´ısel jsou .0, -1.10, +1E+30, 2E4, 1.12E-01 nebo 0.091. Zname´nko plus je volitelne´ a nemusı´ se uva´deˇt. Za typem lze v kulaty´ch za´vorka´ch uve´st prˇesnost promeˇnne´. Veˇtsˇ´ı hodnota odpovı´da´ prˇesneˇjsˇ´ı promeˇnne´. Mozˇne´ hodnoty za´visı´ na konkre´tnı´m prˇekladacˇi. U Visual Fortranu jsou mozˇne´ hodnoty: INTEGER(1), INTEGER(2), INTEGER(4), INTEGER(8), REAL(4), REAL(8). U Intel Fortranu navı´c i REAL(16). Cˇ´ıslo v za´vorce v tomto prˇ´ıpadeˇ znamena´ pocˇet bytu˚, ktere´ zabere promeˇnna´ v pameˇti pocˇ´ıtacˇe. REAL(4) prˇedstavuje jednoduchou prˇesnost rea´lny´ch cˇ´ısel, REAL(8) prˇesnost dvojitou, pro kterou se pouzˇ´ıva´ te´zˇ oznacˇenı´ DOUBLE PRECISION. Prˇi pra´ci s rea´lny´mi a celocˇ´ıselny´mi promeˇnny´mi je trˇeba da´t pozor na neˇkolik veˇcı´: Vy´sledkem vy´razu s cely´mi cˇ´ısly je opeˇt cele´ cˇ´ıslo. Z toho plynou velice cˇaste´ chyby, naprˇ´ıklad 1/2 je nula nikoliv polovina. Jednu polovinu musı´me zapsat jako 1.0/2 nebo 1/2.0 poprˇ. 1.0/2.0. Pozor: pokud budeme pracovat ve dvojite´ prˇesnosti, je trˇeba sdeˇlit tuto skutecˇnost i komplila´toru naprˇ. tı´m, zˇe mı´sto symbolu pro exponent E pouzˇijeme pı´smeno D. Vy´sˇe uvedene´ prˇ´ıklady rea´lny´ch cˇ´ısel zapı´sˇeme ve dvojite´ prˇesnosti naprˇ´ıklad takto: 0.0D0, -1.10D0, 1D+30, 2D4, 1.12D-01 nebo 9.1D-02. Jednu polovinu tedy napı´sˇeme spra´vneˇ naprˇ´ıklad jako 1.D0/2.D0. Neˇktere´ funkce prˇedpokla´dajı´, zˇe jejich parametr je rea´lne´ a ne cele´ cˇ´ıslo. Naprˇ´ıklad SQRT(2) je chyba, SQRT(2.0) je spra´vneˇ. Existujı´ i podobne´ standardnı´ funkce pracujı´cı´ prˇ´ımo ve dvojite´ prˇesnosti. Tyto funkce majı´ zpravidla jako prvnı´ pı´smeno D, naprˇ. DSQRT, DSIN, DCOS, apod. a jako parametr je vhodne´ samozrˇejmeˇ pouzˇ´ıvat rea´lne´ konstanty a rea´lne´ promeˇnne´ ve dvojite´ prˇesnosti.
4.2
Prˇevody typu˚
Cele´ cˇ´ıslo na rea´lne´ cˇ´ıslo veˇtsˇinou nenı´ potrˇeba prˇeva´deˇt, protozˇe prˇevod se uskutecˇnı´ automaticky. Naprˇ. REAL :: r r = 1 15
4
Typy promeˇnny´ch
Neˇkdy je vsˇak trˇeba prˇevod explicitneˇ uve´st. To lze udeˇlat pomocı´ prˇevodnı´ funkce REAL pro jednoduchou prˇesnost poprˇ. DBLE pro prˇesnost dvojitou nebo vytvorˇenı´m jednoduche´ho rea´lne´ho vy´razu. INTEGER :: WRITE(*,*) WRITE(*,*) WRITE(*,*) WRITE(*,*)
i SQRT(REAL(i)) SQRT(1.0*i) DSQRT(DBLE(i)) DSQRT(1D0*i)
Prˇi prˇevodu rea´lne´ho cˇ´ısla na cele´ je trˇeba urcˇit jaky´m zpu˚sobem zaohrouhlujeme. Ma´me k dispozici neˇkolik podobny´ch funkcı´: INT – odrˇ´ıznutı´ desetinne´ cˇa´sti, NINT – nejblizˇsˇ´ı cele´ cˇ´ıslo, CEILING – zaokrouhlenı´ nahoru, FLOOR – zaokrouhlenı´ dolu˚.
4.3
Typ COMPLEX
Typ COMPLEX reprezentuje komplexnı´ promeˇnne´. Podobneˇ jako u rea´lny´ch promeˇnny´ch lze do kulaty´ch za´vorek uve´st prˇesnost promeˇnne´. Komplexnı´ konstanty se definujı´ tak, zˇe do kulaty´ch za´vorek uvedeme rea´lnou a imagina´rnı´ cˇa´st oddeˇlene´ cˇa´rkami, naprˇ´ıklad komplexnı´ jednotka je x=(0,1). Takto je trˇeba zapisovat komplexnı´ cˇ´ıslo i v prˇ´ıpadeˇ, zˇe jej nacˇ´ıta´me z kla´vesnice a takto je i vypsa´no prˇ´ıkazem WRITE. Z rea´lny´ch promeˇnny´ch lze vytvorˇit komplexnı´ pomocı´ funkce CMPLX. c = CMPLX(a,b) REAL a,b – rea´lna´ a imagina´rnı´ cˇa´st COMPLEX c – vy´sledne´ komplexnı´ cˇ´ıslo Obra´ceneˇ funkce REAL vra´tı´ rea´lnou cˇa´st komplexnı´ho cˇ´ısla a funkce AIMAG imagina´rnı´ cˇa´st. Funkce CONJG vra´tı´ cˇ´ıslo komplexneˇ sdruzˇene´ a funkce ABS vra´tı´ absolutnı´ hodnotu. Komplexnı´ cˇ´ısla mu˚zˇeme scˇ´ıtat, odcˇ´ıtat, na´sobit i deˇlit pouze za pomoci opera´toru˚ +, -, * a /, takzˇe manipulace s komplexnı´mi cˇ´ısly v jazyku Fortran je velmi jednoducha´. Rovneˇzˇ funkce jako naprˇ. SIN nebo LOG umozˇnˇujı´ jako parametr pouzˇ´ıvat komplexnı´ cˇ´ısla.
4.4
Typ LOGICAL
Promeˇnna´ typu LOGICAL reprezentuje logickou hodnotu. Mu˚zˇe naby´vat pouze dvou hodnot a to pravda .TRUE. a nepravda .FALSE.. Logicke´ vy´razy lze vytva´rˇet pomocı´ srovna´vacı´ch (relacˇnı´ch) opera´toru˚ ==, >, <, >=, <=, /=. Pozor prˇedevsˇ´ım na opera´tor „je ru˚zne´ od“ /=, ktery´ se lisˇ´ı od jiny´ch programovacı´ch jazyku˚, naprˇ. od jazyka C. Ve vy´razech lze take´ pouzˇ´ıvat rˇadu logicky´ch spojek. Vsˇechny tyto opera´tory zacˇ´ınajı´ a koncˇ´ı tecˇkou. 16
4 Opera´tor .AND. .OR. .NOT. .EQV. .NEQV.
Typy promeˇnny´ch
Logicky´ vy´znam a za´rovenˇ nebo neplatı´ je ekvivalentnı´ nenı´ ekvivalentnı´
Do promeˇnny´ch typu LOGICAL lze naprˇ´ıklad prˇirˇadit konstantu (k=.TRUE.), porovna´nı´ cˇ´ıselny´ch promeˇnny´ch (k= a
4.5
Typ CHARACTER
Promeˇnne´ typu CHARACTER reprezentuje jeden znak. Pomocı´ tohoto typu se definujı´ i rˇeteˇzce, v tom prˇ´ıpadeˇ za CHARACTER uvedeme do kulaty´ch za´vorek de´lku rˇeteˇzce, naprˇ. CHARACTER(15) :: s je rˇeteˇzec, ktery´ ma´ 15 znaku˚. Tote´zˇ mu˚zˇeme zapsat i takto CHARACTER(LEN=15) :: s Rˇeteˇzce i znaky se uva´deˇjı´ do za´vorek nebo do apostrofu˚. Mezi za´vorkami a apostrofy nenı´ rozdı´l. Rˇeteˇzec, ktery´ zacˇ´ına´ uvozovkami musı´ i uvozovkami koncˇit, stejneˇ je to s apostrofy. Toho lze vyuzˇ´ıt pro rˇeteˇzec obsahujı´cı´ trˇeba apostrof. Naprˇ. CHARACTER :: c CHARACTER(5) :: s c = ’a’ c = ”a” s = ’ahoj!’ s = ”Can’t” Podrobneˇji bude o rˇeteˇzcı´ch pojedna´no v kapitole 8. 17
4
Typy promeˇnny´ch
´ koly U 1. Prostudujte, zda program PROGRAM Vypocet IMPLICIT NONE INTEGER :: aI=5, bI=3, cI REAL :: aR=5.0, bR=3.0, cR ! Prvni vypocet a tisk cI=aI/bI cR=aR/bR PRINT *, ”cI=aI/bI=”, cI PRINT *, ”cR=aR/bR=”, cR ! Druhy vypocet a tisk cI=aR/bR cR=aI/bI PRINT *, ”cI=aR/bR=”, cI PRINT *, ”cR=aI/bI=”, cR END PROGRAM Vypocet da´va´ vy´sledky, jake´ byste ocˇeka´vali. Pokud ne, uveˇdomte si rozdı´l mezi typy INTEGER a REAL a mezi celocˇ´ıselny´m a rea´lny´m deˇlenı´m. 2. Vyzkousˇejte funkce INT, NINT, CEILING a FLOOR na rea´lny´ch cˇ´ıslech −2.5 a 2.5. 3. Nacˇteˇte z kla´vesnice promeˇnnou a typu REAL a promeˇnne´ b a c typu COMPLEX. Proved’te operace a ∗ b − c, b + a ∗ c, b ∗ c a b/c. Vy´sledky vypisˇte na obrazovku. 4. Nacˇteˇte z kla´vesnice hodnoty dvou logicky´ch promeˇnny´ch L1 a L2, proved’te s nimi postupneˇ logicke´ operace .AND., .OR., .NOT., .EQV. a .NEQV. a vytiskneˇte prˇehledneˇ vy´sledky teˇchto operacı´, naprˇ. takto L1= T L2= F L1 .AND. L2 = F L1 .OR. L2 = T .NOT. L1 = F .NOT. L2 = T L1 .EQV. L2 = F L1 .NEQV. L2 = T 5. Napisˇte program, ktery´ se postupneˇ zepta´ na Vasˇe jme´no, datum, mı´sto narozenı´ a Vasˇe za´liby. Po obdrzˇenı´ jednotlivy´ch informaci program pro kontrolu tyto informace vypı´sˇe na obrazovku. 18
5 5.1
Prˇ´ıkazy organizacˇnı´ Podmı´neˇny´ prˇ´ıkaz
Prvnı´ organizacˇnı´ prˇ´ıkaz je podmı´neˇny´ prˇ´ıkaz. Je ho za´kladnı´ forma je IF (logicky ´_vy ´raz) THEN pr ˇı ´kazy ELSE pr ˇı ´kazy END IF Mı´sto END IF mu˚zˇeme psa´t take´ ENDIF, mezera zde nemusı´ by´t. Cˇa´st ELSE lze vypustit, zbyde pouze: IF (logicky ´_vy ´raz) THEN pr ˇı ´kazy END IF Pokud chceme vykonat pouze jediny´ prˇ´ıkaz, lze THEN a ENDIF vynechat: IF (logicky ´_vy ´raz) pr ˇı ´kaz Prˇ´ıkazy IF lze rˇeteˇzit ve tvaru: IF (logicky ´_vy ´raz1) THEN ... ELSE IF (logicky ´_vy ´raz2) THEN ... ELSE ... END IF Podmı´nky mohou by´t i vı´cena´sobneˇ vnorˇene´, naprˇ. IF (logicky ´_vy ´raz1) THEN ... IF (logicky ´_vy ´raz2) THEN ... ELSE ... END IF 19
5
Prˇ´ıkazy organizacˇnı´
ELSE ... END IF O jednoznacˇne´ prˇirˇazenı´ prˇ´ıkazu ELSE k prˇ´ıslusˇne´mu IF se vzˇdy postara´ umı´steˇnı´ prˇ´ıkazu END IF, ktere´ uzavı´ra´ blok s podmı´nkou. Je vzˇdy velice vhodne´ vnorˇene´ podmı´nky odsadit, aby i vizua´lneˇ prˇi cˇtenı´ programu bylo hned patrne´, ktera´ cˇa´st programu je vnorˇena a tvorˇ´ı vnitrˇnı´ cˇa´st jine´ podmı´nky. Nejcˇasteˇjsˇ´ı chybou je zapomenutı´ za´vorek, slova THEN nebo pouzˇitı´ END mı´sto ENDIF. Mezery mezi klı´cˇovy´mi slovy nejsou du˚lezˇite´ a lze pouzˇ´ıvat ENDIF i END IF, ELSEIF i ELSE IF. Prˇ´ıklady Prˇ´ıklad: zjisˇteˇnı´ zname´nka zadane´ho cˇ´ısla INTEGER :: a READ(*,*) a IF (a>0) THEN WRITE(*,*) ELSE IF (a<0) WRITE(*,*) ELSE WRITE(*,*) END IF
”cislo je kladne” THEN ”cislo je zaporne” ”cislo je nula”
Prˇ´ıklad: zjisˇteˇnı´, zda obeˇ cˇ´ısla jsou kladna´ a zda jsou obeˇ nenulova´. Podmı´neˇne´ prˇ´ıkazy mohou by´t i vnorˇene´. INTEGER a,b READ(*,*) a,b IF (a>0 .AND. b>0) WRITE(*,*) ”obe cisla jsou kladna” IF (b/=0) THEN IF (a/=0) THEN WRITE(*,*) ”obe cisla jsou nenulova” END IF END IF ´ koly U 1. Prˇepisˇte na´sledujı´cı´ vnorˇenou podmı´nku tak, abyste pouzˇili pouze jeden prˇ´ıkaz IF a spra´vnost rˇesˇenı´ oveˇrˇte v programu. 20
5
Prˇ´ıkazy organizacˇnı´
IF (b/=0) THEN IF (a/=0) THEN WRITE(*,*) ”obe cisla jsou nenulova” END IF END IF
2. Prˇecˇteˇte trˇi cˇ´ısla a vypisˇte nejveˇtsˇ´ı z nich. 3. Prˇecˇteˇte trˇi cˇ´ısla a vypisˇte ty dveˇ, ktere´ majı´ nejveˇtsˇ´ı soucˇet. 4. Zmeˇnˇte program pro hleda´nı´ koeficientu˚ kvadraticke´ rovnice z kapitoly 3 tak, aby byly osˇetrˇeny vsˇechny mozˇne´ prˇ´ıpady (tj. rˇesˇenı´m je jen jeden korˇen, rˇesˇenı´m jsou komplexnı´ korˇeny, je zada´no a = 0 nebo je zada´no a = b = 0).
5.2
Prˇ´ıkazy cyklu
Dalsˇ´ım organizacˇnı´m prˇ´ıkazem je prˇ´ıkaz cyklu. Nejjednodusˇsˇ´ı je nekonecˇny´ cyklus, ktery´ neusta´le opakuje prˇ´ıkazy v neˇm obsazˇene´. Ma´ tvar: DO pr ˇı ´kazy END DO Kamkoliv do tohoto cyklu lze zarˇadit prˇ´ıkaz EXIT, ktery´ cyklus okamzˇiteˇ ukoncˇ´ı, a program pokracˇuje za END DO. Da´le lze pouzˇ´ıt prˇ´ıkaz CYCLE, ktery´ ukoncˇ´ı aktua´lnı´ pru˚chod cyklem a program pokracˇuje dalsˇ´ım pru˚chodem za DO. Mezery mezi klı´cˇovy´mi slovy opeˇt nejsou du˚lezˇite´ a lze pouzˇ´ıvat ENDDO i END DO. Dalsˇ´ı formou cyklu je tzv. cyklus u´plny´. Ma´ tvar DO prom = start,konec,krok pr ˇı ´kazy END DO Pokud krok nenı´ uveden, prˇedpokla´da´ se krok rovny´ jedne´. I v tomto typu cyklu se mohou vyskytovat prˇ´ıkazy EXIT a CYCLE. Cyklus probı´ha´ tak, zˇe se nejprve nastavı´ hodnota promeˇnne´ prom na hodnotu start a provedou se postupneˇ prˇ´ıkazy mezi DO a END DO. Potom se k promeˇnne´ prom prˇicˇte krok a opeˇt se prova´dı´ vsˇechny prˇ´ıkazy uvnitrˇ cyklu. Toto se opakuje do te´ doby, nezˇ promeˇnna´ prom bude mı´t na zacˇa´tku cyklu hodnotu veˇtsˇ´ı nezˇ konec, nebo dokud nenı´ cyklus prˇedcˇasneˇ ukoncˇen naprˇ´ıklad pomocı´ EXIT. Poslednı´ mozˇnostı´ je cyklus podmı´neˇny´, ktery´ ma´ tvar 21
5
Prˇ´ıkazy organizacˇnı´
DO WHILE (logicky ´ vy ´raz) pr ˇı ´kazy END DO Prˇed provedenı´m prˇ´ıkazu˚ uvnitrˇ podmı´neˇne´ho cyklu se vzˇdy vyhodnocuje logicky´ vy´raz (uzavrˇeny´ v kulaty´ch za´vorka´ch) na jeho pocˇa´tku. Pokud je vy´sledkem logicke´ho vy´razu .TRUE., pak se prˇ´ıkazy uvnitrˇ cyklu provedou a pote´ se logicky´ vy´raz opeˇt vyhodnotı´, atd. V prˇ´ıpadeˇ, zˇe vy´sledkem logicke´ho vy´razu je .FALSE., prˇ´ıkazy uvnitrˇ cyklu se neprova´deˇjı´ a beˇh programu se prˇesouva´ na prvnı´ prˇ´ıkaz za cyklem. Cyklus tedy probı´ha´ dokud je splneˇna podmı´nka v jeho u´vodu. Prˇedpokla´da´ se samozrˇejmeˇ, zˇe uvnitrˇ cyklu se neˇjaky´m zpu˚sobem meˇnı´ promeˇnna´, ktera´ je soucˇa´stı´ logicke´ho vy´razu. V opacˇne´m prˇ´ıpadeˇ by byl totizˇ cyklus nekonecˇny´ (a beˇh programu bychom museli ukoncˇit na´silneˇ). Rovneˇzˇ cykly mohou by´t vnorˇene´, prˇ´ıkazy EXIT a CYCLE se pak vztahujı´ vzˇdy k nejvnitrˇneˇjsˇ´ımu cyklu DO. Opeˇt je vhodne´ prˇ´ıkazy vnitrˇnı´ho cyklu odsadit, aby byla prˇi cˇtenı´ programu dobrˇe patrna´ jeho struktura. Prˇ´ıklady Prˇ´ıklad 1: vy´pis cˇ´ısel od jedne´ do desı´ti. DO i=1,10 WRITE(*,*) i END DO Prˇ´ıklad 2: vy´pis sudy´ch cˇ´ısel od dvou do dvaceti. DO i=2,20,2 WRITE(*,*) i END DO Tote´zˇ zapsa´no pomocı´ cyklu DO WHILE vypada´ na´sledovneˇ: DO i=1,10 WRITE(*,*) 2*i END DO Prˇ´ıklad 3: vy´pis cˇ´ısel od desı´ti do jedne´. DO i=10,1,-1 WRITE(*,*) i END DO 22
5
Prˇ´ıkazy organizacˇnı´
Tote´zˇ zapsa´no „naopak“: DO i=1,10 WRITE(*,*) 11-i END DO Tote´zˇ zapsa´no pomocı´ cyklu DO WHILE: i=10 DO WHILE (i>0) WRITE(*,*) i i=i-1 END DO Prˇ´ıklad 4: nacˇ´ıta´nı´ cˇ´ısel z kla´vesnice, konec prˇi zada´nı´ nuly. DO READ(*,*) a WRITE(*,*) a IF (a == 0) EXIT END DO Tote´zˇ zapsa´no pomocı´ cyklu DO WHILE: a=1 ! abychom me ˇli jistotu, z ˇe je ’a’ nenulove ´ DO WHILE (a/=0) READ(*,*) a WRITE(*,*) a END DO Prˇ´ıklad 5: nacˇ´ıta´nı´ cˇ´ısel z kla´vesnice, vypisova´nı´ jen kladny´ch, deset pokusu˚. DO i=1,10 READ(*,*) a IF (a < 0) CYCLE WRITE(*,*) i,a END DO Prˇ´ıklad 6: nacˇ´ıta´nı´ cˇ´ısel z kla´vesnice, vypisova´nı´ jen kladny´ch, konec po deseti vypsany´ch kladny´ch cˇ´ıslech. 23
5
Prˇ´ıkazy organizacˇnı´
i = 0; DO READ(*,*) a IF (a < 0) CYCLE i = i + 1 WRITE(*,*) i,a IF (i == 10) EXIT END DO Opeˇt zapı´sˇeme cyklus i pomocı´ podmı´neˇne´ho cyklu: i = 0; DO WHILE (i<10) READ(*,*) a IF (a < 0) CYCLE i = i + 1 WRITE(*,*) i,a END DO
´ koly U 1. Prostudujte pecˇliveˇ rozdı´l mezi prˇ´ıklady 5 a 6. 2. Cˇteˇte cˇ´ısla z kla´vesnice, konec prˇi zada´nı´ nuly. Nakonec vypisˇte nejveˇtsˇ´ı z nich, jejich pocˇet a aritmeticky´ pru˚meˇt. 3. Cˇteˇte cˇ´ısla z kla´vesnice, konec prˇi zada´nı´ nuly. Pru˚beˇzˇneˇ vypisujte dosud nejveˇtsˇ´ı a nejmensˇ´ı cˇ´ıslo. 4. Vypisˇte vsˇechny dvojice cˇ´ısel mensˇ´ıch nezˇ 5, kazˇda´ dvojice se vypı´sˇe jen jednou ([3,4] je tote´zˇ co [4,3]). 5. Vypisˇte vsˇechny dvojice cˇ´ısel mensˇ´ıch nezˇ deset, jejichzˇ soucˇin je mensˇ´ı nezˇ 40. Nakonec vypisˇte jejich pocˇet. 6. Cˇteˇte znaky z kla´vesnice dokud nestisknete kla´vesu ’x’ nebo ’X’, potom program ukoncˇete. 7. Napisˇte program pro vy´pocˇet faktoria´lu zadane´ho cˇ´ısla n. 8. Napisˇte program, ktery´ prˇecˇte na vstupu cˇ´ıslo X a najde cˇ´ıslo n, jehozˇ faktoria´l je nejblizˇsˇ´ı nizˇsˇ´ı cˇ´ıslo k X. (Na´vod na rˇesˇenı´: hleda´me cˇ´ıslo n, pro ktere´ platı´ n ≤ X.) 24
5
5.3
Prˇ´ıkazy organizacˇnı´
Na´hodna´ cˇ´ısla
V rˇadeˇ prˇ´ıkladu˚ a u´kolu˚, ktere´ budou da´le uva´deˇny, je trˇeba nacˇ´ıtat cˇ´ısla z kla´vesnice. Opakovane´ zada´va´nı´ rˇady cˇ´ısel ale prˇi ladeˇnı´ programu cˇasto zdrzˇuje. Jako alternativu mu˚zˇete pouzˇ´ıvat vygenerova´nı´ na´hodny´ch (prˇesneˇji pseudona´hodny´ch) cˇ´ısel. Rea´lne´ cˇ´ıslo z intervalu h0, 1) lze vygenerovat prˇ´ıkazem RANDOM NUMBER. REAL :: a CALL RANDOM_NUMBER(a) Takto vygenerovana´ cˇ´ısla budou prˇi kazˇde´m spusˇteˇnı´ programu stejna´. Pokud chceme, aby cˇ´ısla byla ru˚zna´, pouzˇijeme na zacˇa´tku programu prˇ´ıkaz: CALL RANDOM_SEED() Pokud chceme generovat cela´ cˇ´ısla v neˇjake´m intervalu hc, di, pouzˇijeme pro prˇevod cˇ´ısla a zı´skane´ho vy´sˇe pomocı´ RANDOM NUMBER vztah INT(a*(d-c+1)+c) tedy cˇ´ıslo z rozsahu h0, 1) vyna´sobı´me rozsahem hodnot cely´ch cˇ´ısel a prˇicˇteme hodnotu prvnı´ho cˇ´ısla v intervalu. Vy´sledne´mu cˇ´ıslu odrˇ´ızneme desetinnou cˇa´st. Prˇ´ıklady Prˇ´ıklad: vygenerova´nı´ 10 na´hodny´ch cˇ´ısel, nalezenı´ nejveˇtsˇ´ıho z nich. INTEGER :: i REAL :: a, max_a CALL RANDOM_SEED() max_a = 0 DO i=1,10 CALL RANDOM_NUMBER(a) WRITE(*,*) a IF (a > max_a) max_a = a END DO WRITE (*,*) ”nejvetsi je ”, max_a ´ koly U 1. Vygenerujte deset na´hodny´ch cˇ´ısel a vypisˇte ta z nich, ktera´ jsou v intervalu h0.6, 0.8i. Napisˇte na za´veˇr, kolik vygenerovany´ch cˇ´ısel bylo z tohoto intervalu. 25
5
Prˇ´ıkazy organizacˇnı´ 2. Generujte na´hodna´ cˇ´ısla tak dlouho, dokud vygenerovane´ cˇ´ıslo nebude z intervalu h0.0, 0.1i. Vypisˇte toto cˇ´ıslo na obrazovku a vypisˇte i pocˇet pokusu˚, ktere´ vedly k vygenerova´nı´ tohoto cˇ´ısla. Prˇedchozı´ pokus opakujte peˇtkra´t. 3. Naprogramujte 20 hodu˚ kostkou, tj. na´hodneˇ generujte cˇ´ıslo od 1 do 6 a pokus 20 kra´t opakujte.
5.4
Prˇ´ıkaz CASE
Tento prˇ´ıkaz podle hodnoty vy´razu provede provede urcˇite´ prˇ´ıkazy. Syntaxe je na´sledujı´cı´ SELECT CASE (vy ´raz) CASE (hodnota1) pr ˇı ´kazy1 CASE (hodnota2) pr ˇı ´kazy2 ... CASE DEFAULT pr ˇı ´kazy END SELECT Vy´raz musı´ by´t typu INTEGER, CHARACTER nebo LOGICAL. Pokud vy´raz naby´va´ uvedene´ hodnoty vykonajı´ se na´sledujı´cı´ prˇ´ıkazy a prˇ´ıkaz CASE skoncˇ´ı. V prˇ´ıpadeˇ, zˇe vy´raz se nerovna´ zˇa´dne´ hodnoteˇ provedou se prˇ´ıkazy za CASE DEFAULT, tato cˇa´st mu˚zˇe ale chybeˇt. Na mı´steˇ hodnoty lze uva´deˇt jednotlive´ konstanty oddeˇlene´ cˇa´rkami. Mı´sto jednoduchy´ch konstant lze uva´deˇt i rozsahy. U rozsahu se uva´dı´ dolnı´ a hornı´ mez oddeˇlene´ dvojtecˇkou. Neˇktera´ z mezı´ mu˚zˇe chybeˇt, rozsah se potom bere od zacˇa´tku nebo do konce. Naprˇ´ıklad INTEGER :: i,a SELECT CASE (i) CASE(0) a = 1 CASE(1,4,20) a = 2 CASE(5:19,21) a = 3 CASE(22:) a = 4 CASE DEFAULT a = 5 END SELECT 26
5
Prˇ´ıkazy organizacˇnı´
Prˇ´ıkaz CASE lze vzˇdy nahradit rˇadou prˇ´ıkazu˚ IF, prˇ´ıkaz CASE je vsˇak prˇehledneˇjsˇ´ı a prˇi vhodne´m prˇekladacˇi by meˇl by´t i rychlejsˇ´ı. Prˇ´ıklady Jednoduche´ menu: INTEGER :: a, b, p DO WRITE(*,*) ”zadej dve cisla” READ(*,*) a, b WRITE(*,*) ”zadej operaci” WRITE(*,*) ”1 - soucet” WRITE(*,*) ”2 - rozdil” WRITE(*,*) ”0 - konec” READ(*,*) p SELECT CASE (p) CASE(0) EXIT CASE(1) WRITE(*,*) a + b CASE(2) WRITE(*,*) a - b CASE DEFAULT WRITE(*,*) ”neznama operace” END SELECT END DO ´ koly U 1. Napisˇte program, ktery´ prˇecˇte dveˇ cˇ´ısla z kla´vesnice a podle vy´beˇru umozˇnı´ prove´st neˇkterou z na´sledujı´cı´ch operacı´: 1) soucˇet 2) rozdı´l 3) soucˇin 4) podı´l teˇchto dvou cˇ´ısel. Tento proces se opakuje, dokud nenı´ stisknuta 0. 2. Upravte prˇedchozı´ program tak, zˇe vybı´ra´me z menu podle kla´ves ’s’ pro soucˇet, ’r’ pro rozdı´l, ’x’ pro soucˇin, ’p’ pro podı´l a ’k’ pro konec programu. 3. Prostudujte a vyzkousˇejte na´sledujı´cı´ program. PROGRAM Semafor IMPLICIT NONE CHARACTER(LEN=7) :: barva 27
5
Prˇ´ıkazy organizacˇnı´
PRINT *,”Mozne barvy semaforu: cervena, zluta, zelena” PRINT *,”Zadejte barvu svetla na semaforu:” READ(*,*) barva IF (barva==”cervena”) THEN WRITE(*,*) ”Stop!” ELSE IF (barva==”zluta”) THEN WRITE(*,*) ”Priprav se!” ELSE IF (barva==”zelena”) THEN WRITE(*,*) ”Jed!” ELSE WRITE(*,*) ”Neplatny udaj!” END IF END PROGRAM Semafor Upravte tento program pomocı´ prˇ´ıkazu CASE.
28
6
Pole I
Pole se ve Fortranu deklarujı´ tı´m, zˇe se prˇi deklaraci za identifika´tor promeˇnne´ uvede do kulaty´ch za´vorek rozmeˇr, prˇ´ıpadneˇ vı´ce rozmeˇru˚. Naprˇ. INTEGER :: a(10), b(3) REAL :: x(5,5) REAL :: y(3,3,3)
! jednorozme ˇrna ´ celoc ˇı ´selna ´ pole ! dvojrozme ˇrne ´ rea ´lne ´ pole ! trojrozme ˇrne ´ pole
Ve Fortranu zacˇ´ınajı´ indexy jednicˇkou. Pole b z poslednı´ho prˇ´ıkladu ma´ tedy prvky b(1), b(2) a b(3). Rozmeˇry se uva´deˇjı´ do kulaty´ch za´vorek a pokud je indexu˚ vı´ce, oddeˇlujı´ se cˇa´rkou. Pokud chceme, aby indexy zacˇ´ınaly od jine´ hodnoty, mu˚zˇeme uve´st pocˇa´tecˇnı´ i koncovy´ index oddeˇlene´ dvojtecˇkou. Naprˇ´ıklad prˇi deklaraci INTEGER c(-1:1) ma´me k dispozici prvky c(-1), c(0) a 0(1). Hodnoty, ktere´ urcˇujı´ velikost pole, musejı´ by´t doprˇedu zna´my. Jsou to bud’ cela´ cˇ´ısla jako v prˇedchozı´m prˇ´ıkladeˇ, nebo celocˇ´ıselne´ konstanty. Naprˇ´ıklad INTEGER, PARAMETER :: N=100 INTEGER, PARAMETER :: M=30 INTEGER :: a(M), b(2*N) REAL :: x(M,M), y(2,N) Rozmeˇry se uva´deˇjı´ do kulaty´ch za´vorek stejneˇ jako rozmeˇry prˇi deklaraci. Naprˇ. INTEGER,PARAMETER :: n=10 INTEGER :: a(n), b(n,n) INTEGER :: i, j DO i=1, n a(i)=i ENDDO DO i=1, n DO j=1, n b(i,j) = 3.0*a(i) + SIN(0.5*j) ENDDO ENDDO Pra´ce s poli je asi nejveˇtsˇ´ı vy´hoda jazyka Fortran, proto je trˇeba tomuto te´matu veˇnovat zvy´sˇenou pozornost. Pokud pouzˇijeme identifika´tor pole ve vy´razu bez uvedenı´ indexu˚, pracujeme s cely´m polem. Nejcˇasteˇjsˇ´ı pouzˇitı´ je prˇi inicializacı´ch, naprˇ´ıklad 29
6
Pole I
REAL :: a(10), b(3,3) a = 0.0 ! nastavı ´ cele ´ pole na nulu b = 1 ! nastavı ´ cele ´ pole na jednic ˇku Cela´ pole se mohou vyskytovat i na prave´ straneˇ vy´razu˚. Operace se potom prova´deˇjı´ pro vsˇechny jednotlive´ prvky. Takto lze nahradit cyklus jediny´m prˇ´ıkazem. Oproti za´pisu s cyklem mu˚zˇeme prˇi vhodne´m prˇekladacˇi dosa´hnout i zrychlenı´ vy´pocˇtu. Vsˇechny pole v prˇ´ıkazu musı´ mı´t stejny´ pocˇet indexu˚ i stejnou velikost. Naprˇ. REAL :: a(10), b(3,3), c(0:9) a = 3*c + 4*c**2 a = SIN(c) + a/2 a = SQRT(b) ! chyba, rozme ˇry nesouhlası ´ ! pr ˇedchozı ´ pr ˇı ´kazy lze zapsat i cyklem DO i=1,10 a(i) = 3*c(i) + 4*c(i)**2 a(i) = SIN(c(i)) + a(i)/2 ENDDO Cela´ pole lze jediny´m prˇ´ıkazem i vypisovat a nacˇ´ıtat. K prˇedchozı´mu prˇ´ıkladu mu˚zˇeme tedy doplnit WRITE(*,*) a WRITE(*,*) b Jestlizˇe takto vypı´sˇeme dvojrozmeˇrne´ pole, prvky budou vypsa´ny postupneˇ po sloupcı´ch. To souvisı´ s tı´m, zˇe ve Fortranu jsou prvky ukla´da´ny po sloupcı´ch. Tato vlastnost se projevı´ jen zrˇ´ıdka, ale obcˇas je trˇeba ji bra´t v u´vahu. ´ koly U 1. Naplnˇte pole o 10 prvcı´ch na´hodny´mi cˇ´ısly z intervalu h0, 1), prvky pole pro kontrolu vypisˇte. 2. Sestavte program pro vy´pocˇet skala´rnı´ho a vektorove´ho soucˇinu trojrozmeˇrny´ch vektoru˚. 3. Napisˇte program, ktery´ bude simulovat vrhy hracı´ kostkou. Vy´sledky jednotlivy´ch pokusu˚ zaznamena´vejte ve formeˇ cˇetnosti do pole o 6 prvcı´ch. Proved’te 1000 pokusu˚ a spocˇ´ıtejte relativnı´ cˇetnosti jednotlivy´ch vy´sledku˚ a pru˚meˇrnou hodnotu vy´sledku˚. 4. Napisˇte program pro rˇesˇenı´ soustavy maxima´lneˇ 6 linea´rnı´ch rovnic o 6 nezna´my´ch Gaussovou eliminacˇnı´ metodou.
30
7
Vstup a vy´stup, forma´t
Za´kladnı´ pouzˇitı´ prˇ´ıkazu˚ READ(*,*) a WRITE(*,*) jsme jizˇ videˇli. Vy´stup, ktery´ teˇmito prˇ´ıkazy dostaneme, je forma´tovany´ standardnı´m zpu˚sobem. Pokud chceme specifikovat vlastnı´ forma´t, lze uve´st popis forma´tu mı´sto druhe´ hveˇzdicˇky. Popis forma´tu je rˇeteˇzec, ktery´ zacˇ´ına´ a koncˇ´ı kulaty´mi za´vorkami. Uvnitrˇ za´vorek je samotna´ specifikace forma´tu. Prvnı´ pı´smeno v popisu forma´tu urcˇuje vypisovany´ typ, naprˇ´ıklad pı´smeno I slouzˇ´ı k vy´pisu promeˇnny´ch typu INTEGER. Cˇ´ıslo za tı´mto pı´smenem veˇtsˇinou oznacˇuje na kolik znaku˚ se ma´ promeˇnna´ vypisovat. Naprˇ´ıklad prˇ´ıkaz WRITE(*,’(I3)’) a vypı´sˇe promeˇnnou a pomocı´ trˇ´ı znaku˚. Pokud vypisujeme jednı´m prˇ´ıkazem vı´ce promeˇnny´ch, jednotlive´ prˇ´ıkazy se oddeˇlujı´ cˇa´rkami. Naprˇ´ıklad WRITE(*,’(I3,I5)’) a, b Pokud za sebou na´sleduje vı´ce stejny´ch forma´tu˚, lze za´pis zjednodusˇit, tı´m zˇe prˇed pı´smeno uvedeme cˇ´ıslo oznacˇujı´cı´ pocˇet opakova´nı´ dane´ho forma´tu, naprˇ´ıklad WRITE(*,’(4I3)’) a, b, c, d Forma´tu˚ existuje cela´ rˇada: Iw vy´pis cˇ´ısla typu INTEGER w je cele´ cˇ´ıslo bez zname´nka uda´vajı´cı´ pocˇet znaku˚ vy´pisu Tvar u´daje I lze uve´st i ve formeˇ Iw.m, kde na vstupu se .m ignoruje a prˇi vy´stupu uda´va´ minima´lnı´ pocˇet cˇ´ıslic. Ma´-li jich cˇ´ıslo me´neˇ, u´daj se prˇi tisku doplnı´ zleva nulami. Musı´ platit 0 ≤ m ≤ w . Bw, Ow, Zw vy´pis cˇ´ısla typu INTEGER Jedna´ se o modifikaci tvaru u´daje I pro cela´ cˇ´ısla ve dvojkove´, osmicˇkove´ a sˇestna´ctkove´ soustaveˇ. Fw.d vy´pis cˇ´ısla typu REAL s pevnou rˇa´dovou cˇa´rkou w je cele´ cˇ´ıslo bez zname´nka uda´vajı´cı´ pocˇet znaku˚ vy´pisu d uda´va´ pocˇet desetinny´ch mı´st. Ew.d vy´pis cˇ´ısla typu REAL s exponentem w je cele´ cˇ´ıslo bez zname´nka uda´vajı´cı´ pocˇet znaku˚ vy´pisu d uda´va´ pocˇet desetinny´ch mı´st Tvar u´daje E lze uve´st i ve formeˇ Ew.dEe. Na vstupu nema´ cˇa´st Ee vy´znam. Prˇi vy´stupu e urcˇuje pocˇet cˇ´ıslic exponentu. 31
7
Vstup a vy´stup, forma´t
EN (’engineering’) Je ekvivalentnı´ tvaru u´daje E s jedinou vy´hradou, zˇe exponent na vy´stupu bude vzˇdy deˇlitelny´ trˇemi. ES (’scientific’) Je ekvivalentnı´ tvaru u´daje E s vy´hradou, zˇe mantisa bude na vy´stupu vzˇdy normalizova´na v rozmezı´ h1, 10). Lw vy´pis cˇ´ısla typu LOGICAL w je cele´ cˇ´ıslo bez zname´nka uda´vajı´cı´ pocˇet znaku˚ vy´pisu nX vynecha´nı´ n znaku˚ na vstupu, nebo vy´pis n mezer. Aw vy´pis promeˇnne´ typu CHARACETER w uda´va´ pocˇet znaku˚, ktere´ se prˇecˇtou do rˇeteˇzce nebo ktere´ se z rˇeteˇzce vypı´sˇ´ı. G, Gw, Gw.d, Gw.dEe vybere vhodneˇjsˇ´ı z tvaru˚ F, E, I, L, A Tc skok na c-ty´ znak v rˇa´dku TLc skok o c znaku˚ doleva TRc skok o c znaku˚ doprava (tote´zˇ co Xc) Mı´sto specifikace forma´tu lze prˇ´ımo uve´st rˇeteˇzec, ktery´ se ma´ vypsat. WRITE(*, ’(”a = ”, I3)’) a WRITE(*, ’(a, I3)’) ”a = ”, a
! tote ´z ˇ co pr ˇedchozı ´ pr ˇı ´kaz
Prˇi vy´pisu kladny´ch cˇ´ısel se implicitneˇ kladne´ zname´nko nevypisuje. Pokud chceme, aby se plus vypisovalo, uvedeme specifikaci SP. Pokud chceme vypisova´nı´ zname´nka plus zrusˇit, uvedeme SS. Naprˇ´ıklad WRITE(*,’(SP, I4, SS, I4)’) a, a Pocˇet specifikacı´ ve forma´tu veˇtsˇinou odpovı´da´ pocˇtu vypisovany´ch promeˇnny´ch. Pokud je promeˇnny´ch vı´ce nezˇ je uvedeno ve forma´tu, forma´t se zacˇne pouzˇ´ıvat opeˇt od zacˇa´tku. Pokud je naopak promeˇnny´ch me´neˇ, zbytek forma´tu se ignoruje. Vyzkousˇejte WRITE(*, ’(”a = ”,I3,” b = ”,I3,” c = ”,I3)’) a, b, c WRITE(*, ’(”a = ”,I3,” b = ”,I3,” c = ”,I3)’) a, b, c, d, e WRITE(*, ’(”a = ”,I3,” b = ”,I3,” c = ”,I3)’) a, b Kazˇdy´ prˇ´ıkaz READ a WRITE vypisuje nebo cˇte jeden rˇa´dek. Jestlizˇe vsˇak chceme na jeden rˇa´dek psa´t pomocı´ vı´ce prˇ´ıkazu˚ je toto chova´nı´ nezˇa´doucı´. Kdyzˇ chceme zabra´nit prˇechodu na novy´ rˇa´dek, uvedeme jako trˇetı´ parametr prˇ´ıkazu WRITE parametr ADVANCE=’NO’. Naprˇ´ıklad 32
7
Vstup a vy´stup, forma´t
WRITE(*, ’(2I3)’) a, b ! lze napsat take ´ pomocı ´ dvou pr ˇı ´kazu ˚ WRITE(*, ’(I3)’,advance=’no’) a WRITE(*, ’(I3)’) b Pokud by se neˇktery´ forma´t neˇkolikra´t opakoval, mu˚zˇeme vyuzˇ´ıt prˇ´ıkazu FORMAT, a potom stacˇ´ı volat na´veˇsˇtı´ tohoto forma´tu, tedy pouze (v cele´m souboru jednoznacˇneˇ dane´) cˇ´ıslo, ktere´ je uvedeno prˇed prˇ´ıkazem FORMAT. Vsˇe lze pochopit z na´sledujı´cı´ uka´zky: INTEGER :: i1, j1, i2, j2 REAL :: x1, y1, x2, y2 ... WRITE(*, FMT=100) i1, i2, x1, y1 WRITE(*, FMT=100) j1, j2, x2, y2 100 FORMAT(’od =’,I3,’ do =’,I3,’ x =’,ES11.3,’ y =’,ES11.3) Uvedeny´ forma´t jsme v uka´zce vyuzˇili dvakra´t a nemusı´me tak naprˇ. opakovat delsˇ´ı vy´pis rˇeteˇzcu˚, ktery´mi jednotlive´ promeˇnne´ popisujeme. Dalsˇ´ı vy´hodou je, zˇe v prˇ´ıpadeˇ, kdyzˇ chceme zmeˇnit najednou neˇkolik vy´stupu˚, zmeˇnı´me vlastneˇ jen jeden prˇ´ıkaz. Prˇ´ıkazy FORMAT je vhodne´ bud’ umı´stit v blı´zkosti vy´pisu˚, nebo je soustrˇedit vsˇechny hromadneˇ do jednoho mı´sta programu (s prˇ´ıslusˇny´m komenta´rˇem popisujı´cı´m u´cˇel jednotlivy´ch prˇ´ıkazu˚). ´ koly U 1. Zobrazte co nejpr √ˇehledneˇji tabulku s hodnotami sinu, kosinu, tangens a kotangens u´hlu˚ 0, π/6, π/4, π/3, 3π/2 a π/2. Hodnoty funkcı´ vypisujte bez exponentu s prˇesnostı´ na peˇt desetinny´ch mı´st. 2. Naprogramujte svisly´ pa´d teˇlesa: zadejte z kla´vesnice vy´sˇku teˇlesa nad zemsky´m povrchem (zabranˇte prˇitom prˇechodu kurzoru na dalsˇ´ı rˇa´dek) a nechte teˇleso padat volny´m pa´dem. V cˇasech t = 0, 1, . . . sekund vypisujte cˇas, hodnotu vy´sˇky nad povrchem a okamzˇitou rychlost teˇlesa. V okamzˇiku dopadu teˇlesa na zemsky´ povrch vy´pis ukoncˇete. Hodnoty vy´sˇky a rychlosti vypisujte s prˇesnostı´ na trˇi desetinna´ mı´sta v za´pisu s exponentem.
33
7
Vstup a vy´stup, forma´t
34
8
ˇ eteˇzce R
Rˇeteˇzce majı´ pevnou de´lku, s jakou byly nadeklarova´ny. To ma´ vy´hodu v tom, zˇe nenı´ trˇeba zaby´vat se slozˇity´m alokova´nı´m pameˇti prˇi zmeˇneˇ de´lky rˇeteˇzce. Naopak nevy´hoda spocˇ´ıva´ v poneˇkud nezvykle´ pra´ci oproti jiny´m jazyku˚m. Pokud prˇirˇadı´me do rˇeteˇzce rˇeteˇzec kratsˇ´ı de´lky, zbytek se doplnı´ mezerami. Pokud prˇirˇadı´me rˇeteˇzec delsˇ´ı konec se ignoruje. Toto chova´nı´ je videˇt na na´sledujı´cı´m prˇ´ıkladu, prˇed a za rˇeteˇzcem vypisujeme dvojtecˇky, aby bylo videˇt de´lku rˇeteˇzce. CHARACTER(5) s s=’abc’ WRITE(*,*) ’:’, s, ’:’ s=’1234567’ WRITE(*,*) ’:’, s, ’:’
! vy ´sledek :abc
:
! vy ´sledek :12345:
Pro rˇeteˇzce existuje opera´tor //, ktery´ spojı´ dva rˇeteˇzce do jednoho. Naprˇ´ıklad WRITE(*,*) ’abc’//’12’. Cˇasto je trˇeba pracovat s cˇa´stı´ rˇeteˇzce. K tomu slouzˇ´ı vy´raz tvaru retezec(start:konec). Informaci o zacˇa´tku resp. o konci mu˚zˇeme vynechat, podrˇeteˇzec se potom vezme od zacˇa´tku rep. do konce pu˚vodnı´ho rˇeteˇzce. Naprˇ´ıklad CHARACTER(6) s s=’abcdef’ WRITE(*,*) s(2:4) WRITE(*,*) s(:4) WRITE(*,*) s(2:)
! vy ´sledek ’bcd’ ! vy ´sledek ’abcd’ ! vy ´sledek ’bcdef’
Ve Fortranu rˇeteˇzec nenı´ pole znaku˚. Na jeden znak se nelze odka´zat takto s(i), ale je trˇeba pouzˇ´ıt zpu˚sob s(i:i). Pro pra´ci s rˇeteˇzci existuje cela´ rˇada prˇ´ıkazu˚, k teˇm za´kladnı´m patrˇ´ı: l = LEN(s) Zjistı´ de´lku rˇeteˇzce CHARACTER(*) s – rˇeteˇzec INTEGER l – de´lka rˇeteˇzce l = LEN TRIM(s) Zjistı´ de´lku rˇeteˇzce bez koncovy´ch mezer CHARACTER(*) s – rˇeteˇzec INTEGER l – de´lka rˇeteˇzce bez koncovy´ch mezer ss = TRIM(s) – odstraneˇnı´ mezer na konci textove´ho rˇeteˇzce CHARACTER(*) s – rˇeteˇzec CHARACTER(*) ss – rˇeteˇzec s bez koncovy´ch mezer, tj. kratsˇ´ı rˇeteˇzec 35
8
Rˇeteˇzce
Pro jednoho prˇevod znaku na cˇ´ıslo (porˇadı´ v ASCII tabulce) a zpeˇt slouzˇ´ı tyto funkce: c = CHAR(i) – prˇevede cˇ´ısla na znak INTEGER i – cˇ´ıslo znaku CHARACTER c – znak na pozici i v tabulce znaku˚ i = ICHAR(c) – prˇevod znaku na cˇ´ıslo (opak CHAR) CHARACTER c – znak INTEGER i – porˇadı´ znaku c v tabulce znaku˚ Jako prˇ´ıklad uved’me ko´d, ktery´ do rˇa´dku vypı´sˇe abecedu: DO i=1, 26 WRITE(*,’(a)’,advance=’no’) char(i-1+ichar(’A’)) ENDDO WRITE(*,*) Dalsˇ´ı prˇ´ıklad prˇevede mala´ pı´smena v rˇeteˇzci na velka´ (vyuzˇ´ıva´me prˇ´ıkazu rozdeˇlene´ho na dva rˇa´dky): DO i=1, len(s) IF (s(i:i)>=’a’.and.s(i:i)<=’z’) s(i:i) = char(ichar(s(i:i))-ichar(’a’)+ichar(’A’)) ENDDO
&
Pro prˇevod rˇeteˇzce na cˇ´ıslo a obra´ceneˇ slouzˇ´ı jizˇ zna´me´ prˇ´ıkazy READ a WRITE. Jako prvnı´ parametr mı´sto hveˇzdicˇky nebo cˇ´ısla jednotky tentokra´t uvedeme identifika´tor rˇeteˇzce „cˇteme a zapisujeme do rˇeteˇzce“. Naprˇ´ıklad CHARACTER(5) s REAL :: x=3.14159 WRITE(s,’(f5.2)’) x s=’12.34’ READ(s,’(f5.2)’) x
! vy ´sledek s = ’ 3.14’ ! vy ´sledek x = 12.34
´ koly U 1. Vytvorˇte tabulku ASCII znaku˚ od 32 do 127 (zobrazte vedle sebe vzˇdy cˇ´ıslo a jemu odpovı´dajı´cı´ znak v ASCII tabulce). Tabulku vhodneˇ naforma´tujte, aby se vesˇla na jednu obrazovku. Zjisteˇte da´le, jake´ znaky se skry´vajı´ pod cˇ´ısly 128 azˇ 255. 2. Prˇecˇteˇte rˇeteˇzec z kla´vesnice a zmeˇnˇte v neˇm vsˇechna velka´ pı´smena na mala´. 3. Prˇecˇteˇte rˇeteˇzec z kla´vesnice (mu˚zˇe by´t i hodneˇ dlouhy´, naprˇ. 200 znaku˚) a nakopı´rujte tento rˇeteˇzec do jine´ho, prˇicˇemzˇ odstranˇte z textu (tedy i uvnitrˇ rˇeteˇzce) vsˇechny mezery.
36
9
Podprogramy
Ve Fortranu se rozlisˇujı´ dva typy podprogramu˚: FUNCTION – podprogramy vracejı´cı´ hodnotu – funkce SUBROUTINE – podprogramy nevracejı´cı´ hodnotu – subroutiny (nebo te´zˇ vlastnı´ procedury)
9.1
Subroutiny
Syntaxe subroutin je na´sledujı´cı´ SUBROUTINE nazev(parametry) ... deklarace ... prikazy ... END SUBROUTINE V hlavicˇce funkce se uva´deˇjı´ pouze identifika´tory parametru˚, jejich typy se specifikujı´ uvnitrˇ subroutiny jako u jiny´ch promeˇnny´ch. Uvnitrˇ subroutiny se nejprve uva´deˇjı´ deklarace loka´lnı´ch promeˇnny´ch a pote´ vy´konne´ prˇ´ıkazy, podobneˇ jako v hlavnı´m programu. Prˇi vola´nı´ subroutiny je nutne´ prˇed identifika´tor subroutiny uve´st prˇ´ıkaz CALL: CALL nazev(skutecne_parametry) Vsˇechny parametry se prˇeda´vajı´ tzv. odkazem. Jake´koliv zmeˇny parametru˚ uvnitrˇ subroutiny se projevı´ i ve skutecˇny´ch parametrech. Subroutiny se umist’ujı´ na konec programu za vy´konne´ prˇ´ıkazy. Od vy´konny´ch prˇ´ıkazu˚ se oddeˇlujı´ prˇ´ıkazem CONTAINS. Prˇ´ıklad: PROGRAM pythagoras ! ze zadany ´ch de ´lek odve ˇsen spoc ˇı ´ta ´ de ´lku pr ˇepony IMPLICIT NONE REAL :: x,y,z ! de ´lky stran WRITE(*,*) ’zadej odvesny’ READ(*,*) x,y CALL pythag(x,y,z) WRITE(*,*) ’prepona je : ’, z READ(*,*)
! ! ! !
CONTAINS 37
nac ˇtenı ´ de ´lek odve ˇsen zavola ´nı ´ podprogramu vy ´pis pr ˇepony c ˇeka ´nı ´ na Enter
9
Podprogramy
!================================================= SUBROUTINE pythag(a,b,c) REAL :: a,b,c c=SQRT(a**2+b**2) ! pythagorova veta END SUBROUTINE !================================================= END PROGRAM Vykona´va´nı´ podprogramu lze kdykoliv ukoncˇit prˇ´ıkazem RETURN. Promeˇnna´ deklarovana´ uvnitrˇ podprogramu je loka´lnı´ – v hlavnı´m programu ani v ostatnı´ch podprogramech ji nelze pouzˇ´ıt. Naopak promeˇnne´ deklarovane´ v hlavnı´m programu jsou globa´lnı´ – lze je pouzˇ´ıt i uvnitrˇ jake´hokoliv podprogramu (pokud ovsˇem nenı´ deklarova´na promeˇnna´ stejne´ho jme´na).
9.2
Funkce
Funkce jsou velice podobne´ subroutina´m, jejich syntaxe je na´sledujı´cı´ FUNCTION nazev(parametry) deklarace pr ˇı ´kazy END FUNCTION Ve Fortranu vystupuje identifika´tor funkce jako promeˇnna´ a vy´sledek se do te´to promeˇnne´ prˇirˇadı´. Prˇedchozı´ prˇ´ıklad zapsany´ jako funkce FUNCTION fpythag(a,b) REAL :: fpythag REAL :: a, b fpythag = SQRT(a**2+b**2) END FUNCTION Funkce se vola´ uvedenı´m identifika´toru se skutecˇny´mi parametry v aritmeticke´m prˇ´ıkazu. Naprˇ´ıklad z=fpythag(x,y) ! nebo WRITE(*,*) fpythag(x,y) Podprogramy nelze beˇzˇneˇ volat rekurzivneˇ. Pokud chceme pouzˇ´ıt rekurzivnı´ vola´nı´ je trˇeba prˇed slovo FUNCTION nebo SUBROUTINE uve´st RECURSIVE, naprˇ. 38
9
Podprogramy
RECURSIVE FUNCTION Recfun(x) REAL :: Recfun, x ... END FUNCTION Tuto funkci mu˚zˇeme nynı´ volat i vı´cekra´t najednou. Pokud nevola´ funkce prˇ´ımo sama sebe, ale prostrˇednictvı´m jine´ho podprogramu, stacˇ´ı uvedena´ deklarace. Pro prˇ´ıme´ rekursivnı´ vola´nı´ je trˇeba jesˇteˇ oddeˇlit na´zev funkce potrˇebny´ pro dalsˇ´ı vola´nı´ od vy´sledku vy´pocˇtu funkcˇnı´ hodnoty. K tomu slouzˇ´ı klı´cˇove´ slovo RESULT uda´vajı´cı´ na´zev promeˇnne´, do nı´zˇ bude vy´sledek ulozˇen. Zrˇejme´ to bude z prˇ´ıkladu na vy´pocˇet faktoria´lu: RECURSIVE FUNCTION Factorial(n) RESULT(res) INTEGER :: res, n IF (n==1) THEN res = 1 ELSE res = n*Factorial(n-1) END IF END FUNCTION
9.3
Standardnı´ funkce
Soucˇa´stı´ jazyka Fortran 90 je velke´ mnozˇstvı´ standardnı´ch funkcı´ a subroutin, ktere´ jsou prˇ´ımo implementova´ny do jazyka. Nenı´ tedy nutne´ prˇi jejich pouzˇ´ıva´nı´ spojovat programovy´ ko´d s ru˚zny´mi knihovnami nebo tyto knihovny volat z programu. Nejcˇasteˇji budeme pouzˇ´ıvat matematicke´ standardnı´ funkce. Jejich vy´znam je veˇtsˇinou patrny´ jizˇ z jejich na´zvu: ACOS(x), ASIN(x), ATAN(x), ATAN2(y,x), COS(x), COSH(x), EXP(x), LOG(x), LOG10(x), SIN(x), SINH(x), SQRT(x), TAN(x), TANH(x). Promeˇnna´ x je ve vsˇech prˇ´ıpadech rea´lne´ (mu˚zˇe vsˇak by´t i komplexnı´) cˇ´ıslo. Upozorneˇme na to, zˇe funkce LOG(x) prˇedstavuje logaritmus prˇirozeny´ a funkce LOG10(x) logaritmus dekadicky´. Jedineˇ funkce ATAN2(y,x) ma´ dva parametry a vracı´ u´hel, ktery´ svı´ra´ poloprˇ´ımka procha´zejı´cı´ bodem (x, y) s osou x. Dalsˇ´ımi cˇasto pouzˇ´ıvany´mi standardnı´mi funkcemi jsou funkce numericke´. Z nich jmenujme tyto za´kladnı´: ABS(x) AIMAG(z) AINT(x) ANINT(x) CEILING(x) CMPLX(x,y)
absolutnı´ hodnota imagina´rnı´ cˇa´st komplexnı´ho cˇ´ısla rea´lne´ cˇ´ıslo orˇ´ıznute´ na cele´ rea´lne´ cˇ´ıslo zaokrouhlene´ na cele´ nejmensˇ´ı cˇ´ıslo veˇtsˇ´ı nebo rovno x vytvorˇ´ı komplexnı´ cˇ´ıslo x + iy 39
9
Podprogramy
CONJG(z) komplexneˇ sdruzˇene´ komplexnı´ cˇ´ıslo DBLE(x) prˇeva´dı´ cele´, rea´lne´ cˇi komplexnı´ cˇ´ıslo na dvojitou prˇesnost DIM(x,y) kladny´ rozdı´l obou cˇ´ısel FLOOR(x) nejveˇtsˇ´ı cˇ´ıslo mensˇ´ı nebo rovno x INT(x) cele´ cˇ´ıslo vznikle´ orˇ´ıznutı´m desetinne´ cˇa´sti MAX(x1,x2,...) maximum z cˇ´ısel x1 , x2 , . . . MIN(x1,x2,...) minimum z cˇ´ısel x1 , x2 , . . . MOD(a,p) zbytek po deˇlenı´ (ma´ zname´nko prvnı´ho cˇ´ısla) MODULO(a,p) deˇlenı´ modulo (ma´ zname´nko druhe´ho cˇ´ısla) NINT(x) nejblizˇsˇ´ı cele´ cˇ´ıslo REAL(x) prˇevod cele´, rea´lne´ cˇi komplexnı´ cˇ´ıslo na cˇ´ıslo REAL(4) SIGN(x,y) hodnota prvnı´ho cˇ´ısla se zname´nkem druhe´ho
Pro prˇesneˇjsˇ´ı popis funkcı´ doporucˇujeme prostudovat dokumentaci a s funkcemi experimentovat.
9.4
Parametry
Prˇeda´va´nı´ skala´rnı´ch promeˇnny´ch jsme jizˇ videˇli. Prˇeda´va´nı´ polı´ jako parametru˚ je velice podobne´, v hlavicˇce podprogramu i prˇi jeho vola´nı´ se uvede pouze identifika´tor pole. Prˇi deklaraci pole uvnitrˇ podprogramu ma´me ale neˇkolik mozˇnostı´. 9.4.1
Pole
Prvnı´ mozˇnostı´ je u´plna´ definice pole, stejna´ jako globa´lnı´ch polı´. Naprˇ´ıklad SUBROUTINE subr(a) INTEGER :: a(10) Tento zpu˚sob prˇeda´va´nı´ pole nenı´ prˇ´ılisˇ vhodny´, protozˇe podprogram umozˇnˇuje pracovat pouze s polem jedne´ de´lky a nenı´ tudı´zˇ prˇ´ılisˇ univerza´lnı´. Druhou mozˇnostı´ je prˇeda´vat spolu s polem i jeho velikost, naprˇ´ıklad SUBROUTINE subr(a,n) INTEGER :: n INTEGER :: a(n) Tento zpu˚sob se lisˇ´ı od deklaracı´, ktere´ jsme videˇli doposud, protozˇe promeˇnna´ n nenı´ konstantnı´, ale mu˚zˇe se meˇnit. Toto lze pouzˇ´ıt nejen u forma´lnı´ch parametru˚, ale i u loka´lnı´ch promeˇnny´ch. Pozor na to, aby deklarace meze prˇedcha´zela deklaraci pole. Trˇetı´ mozˇnostı´ je uve´st mı´sto mezı´ pole dvojtecˇky, naprˇ´ıklad 40
9
Podprogramy
SUBROUTINE subr(a) INTEGER :: a(:) Velikost takove´ho pole bude stejna´ jako velikost pole, ktere´ prˇeda´me jako parametr prˇi vola´nı´ podprogramu. Tento zpu˚sob prˇeda´va´nı´ pole by meˇl by´t vyuzˇ´ıva´n co nejvı´ce. 9.4.2
ˇ eteˇzce R
Rˇeteˇzce lze prˇeda´vat podobneˇ jako pole s konstantnı´ de´lkou, naprˇ´ıklad SUBROUTINE subr(s) CHARACTER s(5) Vhodneˇjsˇ´ı ale je, uve´st mı´sto de´lky hveˇzdicˇku. De´lka rˇeteˇzce je potom stejna´ jako u skutecˇne´ho parametru, naprˇ´ıklad SUBROUTINE subr(s) CHARACTER s(*) 9.4.3
Popis INTENT
Podprogramu mu˚zˇeme rˇ´ıci, zda promeˇnna´, ktera´ je parametrem, je na vstupu zna´ma, cˇi zda jejı´ hodnota je nezna´ma´ a bude teprve vypocˇ´ıta´na uvnitrˇ podprogramu, nebo zda se jedna´ o promeˇnnou, jejı´zˇ hodnotu zna´me a uvnitrˇ podprogramu se tato hodnota zmeˇnı´. K tomu slouzˇ´ı popis INTENT, ktery´ ma´ na´sledujı´cı´ trˇi mozˇne´ hodnoty: IN – parametr je vstupnı´, jeho hodnota nesmı´ by´t uvnitrˇ podprogramu zmeˇneˇna. OUT – parametr je vy´stupnı´, jeho hodnota nenı´ na zacˇa´tku zna´ma, bude uvnitrˇ podprogramu urcˇena a vyuzˇita v cˇa´sti programu, ze ktere´ podprogram vola´me. Parametr je tedy urcˇen pro prˇenos vy´sledku z podprogramu ven. INOUT – parametr je vstupneˇ-vy´stupnı´, jeho hodnota je definova´na prˇi vstupu do podprogramu, mu˚zˇe by´t uvnitrˇ podprogramu zmeˇneˇna a prˇeda´ se do mı´sta vola´nı´ podprogramu, kde mu˚zˇe by´t da´le vyuzˇita. Atribut INOUT je nastaven jako implicitnı´ a nenı´ jej trˇeba uva´deˇt. Naprˇ´ıklad ve vy´sˇe uvedene´ subroutineˇ na vy´pocˇet prˇepony pravou´hle´ho troju´helnı´ka bychom popis INTENT pouzˇili na´sledovneˇ: SUBROUTINE pythag(a,b,c) REAL, INTENT(IN) :: a,b ! vstupnı ´ parametry REAL, INTENT(OUT) :: c ! vy ´stupnı ´ parametr = vy ´sledek c=SQRT(a**2+b**2) ! pythagorova veta END SUBROUTINE 41
9
Podprogramy
V mnohy´ch prˇ´ıpadech tı´mto zpu˚sobem se v programu vyvarujeme chyb a program bude navı´c mozˇne´ prˇi prˇekladu i le´pe optimalizovat. Shrnutı´ za´sad pro pra´ci s podprogramy: • Subroutiny se volajı´ prˇ´ıkazem CALL • Podprogramy nelze volat rekurzivneˇ, pouze s RECURSIVE • Podprogramy se umist’ujı´ za CONTAINS • Pro parametry podprogramu uva´dı´me popis INTENT • Subroutinu lze ukoncˇit prˇ´ıkazem RETURN ´ koly U 1. Vytvorˇte program, ktery´ spocˇ´ıta´ pru˚meˇr pouze lichy´ch cˇ´ısel z cˇ´ısel, ktere´ zada´va´ uzˇivatel. Prˇi zada´nı´ za´porne´ho cˇ´ısla se program ukoncˇ´ı. Pouzˇijte funkci modulo(a,b) a prˇ´ıkazy CYCLE a EXIT. 2. Napisˇte program, ve ktere´m pouzˇijete vsˇechny standardnı´ funkce uvedene´ v kapitole 9.3. 3. Napisˇte program pro vy´pocˇet druhe´ mocniny pomocı´ vlastnı´ funkce. Program pak rozsˇirˇte pro vy´pocˇet n-te´ mocniny (n prˇirozene´). 4. Prˇepisˇte program pro vy´pocˇet skala´rnı´ho a vektorove´ho soucˇinu z kapitoly 6 pomocı´ podprogramu˚. Jako parametr prˇeda´vejte cele´ pole. 5. Napisˇte rekurzivnı´ podprogram na vy´pocˇet rekurentneˇ zadane´ posloupnosti, jejı´zˇ prvnı´ cˇlen je roven x1 = 0.5 a n-ty´ cˇlen te´to posloupnosti je da´n jako na´sobek prˇedchozı´ho cˇlenu vztahem xn = xn−1 ∗ 1.5. 6. Prˇepisˇte u´lohy 2 resp. 3 z kapitoly 8 tak, zˇe zmeˇnu velky´ch pı´smen na mala´ resp. vymaza´nı´ vsˇech mezer z rˇeteˇzce zabezpecˇ´ı podprogramy.
42
10
Pra´ce se soubory
V te´to kapitole probereme pra´ci s nejjednodusˇsˇ´ım typem souboru˚ – s textovy´mi soubory. Kazˇde´mu soubor, se ktery´m v jazyce Fortran pracujeme, prˇirˇadı´me tzv. cˇ´ıslo jednotky. Pra´ci se souborem zacˇ´ına´me prˇ´ıkazem OPEN. Prvnı´ parametr tohoto prˇ´ıkazu je cˇ´ıslo jednotky a druhy´ parametr je rˇeteˇzec obsahujı´cı´ na´zev souboru prˇirˇazeny´ do parametru FILE=. Naprˇ´ıklad OPEN(5, FILE=’data.txt’) Prˇed prvnı´m parametrem mu˚zˇe volitelneˇ by´t UNIT=, tj. vy´sˇe uvedeny´ prˇ´ıkaz je tudı´zˇ totozˇny´ s prˇ´ıkazem OPEN(UNIT=5, FILE=’data.txt’) Prˇi otevrˇenı´ souboru se nerozlisˇuje, zda ze souboru budeme cˇ´ıst nebo do neˇj zapisovat. Pokud soubor existuje, prˇ´ıkaz OPEN ho otevrˇe a nastavı´ aktua´lnı´ pozici na jeho zacˇa´tek. Pokud soubor neexistuje, prˇ´ıkaz OPEN vytvorˇ´ı soubor nulove´ de´lky a nastavı´ aktua´lnı´ pozici na jeho zacˇa´tek. Pra´ce se souborem se ukoncˇ´ı prˇ´ıkazem CLOSE, ktery´ ma´ jediny´ povinny´ parametr, a tı´m je cˇ´ıslo jednotky. Naprˇ´ıklad CLOSE(5) Podobneˇ jako u prˇ´ıkazu OPEN, mu˚zˇeme i zde volitelneˇ napsat prˇed cˇ´ıslo jednotky specifika´tor UNIT=. Pokud je soubor otevrˇen, mu˚zˇeme z neˇj nacˇ´ıtat prˇ´ıkazem READ nebo do neˇj zapisovat prˇ´ıkazem WRITE, stejneˇ jako cˇteme z kla´vesnice nebo vypisujeme na obrazovku. Jako prvnı´ parametr teˇchto prˇ´ıkazu˚ uva´dı´me mı´sto hveˇzdicˇky cˇ´ıslo jednotky. Naprˇ´ıklad WRITE(5,*) i WRITE(5,’(I4,F5.2)’) j, x READ(6,*) i, j, k Zda se nacha´zı´me na konci souboru, lze zjistit funkcı´ EOF – end of file. Tato funkce ma´ jako parametr cˇ´ıslo jednotky a vracı´ .TRUE., pokud je aktua´lnı´ pozice na konci souboru a .FALSE. jinak. Naprˇ´ıklad na´sledujı´cı´ ko´d nacˇte vsˇechna cˇ´ısla ze souboru a vypı´sˇe jejich pocˇet. OPEN(4, FILE=’data.txt’) n=0 DO 43
10
Pra´ce se soubory
IF (EOF(4)) EXIT READ(4,*) x n=n+1 END DO CLOSE(4) WRITE(*,*) n S vy´sˇe uvedeny´mi neˇkolika prˇ´ıkazy mu˚zˇeme vystacˇit ve veˇtsˇineˇ prˇ´ıpadu˚ jednoduche´ pra´ce se soubory. Uvedeme jesˇteˇ neˇkolik parametru˚, ktery´mi mu˚zˇeme ovlivnit vstup a vy´stup do souboru. Prˇi otevı´ra´nı´ souboru mu˚zˇeme pomocı´ rˇeteˇzce prˇirˇazene´ho do parametru STATUS= sdeˇlit programu stav souboru v okamzˇiku jeho otevı´ra´nı´. Pokud zada´me hodnotu ’NEW’, jedna´ se o soubor, ktery´ bude programem noveˇ vytvorˇen (tento soubor nesmı´ existovat). Pokud zada´me hodnotu ’OLD’, jedna´ se o soubor, ktery´ jizˇ existuje (tento soubor musı´ existovat). Hodnota ’REPLACE’ znamena´ nahrazenı´ souboru a zajistı´ vytvorˇenı´ nove´ho souboru v prˇ´ıpadeˇ, zˇe neexistuje, nebo – pokud soubor existuje – smaza´nı´ tohoto souboru a vytvorˇenı´ nove´ho souboru se stejny´m jme´nem. Volbu ’SCRATCH’ mu˚zˇeme pouzˇ´ıt pro nepojmenovany´ novy´ docˇasny´ soubor, ktery´ se po zavrˇenı´ souboru nebo po ukoncˇenı´ programu automaticky smazˇe. Pokud neuvedeme parametr STATUS=, je mu prˇirˇazena hodnota ’UNKNOWN’. Ta znamena´, zˇe soubor mu˚zˇe, ale nemusı´, existovat. Pokud soubor neexistuje, vytvorˇ´ı se novy´ soubor. Jako prˇ´ıklad otevrˇeme soubor vystup.txt. Pokud soubor neexistuje, bude vytvorˇen, pokud existuje, bude nahrazen: OPEN(7, FILE=’vystup.txt’, STATUS=’REPLACE’) Po otevrˇenı´ se meˇnı´ stav souboru na ’OLD’. Pokud bychom chteˇli otevrˇ´ıt existujı´cı´ soubor a nava´zat na neˇj, tj. dalsˇ´ı hodnoty prˇida´vat na konec souboru, mu˚zˇeme vyuzˇ´ıt parametr POSITION=, ktere´mu prˇirˇadı´me hodnotu ’APPEND’. Tedy meˇjme naprˇ´ıklad jizˇ vytvorˇen soubor ’data.txt’. Chceme-li nynı´ prˇipsat dalsˇ´ı vy´stup za konec tohoto souboru, otevrˇeme jej na´sledovneˇ: OPEN(8, FILE=’data.txt’, STATUS=’OLD’, POSITION=’APPEND’) Pokud bychom v prˇedchozı´m prˇ´ıkazu zvolili STATUS=’UNKNOWN’, docı´lili bychom stejne´ho efektu a navı´c by soubor byl v prˇ´ıpadeˇ, zˇe neexistuje, vytvorˇen (a do souboru by se tedy zapisovalo od jeho zacˇa´tku, ktery´ je prˇi prvnı´m otevrˇenı´ souboru totozˇny´ s jeho koncem). Parametr POSITION= mu˚zˇe jesˇteˇ naby´vat hodnotu ’REWIND’ pro pozici prˇesunutou na zacˇa´tek souboru a ’ASIS’, ktera´ ponecha´va´ pozici bez zmeˇny, pokud byl soubor jizˇ prˇipojen. Abychom naprˇ. zabra´nili neu´myslne´mu za´pisu do souboru, ma´me mozˇnost pomocı´ parametru ACTION= urcˇit, zda soubor pouzˇijeme jen pro cˇtenı´ (ACTION=’READ’), jen pro za´pis (ACTION=’WRITE’) nebo bez omezenı´ pro cˇtenı´ i pro za´pis (ACTION=’READWRITE’). Poslednı´ hodnota je zpravidla (ne vsˇak nutneˇ) nastavena jako implicitnı´. V na´sledujı´cı´m prˇ´ıkladu otevrˇeme jizˇ existujı´cı´ soubor katalog.txt jen pro cˇtenı´: 44
10
Pra´ce se soubory
OPEN(9, FILE=’katalog.txt’, STATUS=’OLD’, ACTION=’READ’) Rovneˇzˇ i u prˇ´ıkaz CLOSE mu˚zˇeme pouzˇ´ıt parametr STATUS=, ktery´ urcˇuje co se stane, kdyzˇ soubor zavrˇeme. Hodnota ’KEEP’ ponecha´ soubor na disku, zatı´mco zvolı´me-li ’DELETE’, soubor bude po sve´m zavrˇenı´ vymaza´n. Implicitneˇ je nastavena hodnota ’KEEP’, to se ovsˇem nevztahuje na docˇasne´ soubory, ktere´ byly otevrˇeny prˇ´ıkazem OPEN jako STATUS=’SCRATCH’. Pokud potrˇebujeme zjistit stav souboru, at’jizˇ otevrˇene´ho nebo jen souboru neˇkde na disku, mu˚zˇeme pouzˇ´ıt prˇ´ıkaz INQUIRY. Ma´ rˇadu mozˇny´ch parametru˚, neˇktere´ z nich si nynı´ prˇedstavı´me. Jedna z variant tohoto prˇ´ıkazu ma´ tvar INQUIRE (FILE=jmeno_souboru, seznam_parametru) a mu˚zˇeme se jejı´ pomocı´ dotazovat na vlastnosti souboru s na´zvem jmeno souboru. Druha´ varianta tohoto prˇ´ıkazu ma´ tvar INQUIRE ([UNIT=]jednotka, seznam_parametru) a mu˚zˇeme se jejı´ pomocı´ dotazovat na vlastnosti jednotky danou (prˇirozeny´m) cˇ´ıslem jednotka. Specifika´tor UNIT= prˇed cˇ´ıslem jednotky je opeˇt volitelny´. V seznamu parametru˚ da´va´me za rovnı´tko promeˇnnou, do ktere´ se ukla´da´ hodnota parametru, na ktery´ se dotazujeme. Parametru˚ je cela´ rˇada, neˇktere´ z nich jsou analogicke´ parametru˚m prˇ´ıkazu OPEN. Uved’me neˇktere´ parametry prˇ´ıkazu INQUIRE vhodne´ pro pra´ci s textovy´mi soubory: • NAME=jmeno ulozˇ´ı do promeˇnne´ jmeno rˇeteˇzec se jme´nem souboru. • EXIST=existuje ulozˇ´ı do logicke´ promeˇnne´ existuje hodnotu .TRUE., pokud soubor existuje a mu˚zˇe by´t otevrˇen nebo pokud uvedena´ jednotka existuje. Pokud soubor nebo jednotka neexistujı´, nebo soubor existuje, ale nemu˚zˇe by´t otevrˇen, promeˇnne´ existuje bude prˇirˇazena hodnota .FALSE. • OPENED=otevren prˇirˇadı´ logicke´ promeˇnne´ otevren hodnotu .TRUE., pokud je uvedeny´ soubor nebo jednotka prˇipojena a hodnotu .FALSE., pokud uvedeny´ soubor nebo jednotka prˇipojeny nejsou. • ACTION=akce vracı´ v promeˇnne´ akce rˇeteˇzec, ktery´ ma´ hodnotu ’READ’ pokud je soubor otevrˇen pouze pro cˇtenı´, ’WRITE’ pokud je soubor otevrˇen pouze pro za´pis a ’READWRITE’ pokud je soubor otevrˇen pro cˇtenı´ i pro za´pis. Hodnota ’UNDEFINED’ je prˇirˇazena v prˇ´ıpadeˇ, zˇe soubor nenı´ prˇipojen. • NUMBER=cislo prˇirˇadı´ do celocˇ´ıselne´ promeˇnne´ cislo cˇ´ıslo jednotky pra´veˇ prˇipojene´ k souboru. Pokud nenı´ prˇipojena k souboru zˇa´dna´ jednotka, prˇirˇadı´ se hodnota −1. 45
10
Pra´ce se soubory • POSITION=pozice umozˇnˇuje dotaz na polohu v souboru. V promeˇnne´ pozice se vracı´ rˇeteˇzec obsahujı´cı´ hodnotu ’REWIND’ pokud je soubor prˇipojen a jeho poloha je na zacˇa´tku souboru, ’APPEND’ pokud je soubor prˇipojen a jeho poloha je na konci souboru (prˇed znacˇkou konce souboru – pokud existuje), ’ASIS’ pokud je soubor prˇipojen a jeho poloha se nemeˇnı´, nebo ’UNDEFINED’ pokud soubor nenı´ prˇipojen. • READ=cteni, WRITE=psani, READWRITE=ctenipsani umozˇnˇujı´ zjistit, zda ze souboru mu˚zˇeme cˇ´ıst, zapisovast, nebo za´rovenˇ cˇ´ıst i zapisovat. V promeˇnny´ch cteni, psani a ctenipsani bude vra´cen rˇeteˇzec obsahujı´cı´ ’YES’ pokud ano, ’NO’ pokud ne, a ’UNKNOWN’ pokud nelze odpoveˇd’ zjistit.
Jako prˇ´ıklad uvedeme dotaz na existenci souboru ’pokus.dat’ a da´le zjistı´me stav jednotky cˇ´ıslo 9, kterou jsme otevrˇeli v uka´zce uvedene´ vy´sˇe: CHARACTER(12) :: nm, ac, wr LOGICAL :: op, ex ... INQUIRE(FILE=’pokus.dat’, EXIST=ex) IF (ex==.TRUE.) THEN WRITE(*,*) ”Soubor ’pokus.dat’ existuje.” ELSE WRITE(*,*) ”Soubor ’pokus.dat’ nelze najit.” END IF ... INQUIRE(UNIT=9, NAME=nm, ACTION=ac, OPENED=op, WRITE=wr) ´ koly U 1. Vytvorˇte program, ktery´ do souboru data.txt napı´sˇe posloupnost cely´ch cˇ´ısel od 1 do 100. 2. Sestavte program, ktery´ do souboru pythagor.txt napı´sˇe vzˇdy po trˇech do rˇa´dku Pythagorejska´ cˇ´ısla a, b, c, tj. cela´ cˇ´ısla vyhovujı´cı´ rovnici a2 + b2 = c2 . Pokud soubor pythagor.txt jizˇ existuje, prˇepisˇte jej. 3. Upravte program pro rˇesˇenı´ kvadraticke´ rovnice tak, zˇe hodnoty zadane´ z kla´vesnice i rˇesˇenı´ rovnice budou (s podrobneˇjsˇ´ım popisem rˇesˇenı´) zapsa´ny do souboru kvadrov.txt. Pokud soubor kvadrov.txt jizˇ existuje, prˇipisujte vy´sledky na konec souboru. 4. Pomocı´ prˇ´ıkazu INQUIRE zjiteˇte, zda soubor ’data.txt’ existuje. Pokud ano, otevrˇete jej pouze pro cˇtenı´ a zobrazte na obrazovce jeho obsah. Pokud neexistuje, vytvorˇte jej pouze pro za´pis a zapisˇte do neˇj vsˇechny u´daje, ktere´ doka´zˇete zjistit o jeho stavu pomocı´ prˇ´ıkazu INQUIRE.
46
11
Pole II
Pole ve Fortranu sky´tajı´ oproti ostatnı´m jazyku˚m velke´ mozˇnosti.
11.1
Konstrukce polı´
Jizˇ vı´me, jak jednı´m prˇ´ıkazem naplnit cele´ pole, naprˇ´ıklad INTEGER :: a(5) a = 1 Tı´mto prˇ´ıkazem nastavı´me vsˇechny prvky pole na jednicˇku. Pokud chceme do jednotlivy´ch prvku˚ prˇirˇadit ru˚zne´ hodnoty, mu˚zˇeme nejprve z teˇchto hodnot vytvorˇit pole a to prˇirˇadit do pole a. Vytvorˇenı´ pole ze zadany´ch hodnot se provede tak, zˇe mezi (/ a /) vlozˇ´ıme jednotlive´ hodnoty oddeˇlene´ cˇa´rkami, naprˇ´ıklad a = (/2,7,3,1,5/) Toho lze vyuzˇ´ıt uzˇ prˇi inicializaci pole v samotne´ deklaraci, naprˇ. (nezapomı´nat na dvojtecˇky za typem) REAL :: b(3) = (/1.0, 2.345, 34.0/) Tı´mto zpu˚sobem lze i spojovat pole dohromady, naprˇ. (pozor velikosti polı´ musı´ souhlasit) INTEGER :: a(3),b(2),c(5) a = (/1,2,3/); b = (/10,11/) c = (/a,b/) ! vy ´sledek c = (/1,2,3,10,11/) c = (/1,5,b,0/) ! vy ´sledek c = (/1,5,10,11,0/) V prˇ´ıpadeˇ, zˇe pole jsou velka´, je vypisova´nı´ vsˇech hodnot obtı´zˇne´. Pro tento prˇ´ıpad je cˇasto mozˇne´ prˇi konstrukci pole vyuzˇ´ıt cyklu. Tento cyklus ma´ tvar podobny´ u´plne´mu DO-cyklu: (vyraz,promenna=od,do,krok) Tento cyklus se vkla´da´ mezi (/ a /) mı´sto vy´cˇtu hodnot. Naprˇ´ıklad: INTEGER :: a(5),i a=(/(i, i=1,5)/) a=(/(i, i=5,1,-1)/) a=(/(3*(i-1), i=1,5)/) a=(/(100*SIN(10.*i), i=1,5)/) a=(/0, (i,i=104,106), 1/)
!vy ´sledek !vy ´sledek !vy ´sledek !vy ´sledek !vy ´sledek 47
a=(/1,2,3,4,5/) a=(/5,4,3,2,1/) a=(/0,3,6,9,12/) a=(/-54,91,-98,74,-26/) a=(/0,104,105,106,1/)
11
Pole II
Konstrukce (/../) vytva´rˇ´ı nove´ pole, mu˚zˇe se tedy vyskytovat nejen v prˇirˇazovacı´m prˇ´ıkazu, ale kdekoliv, kde mu˚zˇe by´t pole. Naprˇ´ıklad a=-2*(/(i,i=1,5)/) CALL subr((/0,1,22/))
11.2
!vy ´sledek a=(/-2,-4,-6,-8,-10/)
Cˇa´sti pole
Jizˇ jsme zmı´nili mozˇnost pra´ce s cely´mi poli najednou. Dalsˇ´ı mozˇnostı´ je pra´ce jen s cˇa´stı´ pole. Na mı´steˇ indexu lze uve´st dveˇ meze oddeˇlene´ dvojtecˇkou. Zı´ska´me tı´m spojity´ u´sek pole zacˇ´ınajı´cı´ prvnı´ mezı´ a koncˇ´ıcı´ druhou mezı´ naprˇ a(2:5). Kteroukoliv z mezı´ lze vynechat, potom se pracuje s u´sekem od zacˇa´tku resp. do konce pole, naprˇ. a(:5) nebo a(2:). Lze vynechat i obeˇ meze. U jednorozmeˇrne´ho pole tı´m nic nezı´ska´me, naprˇ´ıklad a(:) je tote´zˇ co samotne´ a. Vynecha´nı´ obou mezı´ u jednoho indexu je vsˇak velice cˇaste´ u vı´cerozmeˇrny´ch polı´, tı´m lze naprˇ´ıklad z dvourozmeˇrne´ho pole udeˇlat jednorozmeˇrne´. Naprˇ´ıklad a(3,:) je jednorozmeˇrne´ pole obsahujı´cı´ trˇetı´ rˇa´dek matice a, nebo a(:,j) je j-ty´ sloupec matice. Z pole mu˚zˇeme vybrat i jednotlive´ prvky, a to tak, zˇe mı´sto indexu uvedeme pole obsahujı´cı´ indexy vybı´rany´ch prvku˚. Toho lze vyuzˇ´ıt i pro permutace prvku˚ pole. Prˇ´ıklady: INTEGER :: a(4) = (/10,20,30,40/), c(4) INTEGER :: b(4) = (/4,2,1,3/) WRITE(*,*) a(2:3) ! vy ´sledek 20,30 WRITE(*,*) a(:2) ! vy ´sledek 10,20 WRITE(*,*) a(2:3) ! vy ´sledek 20,30 WRITE(*,*) a((/4,2,3/)) ! vy ´sledek 40,20,30 c = a((/4,2,3,1/)) ! vy ´sledek c = (/40,20,30,10/) c = a(b) ! vy ´sledek c = (/40,20,10,30/) c(b) = a ! vy ´sledek c = (/30,20,40,10/)
11.3
Standardnı´ podprogramy pro pole
Pro pra´ci s poli existuje rˇada funkcı´. Nejdu˚lezˇiteˇjsˇ´ı z nich si nynı´ probereme. Funkce SUM a PRODUCT umozˇnˇujı´ secˇ´ıst a vyna´sobit cele´ pole. SUM(array) – Funkce secˇte prvky pole typu INTEGER, REAL nebo COMPLEX PRODUCT(array) – Funkce vyna´sobı´ prvky pole typu INTEGER, REAL nebo COMPLEX Funkce MAXVAL a MINVAL zjistı´ hodnotu nejveˇtsˇ´ıho a nejmensˇ´ıho prvku v poli. Cˇasto ale nestacˇ´ı zna´t hodnotu nejveˇtsˇ´ıho nebo nejmensˇ´ıho prvku, ale i jeho polohu. K tomu slouzˇ´ı dalsˇ´ı dveˇ funkce MAXLOC a MINLOC 48
11
Pole II
MAXVAL(array) – Funkce vra´tı´ hodnotu maxima´lnı´ho prvku pole typu INTEGER nebo REAL MINVAL(array) – Funkce vra´tı´ hodnotu minima´lnı´ho prvku pole typu INTEGER nebo REAL MAXLOC(array) – Funkce vra´tı´ polohu maxima´lnı´ho prvku pole MINLOC(array) – Funkce vra´tı´ polohu minima´lnı´ho prvku pole Poloha extre´mnı´ho prvku se vracı´ jako celocˇ´ıselne´ pole, jehozˇ de´lka odpovı´da´ pocˇtu indexu˚ vstupnı´ho. Pokud je vstupnı´ pole naprˇ´ıklad dvourozmeˇrne´ dostaneme vektor o de´lce dveˇ. Pokud je vstupnı´ pole jednorozmeˇrne´ dostaneme vektor o de´lce jedna (pozor – to je neˇco jine´ho nezˇ skala´r). Tato neprˇ´ıjemnost je jizˇ v jazyce Fortran95 odstraneˇna tı´m, zˇe jako druhy´ parametr funkce MINLOC uvedeme cˇ´ıslo indexu, ktery´ na´s zajı´ma´ a jako vy´sledek pak dosta´va´me skala´r. Prˇ´ıklad: REAL :: a(4) = (/1.2, INTEGER :: k,l(1) x = SUM(a) x = SUM(1+2*ABS(a)) x = PRODUCT(a) x = MAXVAL(a) l = MAXLOC(a) k = MAXLOC(a) k = MAXLOC(a,1)
3.6, -4.7, 2.2/), x ! ! ! ! ! ! !
vy ´sledek x = 2.3 vy ´sledek x = 27.4 vy ´sledek x = -44.6688 vy ´sledek x = 3.6 vy ´sledek l = (/2/) !! chyba - k nenı ´ pole vy ´sledek k = 2
Pro operace s maticemi a vektory jsou naprˇ´ıklad funkce: DOT PRODUCT(a,b) – skala´rnı´ soucˇin vektoru˚ a a b oba vektory musı´ mı´t stejnou de´lku MATMUL(a,b) – vyna´sobenı´ matic a a b pocˇet sloupcu˚ matice a se musı´ rovnat pocˇtu rˇa´dku˚ matice b TRANSPOSE(a) – vra´tı´ transponovanou matici a musı´ by´t dvojrozmeˇrna´ matice RESHAPE(a,tvar) – zmeˇna tvaru pole a – pole jehozˇ tvar se meˇnı´ tvar – jednorozmeˇrny´ celocˇ´ıselny´ vektor Za zmı´nku stojı´ prˇedevsˇ´ım funkce RESHAPE. Tato funkce umozˇnˇuje prˇeve´st naprˇ. jednorozmeˇrne´ pole na dvojrozmeˇrne´ nebo trˇeba matici 4×5 na 10×2. Pocˇet prvku˚ ve vstupnı´m a vy´stupnı´m poli by meˇl souhlasit. Tvar vy´sledne´ho pole je popsa´n druhy´m parametrem funkce, naprˇ. (/2,3/) je matice 2 × 3, (/10/) je desetiprvkovy´ vektor. Prˇi transformaci se postupuje po sloupcı´ch (prvnı´ index se meˇnı´ nejrychleji). Te´to funkce se nejcˇasteˇji pouzˇ´ıva´ prˇi inicializaci vı´cerozmeˇrne´ho pole. Prˇ´ıklady: 49
11
Pole II
INTEGER :: b(2,3)=RESHAPE((/1,2,3,4,5,6/),(/2,3/)) ! ! INTEGER :: c(3,2)=RESHAPE((/1,2,3,4,5,6/),(/3,2/)) ! ! ! INTEGER :: l(2) c = RESHAPE(b,(/3,2/)) l = MAXLOC(b) ! vy ´sledek l = (/2,3/)
11.4
1 2 1 2 3
3 5 4 6 4 5 6
Dynamicke´ alokace
Pole, se ktery´mi jsme se doposud setkali, meˇla doprˇedu zna´mou velikost. Stejneˇ jako v jiny´ch programovacı´ch jazycı´ch (naprˇ. v jazyce C) existuje i ve Fortranu mozˇnost dynamicke´ alokace polı´. Pokud chceme velikost pole urcˇit azˇ za beˇhu programu, uvedeme prˇi jeho deklaraci specifikaci ALLOCATABLE a mı´sto velikosti uvedeme pro kazˇdy´ rozmeˇr jen dvojtecˇku. Samotna´ alokace pameˇti se prova´dı´ prˇ´ıkazem ALLOCATE. Jako parametr se uvede identifika´tor pole s pozˇadovany´mi rozmeˇry. Pameˇt’se uvolnˇuje prˇ´ıkazem DEALLOCATE. Zda bylo jizˇ pole alokova´no lze zjistit funkcı´ ALLOCATED. INTEGER,ALLOCATABLE :: a(:) INTEGER :: n READ(*,*) n a(1)=3 ! chyba - pole jes ˇte ˇ nebylo alokova ´no ALLOCATE(a(0:n)) a(n)=3 ... IF (ALLOCATED(a)) then DEALLOCATE(a) ALLOCATE(a(10)) ENDIF ... DEALLOCATE(a) ´ koly U 1. Naplnˇte pole A o 10 prvcı´ch postupneˇ hodnotami od 10 do 19 a pole B o 10 prvcı´ch hodnotami sestupneˇ od 50 do 41. Secˇteˇte obeˇ pole a vytiskneˇte vy´sledek. 2. Naplnˇte jednorozmeˇrne´ pole o 100 prvcı´ch na´hodny´mi cˇ´ısly od 1 do 1000. Zdvojna´sobte prvnı´ch 50 prvku˚ pole. Vytvorˇte z pole matici typu 10 × 10. Zjisteˇte nejmensˇ´ı a nejveˇtsˇ´ı prvky pole a jejich umı´steˇnı´ v poli. Zjisteˇte soucˇet vsˇech prvku˚ a jejich pru˚meˇrnou hodnotu. 50
11
Pole II
3. Nacˇteˇte z kla´vesnice cela´ cˇ´ısla N a M . Osˇetrˇete vstup tak, aby obeˇ cˇ´ısla byla v rozsahu od 1 do 6. Dynamicky alokujte matici A typu N × M a vektor x o M prvcı´ch. Nacˇteˇte do te´to matice i do vektoru hodnoty (z kla´vesnice). Vyna´sobte matici A (maticoveˇ) vektorem x a vy´sledek ulozˇte do vektoru y (kolik prvku˚ bude mı´t tento vektor?). Vytiskneˇte matici A a vektory x a y. Dealokujte matici a vektory.
51
11
Pole II
52
12
Grafika
Grafika nenı´ standardnı´ soucˇa´stı´ jazyka. To, co si uvedeme v te´to kapitole platı´ pouze pro Visual Fortran v prostrˇedı´ operacˇnı´ho syste´mu Windows. Pokud chceme pouzˇ´ıvat grafiku je trˇeba vybrat projekt s na´zvem Fortran Standard or QuickWin Application, a potom podtyp Standard Graphics. Vznikly´ program bude vypadat velice podobneˇ jako konzolova´ aplikace, kterou jsme pouzˇ´ıvali doposud, pouze okno je veˇtsˇ´ı a lze meˇnit jeho velikost. Abychom mohli pouzˇ´ıvat graficke´ prˇ´ıkazy je trˇeba na zacˇa´tku programu (hned za rˇa´dkem PROGRAM ...) uve´st prˇ´ıkaz USE DFLIB, nebo u starsˇ´ıch kompila´toru˚ USE MSFLIB. Pro grafiku existuje cela´ rˇada prˇ´ıkazu˚. Ukazˇme si neˇkolik za´kladnı´ch. Prvnı´ skupina prˇ´ıkazu˚ pracuje s celocˇ´ıselny´mi sourˇadnicemi obrazovkovy´ch bodu˚ (pixelu˚). Prvnı´ sourˇadnice (x) urcˇuje porˇadı´ bodu od leve´ho okraje obrazovky. Druha´ sourˇadnice (y) urcˇuje porˇadı´ bodu od hornı´ho okraje. Body se v obou smeˇrech cˇ´ıslujı´ od nuly. res = SETPIXEL(x,y) Nakreslı´ bod. INTEGER x,y – sourˇadnice bodu INTEGER(2) res res = LINETO(x,y) Nakreslı´ cˇa´ru z aktua´lnı´ pozice do zadane´ho bodu. INTEGER x,y – sourˇadnice koncove´ho bodu INTEGER(2) res CALL MOVETO(x,y,xy) Nastavı´ aktua´lnı´ pozici do zadane´ho bodu. INTEGER x,y – sourˇadnice bodu TYPE(xycoord) xy – promeˇnne´ uzˇivatelske´ho typu (viz. kapitola xx), pro na´s nenı´ du˚lezˇita´ Na´vratove´ hodnoty neˇktery´ch funkcı´ (res) nejsou pro na´s du˚lezˇite´. Nynı´ si jizˇ mu˚zˇeme uka´zat jednoduchy´ graficky´ program – nakreslenı´ cˇtverce s bodem uprostrˇed. PROGRAM ctverec USE dflib IMPLICIT NONE INTEGER :: sx,sy,l INTEGER :: r TYPE(xycoord) cxy sx = 200 sy = 100 l = 50
! sour ˇadnice str ˇedu ! sour ˇadnice str ˇedu ! polovina de ´lky strany
53
12
Grafika
r = setpixel(sx,sy) ! bod do str ˇedu CALL moveto(sx+l, sy+l, cxy) ! c ˇtverec r = lineto(sx-l, sy+l) r = lineto(sx-l, sy-l) r = lineto(sx+l, sy-l) r = lineto(sx+l, sy+l) READ(*,*) END PROGRAM Rozlisˇenı´ obrazovky v bodech lze zjistit pomocı´ prˇ´ıkazu GETWINDOWCONFIG, viz na´sledujı´cı´ ko´d: TYPE (windowconfig) msc INTEGER :: res res=GETWINDOWCONFIG(msc) WRITE(*,*) ’s ˇı ´r ˇka obrazovky : ’,msc%numxpixels WRITE(*,*) ’vy ´s ˇka obrazovky : ’,msc%numypixels Prˇedchozı´ prˇ´ıkazy pracovaly s jednotlivy´mi pixely. Prˇi kreslenı´ naprˇ´ıklad grafu funkce vsˇak veˇtsˇinou chceme pracovat s rea´lny´mi sourˇadnicemi o zadane´m rozsahu. I toto Digital Fortran umozˇnˇuje. Prˇedchozı´ prˇ´ıkazy majı´ jesˇteˇ tvar, kdy se sourˇadnice zada´vajı´ jako rea´lna´ cˇ´ısla: res = SETPIXEL W(x,y) Nakreslı´ bod. REAL(8) x,y – sourˇadnice bodu INTEGER(2) res res = LINETO W(x,y) Nakreslı´ cˇa´ru z aktua´lnı´ pozice do zadane´ho bodu. REAL(8) x,y – sourˇadnice koncove´ho bodu INTEGER(2) res CALL MOVETO W(x,y,xy) Nastavı´ aktua´lnı´ pozici do zadane´ho bodu. REAL(8) x,y – sourˇadnice bodu TYPE(wxycoord) xy – promeˇnne´ uzˇivatelske´ho typu (viz. kapitola xx), pro na´s nenı´ du˚lezˇita´ Jak je videˇt na´zvy se lisˇ´ı prˇidany´m W na konci. Sourˇadnice jsou rea´lne´ a ne celocˇ´ıselne´. Pozor na zmeˇnu typu u MOVETO. Sourˇadnice bodu˚ nemajı´ u teˇchto prˇ´ıkazu˚ vztah k obrazovkovy´m bodu˚m, ale jejich rozsah je trˇeba nastavit. Pro nastavenı´ rozsahu je prˇ´ıkaz res = SETWINDOW(dir,x0,y0,x1,y1) Nastavı´ rozsah rea´lny´ch sourˇadnic. REAL(8) x0,y0 – sourˇadnice leve´ho dolnı´ho rohu REAL(8) x1,y1 – sourˇadnice prave´ho hornı´ho rohu 54
12
Grafika
LOGICAL dir – smeˇr osy y, .TRUE. – zezdola nahoru, .FALSE. – zezhora dolu INTEGER(2) res Na´sledujı´cı´ uka´zkovy´ program nakreslı´ graf funkce sinus. PROGRAM sinusovka USE dflib IMPLICIT NONE TYPE(wxycoord) cxy INTEGER :: r, i, n = 100 REAL :: x, xkon = 4*3.1415926 r = setwindow(.true., 0.0, -1.0, xkon, 1.0) CALL moveto_w(0.0_8,0.0_8,cxy) DO i=1,n x = xkon/n*i r = lineto_w(x,SIN(x)) ENDDO READ(*,*) END PROGRAM At’uzˇ pracujeme se sourˇadnicemi pixelu˚ cˇi s rea´lny´mi sourˇadnicemi, rˇada funkcı´ je spolecˇna´. Ty nejpouzˇ´ıvaneˇjsˇ´ı jsou: CALL CLEARSCREEN ($GCLEARSCREEN) Vymazˇe obrazovku. res = SETCOLOR(c) Nastavı´ barvu cˇ´ıslo c. INTEGER(2) c – cˇ´ıslo barvy (0 – cˇerna´, . . . , 15 – bı´la´) INTEGER(2) res res = SETCOLORRGB(c) Nastavı´ barvu RGB. INTEGER(4) c – libovolna´ barva INTEGER(2) res Mimo trˇ´ı za´kladnı´ch funkcı´ ktere´ jsme si uvedli existuje rˇada dalsˇ´ıch: res = RECTANGLE(typ,x0,y0,x1,y1) Nakreslı´ obde´lnı´k. INTEGER x0,y0 – levy´ dolnı´ roh INTEGER x1,y1 – pravy´ hornı´ roh INTEGER typ – $GBORDER – nakreslı´ jen obvod, $GFILLINTERIOR – vyplneˇny´ obde´lnı´k res = ELLIPSE(typ,x0,y0,x1,y1) Nakreslı´ elipsu. INTEGER x0,y0 – levy´ dolnı´ roh ohranicˇujı´cı´ho obde´lnı´ku INTEGER x1,y1 – pravy´ hornı´ roh ohranicˇujı´cı´ho obde´lnı´ku INTEGER typ – jako u obde´lnı´ku 55
12
Grafika
res = FLOODFILL(x,y,bc) Vyplnı´ oblast barvou. INTEGER x,y – bod uvnitrˇ oblasti INTEGER bc – cˇ´ıslo barvy hranice c = GETPIXEL(x,y) Zjistı´ barvu pixelu. INTEGER x,y – sourˇadnice bodu INTEGER c – cˇ´ıslo barvy CALL OUTGTEXT(str) Vypı´sˇe rˇeteˇzec na aktua´lnı´ pozici. CHARACTER(*) str – vypisovany´ rˇeteˇzec Prˇed pouzˇitı´m te´to funkce je trˇeba volat prˇ´ıkazy INITIALIZEFONTS a SETFONT res = INITIALIZEFONTS() Inicializuje graficke´ pı´smo. res = SETFONT(str) Vybere graficky´ font pro OUTGTEXT. CHARACTER(*) str – rˇeteˇzec popisujı´cı´ pozˇadovany´ ’t’’Arial’’h16w7’ viz na´poveˇda.
font,
naprˇ.
Uka´zky pouzˇitı´ uvedeny´ch prˇ´ıkazu˚ mu˚zˇete najı´t v programu GR DEMO.F90. Uvedene´ prˇ´ıkazy majı´ i varianty pracujı´cı´ s rea´lny´mi sourˇadnicemi. ´ koly U 1. Napisˇte program, ktery´ zobrazı´ funkci y = cos x v intervalu h−2π, 2πi vcˇetneˇ sourˇadnicovy´ch os, znacˇek a popisku˚. 2. Napisˇte program, ktery´ bude na obrazovku na na´hodna´ mı´sta zobrazovat na´hodne´ geometricke´ tvary vyplneˇne´ na´hodny´mi barvami.
56
13
Moduly
Jazyk Fortran umozˇnˇuje rozdeˇlit program do mensˇ´ıch celku˚ tzv. modulu˚. Moduly by meˇly by´t pokud mozˇno samostatne´ a vı´cena´sobneˇ pouzˇitelne´ jednotky. Prˇi tvorbeˇ veˇtsˇ´ıho programu bychom se meˇli snazˇit rozdeˇlit program do samostatny´ch celku˚. Tento tzv. modula´rnı´ prˇ´ıstup ma´ rˇadu vy´hod. Modul lze ladit a zkousˇet postupneˇ, lokalizace chyb je potom jednodusˇsˇ´ı. Hlavnı´ vy´hodou ale je, zˇe prˇi vhodne´m na´vrhu lze moduly pouzˇ´ıvat vı´cekra´t. Prˇ´ıkladem modulu, se ktery´m jsme se jizˇ setkali, je modul pro pra´ci s grafikou. Rˇadu uzˇitecˇny´ch modulu˚ lze zı´skat i z internetu – modul pro pra´ci s libovolneˇ prˇesny´mi rea´lny´mi cˇ´ısly, modul pro tvorbu postscriptovy´ch souboru˚. Jednotlive´ moduly je vhodne´ umist’ovat do samostatny´ch souboru˚, opeˇt s koncovkou .f90. Modul je velice podobny´ programu, ale s neˇkolika rozdı´ly: • Zacˇ´ına´ MODULE mı´sto PROGRAM. • Koncˇ´ı END MODULE mı´sto END PROGRAM. • Nesmı´ obsahovat zˇa´dne´ vy´konne´ prˇ´ıkazy mezi deklaracemi a CONTAINS. Do modulu mu˚zˇeme umist’ovat podprogramy nebo promeˇnne´. Tyto mu˚zˇeme pouzˇ´ıvat v hlavnı´m programu nebo i v jine´m modulu. Pokud chceme modul pouzˇ´ıt, je trˇeba bezprostrˇedneˇ za prvnı´m rˇa´dkem (PROGRAM ... nebo MODULE ...) uve´st USE a na´zev modulu. Prˇ´ıklad modul s funkcı´ na vy´pocˇet mocniny. Soubor mod mocnina.f90 MODULE mod_mocnina IMPLICIT NONE INTEGER :: exponent CONTAINS FUNCTION f(x) REAL :: f,x INTEGER :: I f=x DO i=2,exponent f=f*x END DO END FUNCTION END MODULE Soubor test mocnina.f90 PROGRAM test_mocnina 57
13
Moduly
USE mod_mocnina IMPLICIT NONE exponent = 4 WRITE(*,*) f(1.24) END PROGRAM
! chceme pouz ˇı ´vat modul ! nastavı ´me velikost exponentu v modulu ! zavola ´nı ´ funkce z modulu
Vsˇechny promeˇnne´ a podprogramy z modulu lze pouzˇ´ıvat v libovolne´ nadrˇazene´ jednotce (modulu cˇi programu). Naopak ale promeˇnne´ a podprogramy z nadrˇazene´ jednotky nelze v modulu pouzˇ´ıvat. Tj. „Promeˇnne´ jsou videˇt pouze zezdola nahoru“. Pokud uvnitrˇ modulu chceme mı´t promeˇnne´ (podprogramy), ktere´ nejde zvencˇ´ı pouzˇ´ıt, mu˚zˇeme pro vybranou promeˇnnou pouzˇ´ıt specifikaci PRIVATE. Naopak pro promeˇnne´ prˇ´ıstupne´ zvencˇ´ı se pouzˇ´ıva´ specifikace PUBLIC. Pokud prˇed deklaracı´ promeˇnny´ch uvedeme samotne´ PRIVATE nebo PUBLIC vztahuje se na vsˇechny na´sledujı´cı´ deklarace. ´ koly U 1. Napisˇte modul, ktery´ bude definovat hodnoty globa´lnı´ch rea´lny´ch promeˇnny´ch a, b, c pro vy´pocˇet korˇenu˚ kvadraticke´ rovnice ax2 + bx + c = 0. Pouzˇijte tento modul v programu na rˇesˇenı´ kvadraticke´ rovnice (viz kapitola 5.1). 2. Napisˇte modul, ve ktere´m budou zahrnuty funkce vytvorˇene´ pro zmeˇnu velky´ch pı´smen v rˇeteˇzci na mala´, zmeˇnu maly´ch pı´smen v rˇeteˇzci na velka´ a vymaza´nı´ vsˇech mezer z rˇeteˇzce (viz kapitola 9). Tyto funkce pouzˇijte v programu, ktery´ bude tento modul pouzˇ´ıvat.
58
14 14.1
Parametry podprogramu˚ Podprogramy jako parametry
Neˇkdy by´va´ potrˇeba prˇedat podprogramu odkaz na jiny´ podprogram. Prˇ´ıkladem mu˚zˇe by´t podprogram pro vykreslenı´ grafu funkce, kdy je trˇeba urcˇit graf ktere´ funkce chceme vykreslovat. Fortran toto prˇeda´va´nı´ podprogramu˚ jako parametru˚ umozˇnˇuje. V hlavicˇce podprogramu uvedeme na´zev podprogramu, ktery´ chceme pouzˇ´ıvat uvnitrˇ podprogramu. Mı´sto typu tohoto identifika´toru, jako u ostatnı´ch promeˇnny´ch, uvedeme mezi INTERFACE a END INTERFACE zkra´ceny´ popis funkce. Uva´dı´me pouze prvnı´ a poslednı´ rˇa´dek podprogramu a specifikaci prˇeda´vany´ch parametru˚. PROGRAM fce_par IMPLICIT NONE WRITE(*,*) maximum(-1.0,6.0,f2) CONTAINS !=============================== FUNCTION maximum(a,b,f) REAL :: a,b,maximum INTERFACE FUNCTION f(x) REAL :: f,x END FUNCTION END INTERFACE INTEGER :: i ... ! viz pr ˇilozeny ´ program END FUNCTION !=============================== FUNCTION f2(x) REAL :: f2,x f2 = 3-(x-2)**2 END FUNCTION !=============================== END PROGRAM
14.2
Volitelne´ parametry
Cˇasto se setka´va´me s procedurami ktere´ mohou mı´t ru˚zny´ pocˇet parametru˚ (naprˇ. subroutina WRITE). Takove´ subroutiny mu˚zˇeme deklarovat sami. U parametru˚, ktere´ nemusı´ by´t vzˇdy prˇ´ıtomne´ (nepovinne´ parametry), uva´dı´me specifikaci OPTIONAL. Povinne´ parametry musı´ vzˇdy v hlavicˇce vzˇdy prˇed nepovinny´mi. Pokud prˇi vola´nı´ podprogramu uvedeme me´neˇ parametru˚, 59
14
Parametry podprogramu˚
dostane hodnotu pouze odpovı´dajı´cı´ pocˇet prvnı´ch nepovinny´ch parametru˚. Pokud chceme zadat nepovinny´ parametr, ktery´ nenı´ na uveden na zacˇa´tku, lze ho prˇi vola´nı´ podprogramu zadat ve tvaru identifika ´tor prome ˇnne ´ = hodnota. Pokud uvnitrˇ podprogramu chceme zjistit zda byl volitelny´ parametr zada´n, pouzˇijeme funkci PRESENT(prom). Tato funkce vracı´ .TRUE. pokud byl parametr zada´n. Prˇ´ıklad: PROGRAM vol_par IMPLICIT NONE CALL sub(1,2) CALL sub(1,2,3) CALL sub(1,2,d=4) CALL sub(a=2,c=4) ! chyba - chybı ´ b CONTAINS !=============================== SUBROUTINE sub(a,b,c,d) INTEGER :: a,b INTEGER, OPTIONAL :: c,d WRITE(*,’(”a=”,i3)’) a WRITE(*,’(”b=”,i3)’) b IF (PRESENT(c)) WRITE(*,’(”c=”,i3)’) c IF (PRESENT(d)) WRITE(*,’(”d=”,i3)’) d END SUBROUTINE !=============================== END PROGRAM ´ koly U 1. Vytvorˇte modul s neˇkolika ru˚zny´mi funkcemi (naprˇ. f1 = cos2 x, f2 = sin 2x, apod.). Nacˇteˇte z kla´vesnice promeˇnnou x a pomocı´ menu vyberte funkci, jejı´zˇ hodnotu v dane´m bodeˇ spocˇ´ıta´te. 2. Upravte program pro kreslenı´ grafu funkce kosinus (viz kapitola 12) tak, zˇe pomocı´ menu v u´vodu programu bude mozˇne´ si vybrat funkci, kterou na grafu zobrazı´te. Vyuzˇijte modul vytvorˇeny´ v prˇedchozı´m u´kolu. 3. Napisˇte podprogram, ktery´ bude mı´sto mezer v rˇeteˇzci doplnˇovat jine´ znaky. Znak, ktery´ se bude mı´sto mezer zapisovat, posˇlete jako volitelny´ parametr podprogramu. Pokud nebude volitelny´ parametr zada´n, doplnˇte rˇeteˇzec nulami. Tento podprogram otestujte v hlavnı´m programu.
60
15
Uzˇivatelsky´ typ
Mimo peˇti standardnı´ch typu˚ (INTEGER, REAL, COMPLEX, CHARACTER, LOGICAL) existuje dalsˇ´ı uzˇivatelsky definovany´ typ. Prˇedtı´m, nezˇ definujeme promeˇnne´ tohoto typu, je trˇeba definovat samotny´ typ. Definice typu zacˇ´ına´ TYPE nazev a koncˇ´ı END TYPE. Mezi teˇmito rˇa´dky definujeme jednotlive´ slozˇky typu, stejneˇ jako bychom deklarovali obycˇejne´ promeˇnne´. Naprˇ´ıklad TYPE datum INTEGER :: den,mesic,rok END TYPE TYPE osoba CHARACTER(30) :: jmeno LOGICAL :: muz TYPE(datum) :: narozen REAL :: plat END TYPE Pokud chceme deklarovat promeˇnnou TYPE(nazev typu). Naprˇ´ıklad
uzˇivatelske´ho
typu,
jako
typ
uva´dı´me
TYPE(datum) vcera, zitra TYPE(osoba) ja, vedouci, uklizecka Odkazy na jednotlive´ polozˇky se uva´deˇjı´ pomocı´ znaku procento %. Naprˇ´ıklad vcera%rok = 2002 ja%jmeno = ”Mu ¨ller Thu ¨rgau” ja%narozen%rok = 1212 Rˇada prˇekladacˇu˚ umozˇnˇuje pouzˇ´ıvat mı´sto znaku procento tecˇku (ja.narozen.rok = 1348). Tato mozˇnost ale nenı´ soucˇa´stı´ normy a neˇktere´ prˇekladacˇe ji nepodporujı´. Pro zachova´nı´ prˇenositelnosti zdrojove´ho ko´du je tedy lepsˇ´ı pouzˇ´ıvat %. Stejneˇ jako u ostatnı´ch typu˚ i uzˇivatelsky´ typ mu˚zˇeme pouzˇ´ıt pro sestavenı´ pole: TYPE(datum) svatky(20) Na jednotlive´ prvky tohoto pole odkazujeme podobneˇ: svatky(1)%rok = 2004 svatky(1)%mesic = 1 svatky(1)%den = 1 61
15
Uzˇivatelsky´ typ
Pro pohodlneˇjsˇ´ı zada´va´nı´ hodnot mu˚zˇeme vyuzˇ´ıt konstruktoru, ktery´ je prˇedstavova´n na´zvem typu a uvnitrˇ kulaty´ch za´vorek jsou jednotlive´ hodnoty (v pocˇtu a v porˇadı´ ve shodeˇ s definicı´ uzˇivatelske´ho typu): svatky(2) = datum(2004, 5, 1) Pokud chceme uzˇivatelsky´ typ vypsat na obrazovku, mu˚zˇeme vypsat bud’ jeho slozˇky, nebo najednou cely´ za´znam, naprˇ. PRINT *, svatky(1)%rok, svatky(1)%mesic, svatky(1)%den PRINT *, svatky(1) ! Tote ´z ˇ co pr ˇedchozı ´ r ˇa ´dek S uzˇivatelsky´mi typy jsme se jizˇ setkali prˇi pra´ci s grafikou – typy xycoord a windowconfig. Naprˇ´ıklad typ xycoord slouzˇ´ı pro uchova´nı´ sourˇadnic x a y na obrazovce a je definova´n takto: TYPE xycoord INTEGER(2) xcoord INTEGER(2) ycoord END TYPE xycoord
! sour ˇadnice x ! sour ˇadnice y
´ koly U 1. Definujte vlastnı´ typ kniha, ktery´ bude obsahovat za´znamy o knihovneˇ: evidencˇnı´ cˇ´ıslo, autor, na´zev, nakladatel, rok vyda´nı´, pocˇet vy´tisku˚ a zda je kniha zapu˚jcˇena (logicka´ promeˇnna´). Naplnˇte tento seznam hodnotami a zapisˇte je do souboru. 2. Upravte prˇedchozı´ program tak, zˇe se prˇi dalsˇ´ım vola´nı´ programu seznam nacˇtete ze souboru a pak se prˇipisujı´ dalsˇ´ı za´znamy. 3. Napisˇte program, ktery´ prˇedchozı´ seznam knih nacˇte ze souboru, serˇadı´ knihy abecedneˇ podle autora a setrˇ´ıdeˇny´ seznam opeˇt ulozˇ´ı do souboru. Vyuzˇijte funkce pro lexika´lnı´ porovna´va´nı´ rˇeteˇzcu˚: LGT, LLT poprˇ. LGE, LLE.
62
16
Fortran 77
Fortran 77 je prˇedcha´zejı´cı´ verze jazyka Fortran. Z dnesˇnı´ho hlediska se jedna´ jizˇ o nemodernı´ jazyk, ktery´ postra´da´ rˇadu potrˇebny´ch rysu˚ (dynamicke´ alokace, globa´lnı´ promeˇnne´, modula´rnı´ struktura) a pro dnesˇnı´ pouzˇitı´ ho nelze doporucˇit. V jazyce Fortran 77 je vsˇak napsa´no obrovske´ mnozˇstvı´ programu˚, zvla´sˇteˇ v matematicky´ch a fyzika´lnı´ch aplikacı´ch. Fortran 77 je nasˇteˇstı´ podmnozˇina Fortranu 90. Kompila´tory F90 by proto meˇly by´t schopny prˇekla´dat i jazyk F77. Je tedy trˇeba pasivneˇ rozumeˇt jazyku F77 a je trˇeba umeˇt prˇipojit zdrojovy´ ko´d v F77 k programu F90. Pro prˇipojenı´ stacˇ´ı ulozˇit ko´d s koncovkou .for a vlozˇit do projektu stejneˇ jako ko´d ve F90. Prvnı´ rozdı´lem mezi F90 a F77 je forma´lnı´ vzhled zdrojove´ho ko´du. Jazyk F77 byl pu˚vodneˇ zapisova´n na deˇrne´ sˇtı´tky, na kazˇdy´ sˇtı´tek jeden rˇa´dek programu. Z toho dodnes vyply´va´ na´sledujı´cı´ forma´t rˇa´dku. • Sloupce 1 azˇ 5 jsou vyuzˇ´ıva´ny pro na´veˇsˇtı´. • Pokud je v prvnı´m sloupci neˇktery´ ze znaku˚ ’*’, ’C’, ’c’, je cely´ rˇa´dek komenta´rˇ. • Sloupec 6 se norma´lneˇ nepouzˇ´ıva´. Pokud je v tomto sloupci jaky´koliv znak, je tento rˇa´dek pokracˇova´nı´m rˇa´dku prˇedchozı´ho. • Do sloupcu˚ 7 azˇ 72 se zapisujı´ vlastnı´ prˇ´ıkazy. Na kazˇde´m rˇa´dku mu˚zˇe by´t pouze jeden prˇ´ıkaz. Prostrˇedı´ MSDS podporuje psanı´ v tomto forma´tu viz obr. 5. Ve Fortranu 77 najdeme neˇkolik prˇ´ıkazu˚ a rysu˚, ktere´ jsou jizˇ povazˇova´ny za zastarale´ a nenı´ doporucˇeno je nada´le pouzˇ´ıvat. Z programa´torske´ho hlediska je trˇeba zavrhnout prˇ´ıkaz GOTO ve vsˇech svy´ch varianta´ch, ktery´ umozˇnˇuje nepodmı´neˇne´ skoky na jina´ mı´sta v programu oznacˇena´ na´veˇsˇtı´m. Fortran 90 jizˇ zcela podporuje strukturova´nı´ programu a skoku˚m na jina´ mı´sta pomocı´ GOTO se lze vzˇdy vyhnout. Bohuzˇel, tento prˇ´ıkaz byl drˇ´ıve pouzˇ´ıva´n velice cˇasto, cozˇ vedlo ke znacˇne´ neprˇehlednosti rˇady programu˚ napsany´ch ve Fortranu 77. Dalsˇ´ım prˇ´ıkladem jsou bloky COMMON, ktere´ slouzˇ´ı pro ukla´da´nı´ dat a sdı´lenı´ globa´lnı´ch promeˇnny´ch. Pro globa´lnı´ promeˇnne´ je dnes daleko lepsˇ´ı pouzˇ´ıt modul, ve ktere´m jsou spolecˇneˇ umı´steˇny. Podrobneˇ popisuje Fortran 77 kniha [1], kde mu˚zˇeme nale´zt jesˇteˇ neˇkolik dalsˇ´ıch prˇ´ıkazu˚, jejichzˇ pouzˇitı´ dnes jizˇ nenı´ nutne´. Jelikozˇ Fortran 77 je podmnozˇinou Fortranu 90, nalezneme tyto prˇ´ıkazy i v na´poveˇdeˇ a dokumentaci kompila´toru˚ Fortran 90.
63
16
Fortran 77
Obra´zek 5: Ko´d ve Fortranu 77
64
Literatura [1] Hrˇebı´cˇek, J., Kopecˇek, I., Kucˇera, J., Polcar, P.: Programovacı´ jazyk FORTRAN 77 a veˇdeckotechnicke´ vy´pocˇty. Academia, Praha, 1989. [2] Marshall, A.C.: Fortran 90 Course Notes. The University of Liverpool, 1997. [3] Metcalf, M., Reid, J.: Fortran 90 Explained. Oxford University Press, 1992.
65