obsah - ujepphysics.ujep.cz/~mlisal/fortran-chomutov/mvicher_fortran.pdf · 2014-02-01 · 2...

65
Obsah 1 U ´ vod 5 2 Fortran ve Windows a v Linuxu 7 2.1 Windows – Prostr ˇedı ´ MSDS ............................ 7 2.2 Linux – Intel Fortran ................................ 9 U ´ koly ........................................ 10 3 Za ´ klady syntaxe 11 Pr ˇı ´klady ....................................... 13 U ´ koly ........................................ 14 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 U ´ koly ........................................ 18 5 Pr ˇı ´kazy organizac ˇnı ´ 19 5.1 Podmı ´ne ˇny ´ pr ˇı ´kaz .................................. 19 Pr ˇı ´klady ....................................... 20 U ´ koly ........................................ 20 5.2 Pr ˇı ´kazy cyklu .................................... 21 Pr ˇı ´klady ....................................... 22 U ´ koly ........................................ 24 5.3 Na ´hodna ´c ˇı ´sla .................................... 25 Pr ˇı ´klady ....................................... 25 U ´ koly ........................................ 25 5.4 Pr ˇı ´kaz CASE .................................... 26 1

Upload: others

Post on 03-Mar-2020

10 views

Category:

Documents


0 download

TRANSCRIPT

Obsah

1 Uvod 5

2 Fortran ve Windows a v Linuxu 7

2.1 Windows – Prostredı MSDS . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7

2.2 Linux – Intel Fortran . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10

3 Zaklady syntaxe 11

Prıklady . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14

4 Typy promennych 15

4.1 Typy INTEGER a REAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

4.2 Prevody typu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15

4.3 Typ COMPLEX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

4.4 Typ LOGICAL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

4.5 Typ CHARACTER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18

5 Prıkazy organizacnı 19

5.1 Podmıneny prıkaz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19

Prıklady . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20

5.2 Prıkazy cyklu . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

Prıklady . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24

5.3 Nahodna cısla . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

Prıklady . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

5.4 Prıkaz CASE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26

1

Obsah

Prıklady . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27

6 Pole I 29

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30

7 Vstup a vystup, format 31

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33

8 Retezce 35

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

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 Retezce . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

9.4.3 Popis INTENT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42

10 Prace se soubory 43

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46

11 Pole II 47

11.1 Konstrukce polı . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47

11.2 Casti pole . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

11.3 Standardnı podprogramy pro pole . . . . . . . . . . . . . . . . . . . . . . . . . 48

11.4 Dynamicke alokace . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50

2

Obsah

12 Grafika 53

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56

13 Moduly 57

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58

14 Parametry podprogramu 59

14.1 Podprogramy jako parametry . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

14.2 Volitelne parametry . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

15 Uzivatelsky typ 61

Ukoly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62

16 Fortran 77 63

Literatura 65

3

Obsah

4

1 Uvod

V techto skriptech se pokusıme vysvetlit zaklady jazyka Fortran 90. Predchazejıcı verze tohotojazyka Fortran 77 bude zmınena jen okrajove. Vetsina toho, co bude uvedeno v techto skriptech,platı pro libovolny kompilator jazyka Fortran, ale pri praktickem programovanı je treba pracovat skonkretnım kompilatorem. V techto skriptech budeme jako prıklad pouzıvat kompilator CompaqVisual Fortran 6.6 (nebo jeho velice podobne predchudce Digital Visual Fortran 5.0 a MicrosoftFortran 4.0) a kompilator Intel Fortran Compiler 7.0.

Jazyk Fortran je jednım z nejstarsıch programovacıch jazyku. Je to jazyk, ktery byl a je urcenpredevsım pro vedecko-technicke vypocty. V tomto jazyce bylo naprogramovano velke mnozstvınumerickych knihoven, ktere byly dokonale odladeny a neobsahujı tedy zadne chyby. Navıc jeovladnutı jazyka ve verzi Fortran 90 pomerne jednoduche.

Tento text obsahuje pouze zakladnı prvky jazyka Fortran 90. Predpokladame, ze pokud si studentosvojı jazyk na urovni techto skript, bude schopen si jiz dalsı podrobnosti tykajıcı se presnesyntaxe, standardnıch funkcı nebo nekterych pokrocilych rysu tohoto jazyka, nastudovat sam zapomoci napovedy a dokumentace, ktera je vzdy soucastı daneho kompilatoru. Dalsım zdrojeminformacı je internet, predevsım pak stranky vyucujıcıho (jejich adresa se muze menit, proto budevzdy uvedena na pocatku semestru). Zde bude mozne nalezt radu odkazu na studijnı materialy avzorove programy (na nektere z nich se odkazuje i prımo v tomto textu).

Aby si ctenar latku osvojil, je ovsem zapotrebı samostatne naprogramovat co nejvıce prıkladua splnit vsechny ukoly. Programovanı se nelze nenaucit jinak nez programovanım. Proto takedoporucujeme studentum pracovat maximalne samostatne, nebot’cılem nenı jen programy pru-bezne odevzdavat, ale programovanı ovladat jako jeden z nastroju jejich budoucı prace. Pritomnezalezı tolik na tom, zda budete Fortran pouzıvat ve Vası budoucı praci. Radu vlastnostı jazykaFortran 90 najdete i v jinych programovacıch jazycıch a naucıte-li se jeden programovacı jazyk,ovladnutı dalsıho Vas jiz nebude stat tolik usilı.

5

1 Uvod

6

2 Fortran ve Windows a v Linuxu

2.1 Windows – Prostredı MSDS

Kompilator Compaq Visual Fortran 6.6 vyuzıva vyvojove prostredı Microsoft Developer Studio.Toto prostredı umoznuje psat, spoustet a ladit programy, je vyuzıvano nejen jazykem Fortran, alei jazykem Microsoft Visual C++ a dalsımi.

Pri praci v tomto prostredı je treba nejprve vytvorit tzv. projekt. Projekt obsahuje informace o tom,ze kterych souboru se ma vytvaret vysledny program a dalsı nastavenı. Projekt v MSDS vytvorımevyberem menu File→New→Projects, pote je treba vybrat typ projektu. Pokud nepotrebujemepracovat s grafikou, vybereme projekt Fortran Console Application, az budeme pozdeji pracovat sgrafikou, vybereme projekt Fortran Standard or QuickWin Application. V prave casti dialogovehookna vyplnıme do Project name nazev projektu (tj. i nazev vysledneho programu) a do Locationmısto na disku, kam se ma projekt ulozit. Prostredı vytvorı pro kazdy projekt novy adresar, doktereho se budou umıst’ovat zdrojove texty a take vysledny program.

Obrazek 1: Vytvorenı projektu

Po vytvorenı projektu je treba vytvorit zdrojove texty. To lze nejjednoduseji provest ikonou New

7

2 Fortran ve Windows a v Linuxu

Text File a ulozenım souboru pod libovolnym nazvem s koncovkou .f90. Souboru muze bytlibovolne mnozstvı. Po vytvorenı souboru je treba urcit, ktere soubory patrı do daneho projektu.V menu vybereme Project→Add to Project→Files a pote vybereme potrebne soubory. Soubory,ktere jsou skutecne obsazeny v projektu jsou videt v leve casti okna MSDS v Source Files.

Obrazek 2: Hotovy projekt s vlozenym zdrojovym textem

Program musıme prelozit („zkompilovat“), coz provadıme tak, ze v menu vybereme Build→Build{nazev programu}, nebo stiskneme klavesu F7. Program spustıme bud’uvnitr vyvojoveho pro-stredı pomocı Build→Execute {nazev programu}, nebo samostatne na prıkazove radce systemuWindows napıseme jmeno prelozeneho programu (tedy souboru s koncovkou .exe) v adresari,kam se tento spustitelny soubor ulozil. Rovnez je mozne spustit program z vyvojoveho prostredıstiskem kombinace klaves Ctrl+F5.

Shrnutı postupu:

• Vytvorenı projektu

• Vytvorenı zdrojovych souboru

• Prirazenı souboru do projektu

8

2 Fortran ve Windows a v Linuxu

2.2 Linux – Intel Fortran

Narozdıl od MSDS je Intel Fortran radkovy prekladac a prace s nım je mene komfortnı. Na druhestrane nenı nutne zakladat zadny projekt jako v MSDS a zdrojovy kod lze rovnou prelozit aprogram spustit.

Obrazek 3: Zdrojovy kod v programu KWrite

Obrazek 4: Preklad a spustenı programu hello

9

2 Fortran ve Windows a v Linuxu

Zdrojovy kod muzeme vytvorit v libovolnem textovem editoru (napr. KWrite nebo Emacs). Predsamotnym prekladem je treba hotovy kod ulozit na pevny disk do souboru s obvyklou prıponou.f90. Preklad spustıme prıkazem

ifc -o nazev programu zdrojovy kod.f90,

od verze prekladace Intel Fortran Compiler for Linux 8.0 pak prıkazem

ifort -o nazev programu zdrojovy kod.f90,

ktery zadavame v konzolovem okne. Samotny program pak spustıme zadanım nazvu programuna prıkazove radce.

Shrnutı postupu:

• Vytvorenı zdrojoveho kodu – obycejny textovy soubor prıponou .f90

• Prelozenı kodu radkovym prekladacem

• Spustenı programu

Ukoly

1. Vytvorte program pomocı jednoho z predchozıch postupu. Do zdrojoveho kodu napiste:

PROGRAM HELLOIMPLICIT NONEWRITE(*,*) ”Hello”END PROGRAM

Program zkompilujte a spust’te.

2. Seznamte se pomocı napovedy (na disku pocıtace i na internetu) a dostupne dokumentaces kompilatorem a vyvojovym prostredım, se kterym budete dale pracovat.

10

3 Zaklady syntaxe

Zakladnı poznamky:

• Nerozlisujı se mala a velka pısmena, tj. Muzeme napsat PROGRAM, program i Program.Totez se tyka i jmen promennych – pokud promennou definujeme jako N, muzeme na niodkazovat i jako n (z duvodu prehlednosti programu je vsak vhodne pouzıvat promennoutak, jak byla definovana).

• Komentar je cokoliv co nasleduje po znaku vykricnık ! az do konce radku. Neexistujevıceradkovy komentar.

• Na kazdem radku je jen jeden prıkaz, ktery se neukoncuje strednıkem. Pokud je na radkuvıce prıkazu, pıseme strednık mezi ne.

• Pokud se prıkaz nevejde na radek, lze ho rozdelit na vıce radku. Na konci radku, kterenejsou poslednı, je treba uvadet znak &.

• Soubor ma vetsinou koncovku .f90.

Nekolik zakladnıch pravidel:

• Kazdy program zacına klıcovym slovem PROGRAM za kterym nasleduje jednoslovny nazevprogramu.

• Jako druhy radek vzdy uvadejte IMPLICIT NONE. Tento prıkaz nenı sice nezbytne nutneuvadet, ale pokud jej uvedeme, mame zarucenu duslednou kontrolu typu promennych –vsechny promenne musı byt deklarovany v uvodu programove jednotky, jinak dojde kchybove hlasce kompilatoru.

• Program koncı slovem END nebo lepe END PROGRAM, za kterym volitelne muze nasle-dovat i nazev programu.

• Mısto END PROGRAM muzeme psat ENDPROGRAM. Podobne je to i s ostatnımi prıkazy,ktere jsou slozeny ze dvou slov, napr. mısto END IF muzeme psat i ENDIF apod.

• Privolanı podprogramu je treba pred jeho nazvem uvest CALL.

Nejjednodussı program vypada tedy treba takto (samozrejme vubec nic nedela):

PROGRAM PRVNI_PROGRAMIMPLICIT NONEEND PROGRAM

11

3 Zaklady syntaxe

Zakladnım prvkem jazyka jsou promenne. Identifikator promenne muze obsahovat pısmena,cıslice a znak podtrzıtko, musı ale zacınat pısmenem. Nerozlisujı se mala a velka pısmena.Promenne mohou mıt nektery ze sesti typu, napr. cela cısla majı typ INTEGER, realna majı typREAL, znaky a retezce majı typ CHARACTER. Pri deklaraci promenne se nejdrıve uvede typ a zanım nasledujı identifikatory oddelene carkami. Naprıklad

INTEGER IREAL A,BCHARACTER C

Promenne nemajı definovanou zadnou pocatecnı hodnotu. Pocatecnı hodnotu vsak muzeme zadatpomocı =. Specifikaci typu a promenne je vsak treba oddelit dvojicı dvojtecek. Naprıklad

INTEGER :: I=0REAL :: PI=3.1415926535, x=1.0CHARACTER :: CH=’x’

Dvojtecky muzeme psat volitelne i v prıpade, ze se pocatecnı hodnoty nezadavajı a v nasledujıcımtextu tak budeme zpravidla cinit. Pokud promenna nema menit svojı hodnotu (konstanta), uvedese za specifikaci typu dalsı specifikace PARAMETER. Naprıklad

REAL, PARAMETER :: PI=3.1415926535897932384626433832795INTEGER, PARAMETER :: N = 100, M = 3CHARACTER, PARAMETER :: plus = ’+’

Zakladnım zpusobem prace s promennymi jsou prirazovacı prıkazy. Znak pro prirazenı je =,zakladnı aritmeticke operatory jsou+ - * /. Pomocı operatoru** lze umocnovat. Lze pouzıvatradu standardnıch funkcı naprıklad SIN, COS nebo SQRT pro odmocninu. Parametry funkcı sezadavajı do kulatych zavorek. Vsechny deklarace promennych musı predchazet vsem prıkazum.Vsechny promenne je treba deklarovat.

PROGRAM DRUHY_PROGRAM ! Toto je prvnı komentar! Toto je take komentarIMPLICIT NONE ! nic nenı deklarovano dopreduINTEGER :: I ! celocıselna promenna IREAL :: x,y,z ! realne promenne x,y,zREAL :: Z ! chyba, Z jiz bylo definovanox = y + zz = 1234*i ! v poradku, i je totez co Iz = SIN(y)y = SQRT(X)x = i**3 ! totez co x = i*i*i

12

3 Zaklady syntaxe

INTEGER :: n ! chyba, deklarace musı byt pred prıkazyy = SIN(3.14/2)i = -j ! chyba j nebylo deklarovanoEND PROGRAM

Zakladnı prıkazem pro vypis promenne nebo vyrazu na obrazovku je prıkaz WRITE(*,*). Zatımto prıkazem nasledujı vypisovane vyrazy, ktere oddelujeme carkou. Naprıklad

WRITE(*,*) IWRITE(*,*) x+y, z

Kazdy prıkaz WRITE vypıse jeden radek. Prıkaz bude podrobneji vysvetlen pozdeji, nynı jenstrucne poznamenejme, ze prvnı hvezdicka zarıdı vystup na obrazovku, druha specifikuje, zeformatovanı vystupu je volne a zarıdı jej sam jazyk Fortran.

Podobne, ale pro ctenı, funguje prıkaz READ. Tento prıkaz nacte udaje zadane z klavesnice dopromennych. Naprıklad

READ(*,*) IREAD(*,*) x, yREAD(*,*) x+y ! chyba - precıst lze jen promennou, nikoli vyraz

Dalsım casto pouzıvanym typem jsou retezce. Pro zacatek vystacıme s konstantnım retezcem,ktery se uvadı jako text uzavreny do uvozovek nebo do apostrofu, naprıklad”abc” nebo’Uplnecokoliv.’. Mezi uvozovkami a apostrofy nenı zadny rozdıl. Vyznam hvezdicek je podobnyjako u prıkazu WRITE.

Prıklady

Prıklad: klasicky program pro vypsanı retezce na obrazovku.

PROGRAM HALLOIMPLICIT NONEWRITE(*,*) ”Hallo World!”READ(*,*)END PROGRAM

Prıklad: jednoduchy program na resenı kvadraticke rovnice ax2 + bx+ c = 0.

PROGRAM ROVNICEIMPLICIT NONEREAL :: a,b,c ! koeficienty rovnice

13

3 Zaklady syntaxe

REAL :: x1,x2 ! vysledkyREAL :: d ! diskriminant

WRITE(*,*) ”zadej koeficienty a,b,c kvadraticke rovnice”READ(*,*) a,b,c ! nactenı koeficientud = b**2 - 4*a*c ! vypocet diskriminantux1 = ( -b + SQRT(d) )/(2*a) ! vypocet korenux2 = ( -b - SQRT(d) )/(2*a)WRITE(*,*) ’koreny jsou: ’,x1,x2 ! vypis korenuREAD(*,*) ! cekanı na stisk ENTEREND PROGRAM

Program po skoncenı prace vetsinou ihned skoncı. Aby si uzivatel stihl precıst udaje vypsane naobrazovku je treba na konec programu zaradit cekanı na stisk nejake klavesy. Toho lze dosahnouprıkazem READ(*,*) bez parametru, ktery pocka na stisk klavesy ENTER.

Poznamka: mısto WRITE(*,*) x muzeme psat PRINT *, x. Mısto READ(*,*) x mu-zeme psat READ *, x.

Ukoly

1. Prostudujte a vyzkousejte program:

PROGRAM VYPOCETIMPLICIT NONEINTEGER :: a, b, c ! deklarace, INTEGER

! ctenı z obrazovkyWRITE(*,*) ”Zadej a:”READ *,aWRITE(*,*) ”Zadej b:”READ *,b

! vypocetc=a+b

! tiskWRITE(*,*) ”a+b =”,cEND PROGRAM VYPOCET

2. Nactete z klavesnice dve realna cısla a vypiste jejich soucet, rozdıl, soucin a podıl.

3. Sestavte program pro vypocet povrchu a objemu pravidelneho sestibokeho hranolu.

4. Napiste program pro zamenu hodnot v promennych p a q. (Kolik dalsıch promennychbudete na tuto vymenu nutne potrebovat?)

14

4 Typy promennych

Fortran zna sest typu promennych: INTEGER, REAL, COMPLEX, CHARACTER, LOGICAL auzivatelsky definovany typ.

4.1 Typy INTEGER a REAL

Cela cısla majı typ INTEGER, realna cısla typ REAL. Prıkladem celych cısel jsou -1100, 0,1 nebo 33. Realna cısla musı mıt desetinnou tecku nebo exponent. Prıklady realnych cısel jsou.0, -1.10, +1E+30, 2E4, 1.12E-01 nebo 0.091. Znamenko plus je volitelne a nemusı seuvadet.

Za typem lze v kulatych zavorkach uvest presnost promenne. Vetsı hodnota odpovıda presnejsıpromenne. Mozne hodnoty zavisı na konkretnım prekladaci. U Visual Fortranu jsou moznehodnoty:INTEGER(1),INTEGER(2),INTEGER(4),INTEGER(8),REAL(4),REAL(8).U Intel Fortranu navıc i REAL(16). Cıslo v zavorce v tomto prıpade znamena pocet bytu, kterezabere promenna v pameti pocıtace. REAL(4) predstavuje jednoduchou presnost realnych cısel,REAL(8) presnost dvojitou, pro kterou se pouzıva tez oznacenı DOUBLE PRECISION.

Pri praci s realnymi a celocıselnymi promennymi je treba dat pozor na nekolik vecı:

Vysledkem vyrazu s celymi cısly je opet cele cıslo. Z toho plynou velice caste chyby, naprıklad1/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 presnosti, je treba sdelit tuto skutecnosti komplilatoru napr. tım, ze mısto symbolu pro exponent E pouzijeme pısmeno D. Vyse uve-dene prıklady realnych cısel zapıseme ve dvojite presnosti naprıklad takto: 0.0D0, -1.10D0,1D+30, 2D4, 1.12D-01 nebo 9.1D-02. Jednu polovinu tedy napıseme spravne naprıkladjako 1.D0/2.D0.

Nektere funkce predpokladajı, ze jejich parametr je realne a ne cele cıslo. Naprıklad SQRT(2) jechyba, SQRT(2.0) je spravne. Existujı i podobne standardnı funkce pracujıcı prımo ve dvojitepresnosti. Tyto funkce majı zpravidla jako prvnı pısmeno D, napr. DSQRT, DSIN, DCOS, apod.a jako parametr je vhodne samozrejme pouzıvat realne konstanty a realne promenne ve dvojitepresnosti.

4.2 Prevody typu

Cele cıslo na realne cıslo vetsinou nenı potreba prevadet, protoze prevod se uskutecnı automaticky.Napr.

REAL :: rr = 1

15

4 Typy promennych

Nekdy je vsak treba prevod explicitne uvest. To lze udelat pomocı prevodnı funkce REAL projednoduchou presnost popr. DBLE pro presnost dvojitou nebo vytvorenım jednoducheho realnehovyrazu.

INTEGER :: iWRITE(*,*) SQRT(REAL(i))WRITE(*,*) SQRT(1.0*i)WRITE(*,*) DSQRT(DBLE(i))WRITE(*,*) DSQRT(1D0*i)

Pri prevodu realneho cısla na cele je treba urcit jakym zpusobem zaohrouhlujeme. Mame k dis-pozici nekolik podobnych funkcı: INT – odrıznutı desetinne casti, NINT – nejblizsı cele cıslo,CEILING – zaokrouhlenı nahoru, FLOOR – zaokrouhlenı dolu.

4.3 Typ COMPLEX

Typ COMPLEX reprezentuje komplexnı promenne. Podobne jako u realnych promennych lze dokulatych zavorek uvest presnost promenne. Komplexnı konstanty se definujı tak, ze do kulatychzavorek uvedeme realnou a imaginarnı cast oddelene carkami, naprıklad komplexnı jednotka jex=(0,1). Takto je treba zapisovat komplexnı cıslo i v prıpade, ze jej nacıtame z klavesnicea takto je i vypsano prıkazem WRITE. Z realnych promennych lze vytvorit komplexnı pomocıfunkce CMPLX.

c = CMPLX(a,b)REAL a,b – realna a imaginarnı castCOMPLEX c – vysledne komplexnı cıslo

Obracene funkce REAL vratı realnou cast komplexnıho cısla a funkce AIMAG imaginarnı cast.Funkce CONJG vratı cıslo komplexne sdruzene a funkce ABS vratı absolutnı hodnotu.

Komplexnı cısla muzeme scıtat, odcıtat, nasobit i delit pouze za pomoci operatoru +, -, * a /,takze manipulace s komplexnımi cısly v jazyku Fortran je velmi jednoducha. Rovnez funkce jakonapr. SIN nebo LOG umoznujı jako parametr pouzıvat komplexnı cısla.

4.4 Typ LOGICAL

Promenna typu LOGICAL reprezentuje logickou hodnotu. Muze nabyvat pouze dvou hodnot ato pravda .TRUE. a nepravda .FALSE..

Logicke vyrazy lze vytvaret pomocı srovnavacıch (relacnıch) operatoru ==, >, <, >=, <=, /=.Pozor predevsım na operator „je ruzne od“ /=, ktery se lisı od jinych programovacıch jazyku,napr. od jazyka C. Ve vyrazech lze take pouzıvat radu logickych spojek. Vsechny tyto operatoryzacınajı a koncı teckou.

16

4 Typy promennych

Operator Logicky vyznam.AND. a zaroven.OR. nebo.NOT. neplatı.EQV. je ekvivalentnı.NEQV. nenı ekvivalentnı

Do promennych typu LOGICAL lze naprıklad priradit konstantu (k=.TRUE.), porovnanı cı-selnych promennych (k= a<b) nebo vyraz vytvoreny pomocı logickych operatoru (k= a<b.AND. c==0 .OR. k). Promenne tohoto typu se mohou vyskytovat v podmınce prıkazuIF() (viz kapitola 5.1). Napr.

REAL :: a, bLOGICAL :: kk = a < b! nasledujıcı je totezIF (k) ...IF (a < b) ...

Pri tisku nebo nacıtanı logicke promenne predstavuje hodnotu k=.TRUE. pısmeno T a hodnotuk=.FALSE. pısmeno F.

4.5 Typ CHARACTER

Promenne typu CHARACTER reprezentuje jeden znak. Pomocı tohoto typu se definujı i retezce,v tom prıpade za CHARACTER uvedeme do kulatych zavorek delku retezce, napr.

CHARACTER(15) :: s

je retezec, ktery ma 15 znaku. Totez muzeme zapsat i takto

CHARACTER(LEN=15) :: s

Retezce i znaky se uvadejı do zavorek nebo do apostrofu. Mezi zavorkami a apostrofy nenı rozdıl.Retezec, ktery zacına uvozovkami musı i uvozovkami koncit, stejne je to s apostrofy. Toho lzevyuzıt pro retezec obsahujıcı treba apostrof. Napr.

CHARACTER :: cCHARACTER(5) :: sc = ’a’c = ”a”s = ’ahoj!’s = ”Can’t”

Podrobneji bude o retezcıch pojednano v kapitole 8.

17

4 Typy promennych

Ukoly

1. Prostudujte, zda program

PROGRAM VypocetIMPLICIT NONEINTEGER :: aI=5, bI=3, cIREAL :: aR=5.0, bR=3.0, cR! Prvni vypocet a tiskcI=aI/bIcR=aR/bRPRINT *, ”cI=aI/bI=”, cIPRINT *, ”cR=aR/bR=”, cR! Druhy vypocet a tiskcI=aR/bRcR=aI/bIPRINT *, ”cI=aR/bR=”, cIPRINT *, ”cR=aI/bI=”, cREND PROGRAM Vypocet

dava vysledky, jake byste ocekavali. Pokud ne, uvedomte si rozdıl mezi typy INTEGER aREAL a mezi celocıselnym a realnym delenım.

2. Vyzkousejte funkce INT, NINT, CEILING a FLOOR na realnych cıslech −2.5 a 2.5.

3. Nactete z klavesnice promennou a typu REAL a promenne b a c typu COMPLEX. Proved’teoperace a ∗ b− c, b+ a ∗ c, b ∗ c a b/c. Vysledky vypiste na obrazovku.

4. Nactete z klavesnice hodnoty dvou logickych promennych L1 a L2, proved’te s nimi po-stupne logicke operace .AND., .OR., .NOT., .EQV. a .NEQV. a vytisknete prehlednevysledky techto operacı, napr. takto

L1= TL2= FL1 .AND. L2 = FL1 .OR. L2 = T.NOT. L1 = F.NOT. L2 = TL1 .EQV. L2 = FL1 .NEQV. L2 = T

5. Napiste program, ktery se postupne zepta na Vase jmeno, datum, mısto narozenı a Vasezaliby. Po obdrzenı jednotlivych informaci program pro kontrolu tyto informace vypıse naobrazovku.

18

5 Prıkazy organizacnı

5.1 Podmıneny prıkaz

Prvnı organizacnı prıkaz je podmıneny prıkaz. Je ho zakladnı forma je

IF (logicky_vyraz) THENprıkazy

ELSEprıkazy

END IF

Mısto END IFmuzeme psat take ENDIF, mezera zde nemusı byt. Cast ELSE lze vypustit, zbydepouze:

IF (logicky_vyraz) THENprıkazy

END IF

Pokud chceme vykonat pouze jediny prıkaz, lze THEN a ENDIF vynechat:

IF (logicky_vyraz) prıkaz

Prıkazy IF lze retezit ve tvaru:

IF (logicky_vyraz1) THEN...

ELSE IF (logicky_vyraz2) THEN...

ELSE...

END IF

Podmınky mohou byt i vıcenasobne vnorene, napr.

IF (logicky_vyraz1) THEN...IF (logicky_vyraz2) THEN

...ELSE

...END IF

19

5 Prıkazy organizacnı

ELSE...

END IF

O jednoznacne prirazenı prıkazu ELSE k prıslusnemu IF se vzdy postara umıstenı prıkazu ENDIF, ktere uzavıra blok s podmınkou. Je vzdy velice vhodne vnorene podmınky odsadit, aby ivizualne pri ctenı programu bylo hned patrne, ktera cast programu je vnorena a tvorı vnitrnı castjine podmınky.

Nejcastejsı chybou je zapomenutı zavorek, slova THEN nebo pouzitı END mısto ENDIF. Mezerymezi klıcovymi slovy nejsou dulezite a lze pouzıvat ENDIF i END IF, ELSEIF i ELSE IF.

Prıklady

Prıklad: zjistenı znamenka zadaneho cısla

INTEGER :: aREAD(*,*) aIF (a>0) THEN

WRITE(*,*) ”cislo je kladne”ELSE IF (a<0) THEN

WRITE(*,*) ”cislo je zaporne”ELSE

WRITE(*,*) ”cislo je nula”END IF

Prıklad: zjistenı, zda obe cısla jsou kladna a zda jsou obe nenulova. Podmınene prıkazy mohoubyt i vnorene.

INTEGER a,bREAD(*,*) a,bIF (a>0 .AND. b>0) WRITE(*,*) ”obe cisla jsou kladna”IF (b/=0) THEN

IF (a/=0) THENWRITE(*,*) ”obe cisla jsou nenulova”

END IFEND IF

Ukoly

1. Prepiste nasledujıcı vnorenou podmınku tak, abyste pouzili pouze jeden prıkaz IF a sprav-nost resenı overte v programu.

20

5 Prıkazy organizacnı

IF (b/=0) THENIF (a/=0) THEN

WRITE(*,*) ”obe cisla jsou nenulova”END IF

END IF

2. Prectete tri cısla a vypiste nejvetsı z nich.

3. Prectete tri cısla a vypiste ty dve, ktere majı nejvetsı soucet.

4. Zmente program pro hledanı koeficientu kvadraticke rovnice z kapitoly 3 tak, aby bylyosetreny vsechny mozne prıpady (tj. resenım je jen jeden koren, resenım jsou komplexnıkoreny, je zadano a = 0 nebo je zadano a = b = 0).

5.2 Prıkazy cyklu

Dalsım organizacnım prıkazem je prıkaz cyklu. Nejjednodussı je nekonecny cyklus, ktery neustaleopakuje prıkazy v nem obsazene. Ma tvar:

DOprıkazy

END DO

Kamkoliv do tohoto cyklu lze zaradit prıkaz EXIT, ktery cyklus okamzite ukoncı, a programpokracuje za END DO. Dale lze pouzıt prıkaz CYCLE, ktery ukoncı aktualnı pruchod cyklem aprogram pokracuje dalsım pruchodem za DO. Mezery mezi klıcovymi slovy opet nejsou dulezitea lze pouzıvat ENDDO i END DO.

Dalsı formou cyklu je tzv. cyklus uplny. Ma tvar

DO prom = start,konec,krokprıkazy

END DO

Pokud krok nenı uveden, predpoklada se krok rovny jedne. I v tomto typu cyklu se mohouvyskytovat prıkazy EXIT a CYCLE. Cyklus probıha tak, ze se nejprve nastavı hodnota promenneprom na hodnotu start a provedou se postupne prıkazy mezi DO a END DO. Potom se kpromenne prom pricte krok a opet se provadı vsechny prıkazy uvnitr cyklu. Toto se opakuje dote doby, nez promenna prom bude mıt na zacatku cyklu hodnotu vetsı nez konec, nebo dokudnenı cyklus predcasne ukoncen naprıklad pomocı EXIT.

Poslednı moznostı je cyklus podmıneny, ktery ma tvar

21

5 Prıkazy organizacnı

DO WHILE (logicky vyraz)prıkazy

END DO

Pred provedenım prıkazu uvnitr podmıneneho cyklu se vzdy vyhodnocuje logicky vyraz (uza-vreny v kulatych zavorkach) na jeho pocatku. Pokud je vysledkem logickeho vyrazu .TRUE.,pak se prıkazy uvnitr cyklu provedou a pote se logicky vyraz opet vyhodnotı, atd. V prıpade, zevysledkem logickeho vyrazu je .FALSE., prıkazy uvnitr cyklu se neprovadejı a beh programuse presouva na prvnı prıkaz za cyklem. Cyklus tedy probıha dokud je splnena podmınka v jehouvodu. Predpoklada se samozrejme, ze uvnitr cyklu se nejakym zpusobem menı promenna, kteraje soucastı logickeho vyrazu. V opacnem prıpade by byl totiz cyklus nekonecny (a beh programubychom museli ukoncit nasilne).

Rovnez cykly mohou byt vnorene, prıkazy EXIT a CYCLE se pak vztahujı vzdy k nejvnitrnejsımucyklu DO. Opet je vhodne prıkazy vnitrnıho cyklu odsadit, aby byla pri ctenı programu dobrepatrna jeho struktura.

Prıklady

Prıklad 1: vypis cısel od jedne do desıti.

DO i=1,10WRITE(*,*) i

END DO

Prıklad 2: vypis sudych cısel od dvou do dvaceti.

DO i=2,20,2WRITE(*,*) i

END DO

Totez zapsano pomocı cyklu DO WHILE vypada nasledovne:

DO i=1,10WRITE(*,*) 2*i

END DO

Prıklad 3: vypis cısel od desıti do jedne.

DO i=10,1,-1WRITE(*,*) i

END DO

22

5 Prıkazy organizacnı

Totez zapsano „naopak“:

DO i=1,10WRITE(*,*) 11-i

END DO

Totez zapsano pomocı cyklu DO WHILE:

i=10DO WHILE (i>0)

WRITE(*,*) ii=i-1

END DO

Prıklad 4: nacıtanı cısel z klavesnice, konec pri zadanı nuly.

DOREAD(*,*) aWRITE(*,*) aIF (a == 0) EXIT

END DO

Totez zapsano pomocı cyklu DO WHILE:

a=1 ! abychom meli jistotu, ze je ’a’ nenuloveDO WHILE (a/=0)

READ(*,*) aWRITE(*,*) a

END DO

Prıklad 5: nacıtanı cısel z klavesnice, vypisovanı jen kladnych, deset pokusu.

DO i=1,10READ(*,*) aIF (a < 0) CYCLEWRITE(*,*) i,a

END DO

Prıklad 6: nacıtanı cısel z klavesnice, vypisovanı jen kladnych, konec po deseti vypsanychkladnych cıslech.

23

5 Prıkazy organizacnı

i = 0;DO

READ(*,*) aIF (a < 0) CYCLEi = i + 1WRITE(*,*) i,aIF (i == 10) EXIT

END DO

Opet zapıseme cyklus i pomocı podmıneneho cyklu:

i = 0;DO WHILE (i<10)

READ(*,*) aIF (a < 0) CYCLEi = i + 1WRITE(*,*) i,a

END DO

Ukoly

1. Prostudujte peclive rozdıl mezi prıklady 5 a 6.

2. Ctete cısla z klavesnice, konec pri zadanı nuly. Nakonec vypiste nejvetsı z nich, jejich poceta aritmeticky prumet.

3. Ctete cısla z klavesnice, konec pri zadanı nuly. Prubezne vypisujte dosud nejvetsı a nejmensıcıslo.

4. Vypiste vsechny dvojice cısel mensıch nez 5, kazda dvojice se vypıse jen jednou ([3,4] jetotez co [4,3]).

5. Vypiste vsechny dvojice cısel mensıch nez deset, jejichz soucin je mensı nez 40. Nakonecvypiste jejich pocet.

6. Ctete znaky z klavesnice dokud nestisknete klavesu ’x’ nebo ’X’, potom program ukoncete.

7. Napiste program pro vypocet faktorialu zadaneho cısla n.

8. Napiste program, ktery precte na vstupu cıslo X a najde cıslo n, jehoz faktorial je nejblizsınizsı cıslo k X . (Navod na resenı: hledame cıslo n, pro ktere platı n ≤ X .)

24

5 Prıkazy organizacnı

5.3 Nahodna cısla

V rade prıkladu a ukolu, ktere budou dale uvadeny, je treba nacıtat cısla z klavesnice. Opakovanezadavanı rady cısel ale pri ladenı programu casto zdrzuje. Jako alternativu muzete pouzıvatvygenerovanı nahodnych (presneji pseudonahodnych) cısel. Realne cıslo z intervalu 〈0, 1) lzevygenerovat prıkazem RANDOM NUMBER.

REAL :: aCALL RANDOM_NUMBER(a)

Takto vygenerovana cısla budou pri kazdem spustenı programu stejna. Pokud chceme, aby cıslabyla ruzna, pouzijeme na zacatku programu prıkaz:

CALL RANDOM_SEED()

Pokud chceme generovat cela cısla v nejakem intervalu 〈c, d〉, pouzijeme pro prevod cısla azıskaneho vyse pomocı RANDOM NUMBER vztah

INT(a*(d-c+1)+c)

tedy cıslo z rozsahu 〈0, 1) vynasobıme rozsahem hodnot celych cısel a pricteme hodnotu prvnıhocısla v intervalu. Vyslednemu cıslu odrızneme desetinnou cast.

Prıklady

Prıklad: vygenerovanı 10 nahodnych cısel, nalezenı nejvetsıho z nich.

INTEGER :: iREAL :: a, max_aCALL RANDOM_SEED()max_a = 0DO i=1,10

CALL RANDOM_NUMBER(a)WRITE(*,*) aIF (a > max_a) max_a = a

END DOWRITE (*,*) ”nejvetsi je ”, max_a

Ukoly

1. Vygenerujte deset nahodnych cısel a vypiste ta z nich, ktera jsou v intervalu 〈0.6, 0.8〉.Napiste na zaver, kolik vygenerovanych cısel bylo z tohoto intervalu.

25

5 Prıkazy organizacnı

2. Generujte nahodna cısla tak dlouho, dokud vygenerovane cıslo nebude z intervalu 〈0.0, 0.1〉.Vypiste toto cıslo na obrazovku a vypiste i pocet pokusu, ktere vedly k vygenerovanı tohotocısla. Predchozı pokus opakujte petkrat.

3. Naprogramujte 20 hodu kostkou, tj. nahodne generujte cıslo od 1 do 6 a pokus 20 kratopakujte.

5.4 Prıkaz CASE

Tento prıkaz podle hodnoty vyrazu provede provede urcite prıkazy. Syntaxe je nasledujıcı

SELECT CASE (vyraz)CASE (hodnota1)

prıkazy1CASE (hodnota2)

prıkazy2...CASE DEFAULT

prıkazyEND SELECT

Vyraz musı byt typu INTEGER, CHARACTER nebo LOGICAL. Pokud vyraz nabyva uvedenehodnoty vykonajı se nasledujıcı prıkazy a prıkaz CASE skoncı. V prıpade, ze vyraz se nerovnazadne hodnote provedou se prıkazy za CASE DEFAULT, tato cast muze ale chybet.

Na mıste hodnoty lze uvadet jednotlive konstanty oddelene carkami. Mısto jednoduchych kon-stant lze uvadet i rozsahy. U rozsahu se uvadı dolnı a hornı mez oddelene dvojteckou. Nekteraz mezı muze chybet, rozsah se potom bere od zacatku nebo do konce. Naprıklad

INTEGER :: i,aSELECT CASE (i)CASE(0)

a = 1CASE(1,4,20)

a = 2CASE(5:19,21)

a = 3CASE(22:)

a = 4CASE DEFAULT

a = 5END SELECT

26

5 Prıkazy organizacnı

Prıkaz CASE lze vzdy nahradit radou prıkazu IF, prıkaz CASE je vsak prehlednejsı a pri vhodnemprekladaci by mel byt i rychlejsı.

Prıklady

Jednoduche menu:

INTEGER :: a, b, pDO

WRITE(*,*) ”zadej dve cisla”READ(*,*) a, bWRITE(*,*) ”zadej operaci”WRITE(*,*) ”1 - soucet”WRITE(*,*) ”2 - rozdil”WRITE(*,*) ”0 - konec”READ(*,*) pSELECT CASE (p)CASE(0)

EXITCASE(1)

WRITE(*,*) a + bCASE(2)

WRITE(*,*) a - bCASE DEFAULT

WRITE(*,*) ”neznama operace”END SELECT

END DO

Ukoly

1. Napiste program, ktery precte dve cısla z klavesnice a podle vyberu umoznı provest nekte-rou z nasledujıcıch operacı: 1) soucet 2) rozdıl 3) soucin 4) podıl techto dvou cısel. Tentoproces se opakuje, dokud nenı stisknuta 0.

2. Upravte predchozı program tak, ze vybırame z menu podle klaves ’s’ pro soucet, ’r’ prorozdıl, ’x’ pro soucin, ’p’ pro podıl a ’k’ pro konec programu.

3. Prostudujte a vyzkousejte nasledujıcı program.

PROGRAM SemaforIMPLICIT NONECHARACTER(LEN=7) :: barva

27

5 Prıkazy organizacnı

PRINT *,”Mozne barvy semaforu: cervena, zluta, zelena”PRINT *,”Zadejte barvu svetla na semaforu:”READ(*,*) barvaIF (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 IFEND PROGRAM Semafor

Upravte tento program pomocı prıkazu CASE.

28

6 Pole I

Pole se ve Fortranu deklarujı tım, ze se pri deklaraci za identifikator promenne uvede do kulatychzavorek rozmer, prıpadne vıce rozmeru. Napr.

INTEGER :: a(10), b(3) ! jednorozmerna celocıselna poleREAL :: x(5,5) ! dvojrozmerne realne poleREAL :: y(3,3,3) ! trojrozmerne pole

Ve Fortranu zacınajı indexy jednickou. Pole b z poslednıho prıkladu ma tedy prvky b(1), b(2)a b(3). Rozmery se uvadejı do kulatych zavorek a pokud je indexu vıce, oddelujı se carkou.Pokud chceme, aby indexy zacınaly od jine hodnoty, muzeme uvest pocatecnı i koncovy indexoddelene dvojteckou. Naprıklad pri deklaraci INTEGER c(-1:1) mame k dispozici prvkyc(-1), c(0) a 0(1).

Hodnoty, ktere urcujı velikost pole, musejı byt dopredu znamy. Jsou to bud’ cela cısla jakov predchozım prıklade, nebo celocıselne konstanty. Naprıklad

INTEGER, PARAMETER :: N=100INTEGER, PARAMETER :: M=30INTEGER :: a(M), b(2*N)REAL :: x(M,M), y(2,N)

Rozmery se uvadejı do kulatych zavorek stejne jako rozmery pri deklaraci. Napr.

INTEGER,PARAMETER :: n=10INTEGER :: a(n), b(n,n)INTEGER :: i, jDO i=1, n

a(i)=iENDDODO i=1, n

DO j=1, nb(i,j) = 3.0*a(i) + SIN(0.5*j)

ENDDOENDDO

Prace s poli je asi nejvetsı vyhoda jazyka Fortran, proto je treba tomuto tematu venovat zvysenoupozornost.

Pokud pouzijeme identifikator pole ve vyrazu bez uvedenı indexu, pracujeme s celym polem.Nejcastejsı pouzitı je pri inicializacıch, naprıklad

29

6 Pole I

REAL :: a(10), b(3,3)a = 0.0 ! nastavı cele pole na nulub = 1 ! nastavı cele pole na jednicku

Cela pole se mohou vyskytovat i na prave strane vyrazu. Operace se potom provadejı pro vsechnyjednotlive prvky. Takto lze nahradit cyklus jedinym prıkazem. Oproti zapisu s cyklem muzemepri vhodnem prekladaci dosahnout i zrychlenı vypoctu.

Vsechny pole v prıkazu musı mıt stejny pocet indexu i stejnou velikost. Napr.

REAL :: a(10), b(3,3), c(0:9)a = 3*c + 4*c**2a = SIN(c) + a/2a = SQRT(b) ! chyba, rozmery nesouhlası! predchozı prıkazy lze zapsat i cyklemDO i=1,10

a(i) = 3*c(i) + 4*c(i)**2a(i) = SIN(c(i)) + a(i)/2

ENDDO

Cela pole lze jedinym prıkazem i vypisovat a nacıtat. K predchozımu prıkladu muzeme tedydoplnit

WRITE(*,*) aWRITE(*,*) b

Jestlize takto vypıseme dvojrozmerne pole, prvky budou vypsany postupne po sloupcıch. Tosouvisı s tım, ze ve Fortranu jsou prvky ukladany po sloupcıch. Tato vlastnost se projevı jenzrıdka, ale obcas je treba ji brat v uvahu.

Ukoly

1. Naplnte pole o 10 prvcıch nahodnymi cısly z intervalu 〈0, 1), prvky pole pro kontroluvypiste.

2. Sestavte program pro vypocet skalarnıho a vektoroveho soucinu trojrozmernych vektoru.

3. Napiste program, ktery bude simulovat vrhy hracı kostkou. Vysledky jednotlivych pokusuzaznamenavejte ve forme cetnosti do pole o 6 prvcıch. Proved’te 1000 pokusu a spocıtejterelativnı cetnosti jednotlivych vysledku a prumernou hodnotu vysledku.

4. Napiste program pro resenı soustavy maximalne 6 linearnıch rovnic o 6 neznamych Gaus-sovou eliminacnı metodou.

30

7 Vstup a vystup, format

Zakladnı pouzitı prıkazu READ(*,*) a WRITE(*,*) jsme jiz videli. Vystup, ktery temitoprıkazy dostaneme, je formatovany standardnım zpusobem. Pokud chceme specifikovat vlastnıformat, lze uvest popis formatu mısto druhe hvezdicky. Popis formatu je retezec, ktery zacınaa koncı kulatymi zavorkami. Uvnitr zavorek je samotna specifikace formatu. Prvnı pısmeno vpopisu formatu urcuje vypisovany typ, naprıklad pısmeno I slouzı k vypisu promennych typuINTEGER. Cıslo za tımto pısmenem vetsinou oznacuje na kolik znaku se ma promenna vypisovat.Naprıklad prıkaz

WRITE(*,’(I3)’) a

vypıse promennou a pomocı trı znaku. Pokud vypisujeme jednım prıkazem vıce promennych,jednotlive prıkazy se oddelujı carkami. Naprıklad

WRITE(*,’(I3,I5)’) a, b

Pokud za sebou nasleduje vıce stejnych formatu, lze zapis zjednodusit, tım ze pred pısmenouvedeme cıslo oznacujıcı pocet opakovanı daneho formatu, naprıklad

WRITE(*,’(4I3)’) a, b, c, d

Formatu existuje cela rada:

Iw vypis cısla typu INTEGERw je cele cıslo bez znamenka udavajıcı pocet znaku vypisuTvar udaje I lze uvest i ve forme Iw.m, kde na vstupu se .m ignoruje a pri vystupu udavaminimalnı pocet cıslic. Ma-li jich cıslo mene, udaj se pri tisku doplnı zleva nulami. Musıplatit 0 ≤ m ≤ w .

Bw, Ow, Zw vypis cısla typu INTEGERJedna se o modifikaci tvaru udaje I pro cela cısla ve dvojkove, osmickove a sestnactkovesoustave.

Fw.d vypis cısla typu REAL s pevnou radovou carkouw je cele cıslo bez znamenka udavajıcı pocet znaku vypisud udava pocet desetinnych mıst.

Ew.d vypis cısla typu REAL s exponentemw je cele cıslo bez znamenka udavajıcı pocet znaku vypisud udava pocet desetinnych mıstTvar udaje E lze uvest i ve forme Ew.dEe. Na vstupu nema cast Ee vyznam. Pri vystupue urcuje pocet cıslic exponentu.

31

7 Vstup a vystup, format

EN (’engineering’) Je ekvivalentnı tvaru udaje E s jedinou vyhradou, ze exponent na vystupubude vzdy delitelny tremi.

ES (’scientific’) Je ekvivalentnı tvaru udaje E s vyhradou, ze mantisa bude na vystupu vzdynormalizovana v rozmezı 〈1, 10).

Lw vypis cısla typu LOGICALw je cele cıslo bez znamenka udavajıcı pocet znaku vypisu

nX vynechanı n znaku na vstupu, nebo vypis n mezer.

Aw vypis promenne typu CHARACETERw udava pocet znaku, ktere se prectou do retezce nebo ktere se z retezce vypısı.

G, Gw, Gw.d, Gw.dEe vybere vhodnejsı z tvaru F, E, I, L, A

Tc skok na c-ty znak v radku

TLc skok o c znaku doleva

TRc skok o c znaku doprava (totez co Xc)

Mısto specifikace formatu lze prımo uvest retezec, ktery se ma vypsat.

WRITE(*, ’(”a = ”, I3)’) aWRITE(*, ’(a, I3)’) ”a = ”, a ! totez co predchozı prıkaz

Pri vypisu kladnych cısel se implicitne kladne znamenko nevypisuje. Pokud chceme, aby se plusvypisovalo, uvedeme specifikaci SP. Pokud chceme vypisovanı znamenka plus zrusit, uvedemeSS. Naprıklad

WRITE(*,’(SP, I4, SS, I4)’) a, a

Pocet specifikacı ve formatu vetsinou odpovıda poctu vypisovanych promennych. Pokud jepromennych vıce nez je uvedeno ve formatu, format se zacne pouzıvat opet od zacatku. Pokudje naopak promennych mene, zbytek formatu se ignoruje. Vyzkousejte

WRITE(*, ’(”a = ”,I3,” b = ”,I3,” c = ”,I3)’) a, b, cWRITE(*, ’(”a = ”,I3,” b = ”,I3,” c = ”,I3)’) a, b, c, d, eWRITE(*, ’(”a = ”,I3,” b = ”,I3,” c = ”,I3)’) a, b

Kazdy prıkaz READ a WRITE vypisuje nebo cte jeden radek. Jestlize vsak chceme na jeden radekpsat pomocı vıce prıkazu je toto chovanı nezadoucı. Kdyz chceme zabranit prechodu na novyradek, uvedeme jako tretı parametr prıkazu WRITE parametr ADVANCE=’NO’. Naprıklad

32

7 Vstup a vystup, format

WRITE(*, ’(2I3)’) a, b! lze napsat take pomocı dvou prıkazuWRITE(*, ’(I3)’,advance=’no’) aWRITE(*, ’(I3)’) b

Pokud by se nektery format nekolikrat opakoval, muzeme vyuzıt prıkazu FORMAT, a potom stacıvolat navestı tohoto formatu, tedy pouze (v celem souboru jednoznacne dane) cıslo, ktere jeuvedeno pred prıkazem FORMAT. Vse lze pochopit z nasledujıcı ukazky:

INTEGER :: i1, j1, i2, j2REAL :: x1, y1, x2, y2...WRITE(*, FMT=100) i1, i2, x1, y1WRITE(*, FMT=100) j1, j2, x2, y2100 FORMAT(’od =’,I3,’ do =’,I3,’ x =’,ES11.3,’ y =’,ES11.3)

Uvedeny format jsme v ukazce vyuzili dvakrat a nemusıme tak napr. opakovat delsı vypis retezcu,kterymi jednotlive promenne popisujeme. Dalsı vyhodou je, ze v prıpade, kdyz chceme zmenitnajednou nekolik vystupu, zmenıme vlastne jen jeden prıkaz. Prıkazy FORMAT je vhodne bud’umıstit v blızkosti vypisu, nebo je soustredit vsechny hromadne do jednoho mısta programu (sprıslusnym komentarem popisujıcım ucel jednotlivych prıkazu).

Ukoly

1. Zobrazte co nejprehledneji tabulku s hodnotami sinu, kosinu, tangens a kotangens uhlu 0,π/6, π/4, π/3,

√3π/2 a π/2. Hodnoty funkcı vypisujte bez exponentu s presnostı na pet

desetinnych mıst.

2. Naprogramujte svisly pad telesa: zadejte z klavesnice vysku telesa nad zemskym povrchem(zabrante pritom prechodu kurzoru na dalsı radek) a nechte teleso padat volnym padem.V casech t = 0, 1, . . . sekund vypisujte cas, hodnotu vysky nad povrchem a okamzitourychlost telesa. V okamziku dopadu telesa na zemsky povrch vypis ukoncete. Hodnotyvysky a rychlosti vypisujte s presnostı na tri desetinna mısta v zapisu s exponentem.

33

7 Vstup a vystup, format

34

8 Retezce

Retezce majı pevnou delku, s jakou byly nadeklarovany. To ma vyhodu v tom, ze nenı trebazabyvat se slozitym alokovanım pameti pri zmene delky retezce. Naopak nevyhoda spocıva vponekud nezvykle praci oproti jinym jazykum.

Pokud priradıme do retezce retezec kratsı delky, zbytek se doplnı mezerami. Pokud priradımeretezec delsı konec se ignoruje. Toto chovanı je videt na nasledujıcım prıkladu, pred a za retezcemvypisujeme dvojtecky, aby bylo videt delku retezce.

CHARACTER(5) ss=’abc’WRITE(*,*) ’:’, s, ’:’ ! vysledek :abc :s=’1234567’WRITE(*,*) ’:’, s, ’:’ ! vysledek :12345:

Pro retezce existuje operator //, ktery spojı dva retezce do jednoho. Naprıklad WRITE(*,*)’abc’//’12’. Casto je treba pracovat s castı retezce. K tomu slouzı vyraz tvaruretezec(start:konec). Informaci o zacatku resp. o konci muzeme vynechat, podrete-zec se potom vezme od zacatku rep. do konce puvodnıho retezce. Naprıklad

CHARACTER(6) ss=’abcdef’WRITE(*,*) s(2:4) ! vysledek ’bcd’WRITE(*,*) s(:4) ! vysledek ’abcd’WRITE(*,*) s(2:) ! vysledek ’bcdef’

Ve Fortranu retezec nenı pole znaku. Na jeden znak se nelze odkazat takto s(i), ale je trebapouzıt zpusob s(i:i).

Pro praci s retezci existuje cela rada prıkazu, k tem zakladnım patrı:

l = LEN(s) Zjistı delku retezceCHARACTER(*) s – retezecINTEGER l – delka retezce

l = LEN TRIM(s) Zjistı delku retezce bez koncovych mezerCHARACTER(*) s – retezecINTEGER l – delka retezce bez koncovych mezer

ss = TRIM(s) – odstranenı mezer na konci textoveho retezceCHARACTER(*) s – retezecCHARACTER(*) ss – retezec s bez koncovych mezer, tj. kratsı retezec

35

8 Retezce

Pro jednoho prevod znaku na cıslo (poradı v ASCII tabulce) a zpet slouzı tyto funkce:

c = CHAR(i) – prevede cısla na znak INTEGER i – cıslo znaku CHARACTER c – znak napozici i v tabulce znaku

i = ICHAR(c) – prevod znaku na cıslo (opak CHAR) CHARACTER c – znak INTEGER i– poradı znaku c v tabulce znaku

Jako prıklad uved’me kod, ktery do radku vypıse abecedu:

DO i=1, 26WRITE(*,’(a)’,advance=’no’) char(i-1+ichar(’A’))

ENDDOWRITE(*,*)

Dalsı prıklad prevede mala pısmena v retezci na velka (vyuzıvame prıkazu rozdeleneho na dvaradky):

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 prevod retezce na cıslo a obracene slouzı jiz zname prıkazy READ a WRITE. Jako prvnıparametr mısto hvezdicky nebo cısla jednotky tentokrat uvedeme identifikator retezce „cteme azapisujeme do retezce“. Naprıklad

CHARACTER(5) sREAL :: x=3.14159WRITE(s,’(f5.2)’) x ! vysledek s = ’ 3.14’s=’12.34’READ(s,’(f5.2)’) x ! vysledek x = 12.34

Ukoly

1. Vytvorte tabulku ASCII znaku od 32 do 127 (zobrazte vedle sebe vzdy cıslo a jemuodpovıdajıcı znak v ASCII tabulce). Tabulku vhodne naformatujte, aby se vesla na jednuobrazovku. Zjistete dale, jake znaky se skryvajı pod cısly 128 az 255.

2. Prectete retezec z klavesnice a zmente v nem vsechna velka pısmena na mala.

3. Prectete retezec z klavesnice (muze byt i hodne dlouhy, napr. 200 znaku) a nakopırujtetento retezec do jineho, pricemz odstrante z textu (tedy i uvnitr retezce) vsechny mezery.

36

9 Podprogramy

Ve Fortranu se rozlisujı dva typy podprogramu:FUNCTION – podprogramy vracejıcı hodnotu – funkceSUBROUTINE – podprogramy nevracejıcı hodnotu – subroutiny (nebo tez vlastnı procedury)

9.1 Subroutiny

Syntaxe subroutin je nasledujıcı

SUBROUTINE nazev(parametry)...deklarace...prikazy...END SUBROUTINE

V hlavicce funkce se uvadejı pouze identifikatory parametru, jejich typy se specifikujı uvnitrsubroutiny jako u jinych promennych. Uvnitr subroutiny se nejprve uvadejı deklarace lokalnıchpromennych a pote vykonne prıkazy, podobne jako v hlavnım programu. Pri volanı subroutinyje nutne pred identifikator subroutiny uvest prıkaz CALL:

CALL nazev(skutecne_parametry)

Vsechny parametry se predavajı tzv. odkazem. Jakekoliv zmeny parametru uvnitr subroutiny seprojevı i ve skutecnych parametrech. Subroutiny se umist’ujı na konec programu za vykonneprıkazy. Od vykonnych prıkazu se oddelujı prıkazem CONTAINS. Prıklad:

PROGRAM pythagoras! ze zadanych delek odvesen spocıta delku preponyIMPLICIT NONEREAL :: x,y,z ! delky stran

WRITE(*,*) ’zadej odvesny’READ(*,*) x,y ! nactenı delek odvesenCALL pythag(x,y,z) ! zavolanı podprogramuWRITE(*,*) ’prepona je : ’, z ! vypis preponyREAD(*,*) ! cekanı na Enter

CONTAINS

37

9 Podprogramy

!=================================================SUBROUTINE pythag(a,b,c)REAL :: a,b,cc=SQRT(a**2+b**2) ! pythagorova vetaEND SUBROUTINE!=================================================END PROGRAM

Vykonavanı podprogramu lze kdykoliv ukoncit prıkazem RETURN.

Promenna deklarovana uvnitr podprogramu je lokalnı – v hlavnım programu ani v ostatnıchpodprogramech ji nelze pouzıt. Naopak promenne deklarovane v hlavnım programu jsou globalnı– lze je pouzıt i uvnitr jakehokoliv podprogramu (pokud ovsem nenı deklarovana promennastejneho jmena).

9.2 Funkce

Funkce jsou velice podobne subroutinam, jejich syntaxe je nasledujıcı

FUNCTION nazev(parametry)deklaraceprıkazyEND FUNCTION

Ve Fortranu vystupuje identifikator funkce jako promenna a vysledek se do teto promenne priradı.Predchozı prıklad zapsany jako funkce

FUNCTION fpythag(a,b)REAL :: fpythagREAL :: a, bfpythag = SQRT(a**2+b**2)END FUNCTION

Funkce se vola uvedenım identifikatoru se skutecnymi parametry v aritmetickem prıkazu. Naprı-klad

z=fpythag(x,y)! neboWRITE(*,*) fpythag(x,y)

Podprogramy nelze bezne volat rekurzivne. Pokud chceme pouzıt rekurzivnı volanı je treba predslovo FUNCTION nebo SUBROUTINE uvest RECURSIVE, napr.

38

9 Podprogramy

RECURSIVE FUNCTION Recfun(x)REAL :: Recfun, x...END FUNCTION

Tuto funkci muzeme nynı volat i vıcekrat najednou. Pokud nevola funkce prımo sama sebe, aleprostrednictvım jineho podprogramu, stacı uvedena deklarace. Pro prıme rekursivnı volanı jetreba jeste oddelit nazev funkce potrebny pro dalsı volanı od vysledku vypoctu funkcnı hodnoty.K tomu slouzı klıcove slovo RESULT udavajıcı nazev promenne, do nız bude vysledek ulozen.Zrejme to bude z prıkladu na vypocet faktorialu:

RECURSIVE FUNCTION Factorial(n) RESULT(res)INTEGER :: res, nIF (n==1) THEN

res = 1ELSE

res = n*Factorial(n-1)END IFEND FUNCTION

9.3 Standardnı funkce

Soucastı jazyka Fortran 90 je velke mnozstvı standardnıch funkcı a subroutin, ktere jsou prımoimplementovany do jazyka. Nenı tedy nutne pri jejich pouzıvanı spojovat programovy kod sruznymi knihovnami nebo tyto knihovny volat z programu.

Nejcasteji budeme pouzıvat matematicke standardnı funkce. Jejich vyznam je vetsinou patrny jiz zjejich nazvu: 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). Promenna x jeve vsech prıpadech realne (muze vsak byt i komplexnı) cıslo. Upozorneme na to, ze funkceLOG(x) predstavuje logaritmus prirozeny a funkce LOG10(x) logaritmus dekadicky. Jedinefunkce ATAN2(y,x)ma dva parametry a vracı uhel, ktery svıra poloprımka prochazejıcı bodem(x, y) s osou x.

Dalsımi casto pouzıvanymi standardnımi funkcemi jsou funkce numericke. Z nich jmenujme tytozakladnı:

ABS(x) absolutnı hodnotaAIMAG(z) imaginarnı cast komplexnıho cıslaAINT(x) realne cıslo orıznute na celeANINT(x) realne cıslo zaokrouhlene na celeCEILING(x) nejmensı cıslo vetsı nebo rovno xCMPLX(x,y) vytvorı komplexnı cıslo x+ iy

39

9 Podprogramy

CONJG(z) komplexne sdruzene komplexnı cısloDBLE(x) prevadı cele, realne ci komplexnı cıslo na dvojitou presnostDIM(x,y) kladny rozdıl obou cıselFLOOR(x) nejvetsı cıslo mensı nebo rovno xINT(x) cele cıslo vznikle orıznutım desetinne castiMAX(x1,x2,...) maximum z cısel x1, x2, . . .MIN(x1,x2,...) minimum z cısel x1, x2, . . .MOD(a,p) zbytek po delenı (ma znamenko prvnıho cısla)MODULO(a,p) delenı modulo (ma znamenko druheho cısla)NINT(x) nejblizsı cele cısloREAL(x) prevod cele, realne ci komplexnı cıslo na cıslo REAL(4)SIGN(x,y) hodnota prvnıho cısla se znamenkem druheho

Pro presnejsı popis funkcı doporucujeme prostudovat dokumentaci a s funkcemi experimentovat.

9.4 Parametry

Predavanı skalarnıch promennych jsme jiz videli. Predavanı polı jako parametru je velice po-dobne, v hlavicce podprogramu i pri jeho volanı se uvede pouze identifikator pole. Pri deklaracipole uvnitr podprogramu mame ale nekolik moznostı.

9.4.1 Pole

Prvnı moznostı je uplna definice pole, stejna jako globalnıch polı. Naprıklad

SUBROUTINE subr(a)INTEGER :: a(10)

Tento zpusob predavanı pole nenı prılis vhodny, protoze podprogram umoznuje pracovat pouzes polem jedne delky a nenı tudız prılis univerzalnı.

Druhou moznostı je predavat spolu s polem i jeho velikost, naprıklad

SUBROUTINE subr(a,n)INTEGER :: nINTEGER :: a(n)

Tento zpusob se lisı od deklaracı, ktere jsme videli doposud, protoze promenna n nenı konstantnı,ale muze se menit. Toto lze pouzıt nejen u formalnıch parametru, ale i u lokalnıch promennych.Pozor na to, aby deklarace meze predchazela deklaraci pole.

Tretı moznostı je uvest mısto mezı pole dvojtecky, naprıklad

40

9 Podprogramy

SUBROUTINE subr(a)INTEGER :: a(:)

Velikost takoveho pole bude stejna jako velikost pole, ktere predame jako parametr pri volanıpodprogramu. Tento zpusob predavanı pole by mel byt vyuzıvan co nejvıce.

9.4.2 Retezce

Retezce lze predavat podobne jako pole s konstantnı delkou, naprıklad

SUBROUTINE subr(s)CHARACTER s(5)

Vhodnejsı ale je, uvest mısto delky hvezdicku. Delka retezce je potom stejna jako u skutecnehoparametru, naprıklad

SUBROUTINE subr(s)CHARACTER s(*)

9.4.3 Popis INTENT

Podprogramu muzeme rıci, zda promenna, ktera je parametrem, je na vstupu znama, ci zdajejı hodnota je neznama a bude teprve vypocıtana uvnitr podprogramu, nebo zda se jedna opromennou, jejız hodnotu zname a uvnitr podprogramu se tato hodnota zmenı. K tomu slouzıpopis INTENT, ktery ma nasledujıcı tri mozne hodnoty:

IN – parametr je vstupnı, jeho hodnota nesmı byt uvnitr podprogramu zmenena.

OUT – parametr je vystupnı, jeho hodnota nenı na zacatku znama, bude uvnitr podprogramuurcena a vyuzita v casti programu, ze ktere podprogram volame. Parametr je tedy urcen proprenos vysledku z podprogramu ven.

INOUT – parametr je vstupne-vystupnı, jeho hodnota je definovana pri vstupu do podprogramu,muze byt uvnitr podprogramu zmenena a preda se do mısta volanı podprogramu, kde muze bytdale vyuzita. Atribut INOUT je nastaven jako implicitnı a nenı jej treba uvadet.

Naprıklad ve vyse uvedene subroutine na vypocet prepony pravouhleho trojuhelnıka bychompopis INTENT pouzili nasledovne:

SUBROUTINE pythag(a,b,c)REAL, INTENT(IN) :: a,b ! vstupnı parametryREAL, INTENT(OUT) :: c ! vystupnı parametr = vysledekc=SQRT(a**2+b**2) ! pythagorova vetaEND SUBROUTINE

41

9 Podprogramy

V mnohych prıpadech tımto zpusobem se v programu vyvarujeme chyb a program bude navıcmozne pri prekladu i lepe optimalizovat.

Shrnutı zasad pro praci s podprogramy:

• Subroutiny se volajı prıkazem CALL

• Podprogramy nelze volat rekurzivne, pouze s RECURSIVE

• Podprogramy se umist’ujı za CONTAINS

• Pro parametry podprogramu uvadıme popis INTENT

• Subroutinu lze ukoncit prıkazem RETURN

Ukoly

1. Vytvorte program, ktery spocıta prumer pouze lichych cısel z cısel, ktere zadava uzivatel.Pri zadanı zaporneho cısla se program ukoncı. Pouzijte funkci modulo(a,b) a prıkazyCYCLE a EXIT.

2. Napiste program, ve kterem pouzijete vsechny standardnı funkce uvedene v kapitole 9.3.

3. Napiste program pro vypocet druhe mocniny pomocı vlastnı funkce. Program pak rozsirtepro vypocet n-te mocniny (n prirozene).

4. Prepiste program pro vypocet skalarnıho a vektoroveho soucinu z kapitoly 6 pomocıpodprogramu. Jako parametr predavejte cele pole.

5. Napiste rekurzivnı podprogram na vypocet rekurentne zadane posloupnosti, jejız prvnı clenje roven x1 = 0.5 a n-ty clen teto posloupnosti je dan jako nasobek predchozıho clenuvztahem xn = xn−1 ∗ 1.5.

6. Prepiste ulohy 2 resp. 3 z kapitoly 8 tak, ze zmenu velkych pısmen na mala resp. vymazanıvsech mezer z retezce zabezpecı podprogramy.

42

10 Prace se soubory

V teto kapitole probereme praci s nejjednodussım typem souboru – s textovymi soubory. Kazdemusoubor, se kterym v jazyce Fortran pracujeme, priradıme tzv. cıslo jednotky. Praci se souboremzacıname prıkazem OPEN. Prvnı parametr tohoto prıkazu je cıslo jednotky a druhy parametr jeretezec obsahujıcı nazev souboru prirazeny do parametru FILE=. Naprıklad

OPEN(5, FILE=’data.txt’)

Pred prvnım parametrem muze volitelne byt UNIT=, tj. vyse uvedeny prıkaz je tudız totozny sprıkazem

OPEN(UNIT=5, FILE=’data.txt’)

Pri otevrenı souboru se nerozlisuje, zda ze souboru budeme cıst nebo do nej zapisovat. Pokudsoubor existuje, prıkaz OPEN ho otevre a nastavı aktualnı pozici na jeho zacatek. Pokud souborneexistuje, prıkaz OPEN vytvorı soubor nulove delky a nastavı aktualnı pozici na jeho zacatek.

Prace se souborem se ukoncı prıkazem CLOSE, ktery ma jediny povinny parametr, a tım je cıslojednotky. Naprıklad

CLOSE(5)

Podobne jako u prıkazu OPEN, muzeme i zde volitelne napsat pred cıslo jednotky specifikatorUNIT=.

Pokud je soubor otevren, muzeme z nej nacıtat prıkazem READ nebo do nej zapisovat prıkazemWRITE, stejne jako cteme z klavesnice nebo vypisujeme na obrazovku. Jako prvnı parametrtechto prıkazu uvadıme mısto hvezdicky cıslo jednotky. Naprıklad

WRITE(5,*) iWRITE(5,’(I4,F5.2)’) j, xREAD(6,*) i, j, k

Zda se nachazıme na konci souboru, lze zjistit funkcı EOF – end of file. Tato funkce ma jakoparametr cıslo jednotky a vracı .TRUE., pokud je aktualnı pozice na konci souboru a .FALSE.jinak. Naprıklad nasledujıcı kod nacte vsechna cısla ze souboru a vypıse jejich pocet.

OPEN(4, FILE=’data.txt’)n=0DO

43

10 Prace se soubory

IF (EOF(4)) EXITREAD(4,*) xn=n+1

END DOCLOSE(4)WRITE(*,*) n

S vyse uvedenymi nekolika prıkazy muzeme vystacit ve vetsine prıpadu jednoduche prace sesoubory. Uvedeme jeste nekolik parametru, kterymi muzeme ovlivnit vstup a vystup do souboru.

Pri otevıranı souboru muzeme pomocı retezce prirazeneho do parametru STATUS= sdelit pro-gramu stav souboru v okamziku jeho otevıranı. Pokud zadame hodnotu’NEW’, jedna se o soubor,ktery bude programem nove vytvoren (tento soubor nesmı existovat). Pokud zadame hodnotu’OLD’, jedna se o soubor, ktery jiz existuje (tento soubor musı existovat). Hodnota ’REPLACE’znamena nahrazenı souboru a zajistı vytvorenı noveho souboru v prıpade, ze neexistuje, nebo –pokud soubor existuje – smazanı tohoto souboru a vytvorenı noveho souboru se stejnym jme-nem. Volbu ’SCRATCH’ muzeme pouzıt pro nepojmenovany novy docasny soubor, ktery se pozavrenı souboru nebo po ukoncenı programu automaticky smaze. Pokud neuvedeme parametrSTATUS=, je mu prirazena hodnota ’UNKNOWN’. Ta znamena, ze soubor muze, ale nemusı,existovat. Pokud soubor neexistuje, vytvorı se novy soubor.

Jako prıklad otevreme soubor vystup.txt. Pokud soubor neexistuje, bude vytvoren, pokudexistuje, bude nahrazen:

OPEN(7, FILE=’vystup.txt’, STATUS=’REPLACE’)

Po otevrenı se menı stav souboru na’OLD’. Pokud bychom chteli otevrıt existujıcı soubor a nava-zat na nej, tj. dalsı hodnoty pridavat na konec souboru, muzeme vyuzıt parametrPOSITION=, kte-remu priradıme hodnotu ’APPEND’. Tedy mejme naprıklad jiz vytvoren soubor ’data.txt’.Chceme-li nynı pripsat dalsı vystup za konec tohoto souboru, otevreme jej nasledovne:

OPEN(8, FILE=’data.txt’, STATUS=’OLD’, POSITION=’APPEND’)

Pokud bychom v predchozım prıkazu zvolili STATUS=’UNKNOWN’, docılili bychom stejnehoefektu a navıc by soubor byl v prıpade, ze neexistuje, vytvoren (a do souboru by se tedy zapi-sovalo od jeho zacatku, ktery je pri prvnım otevrenı souboru totozny s jeho koncem). ParametrPOSITION= muze jeste nabyvat hodnotu ’REWIND’ pro pozici presunutou na zacatek souborua ’ASIS’, ktera ponechava pozici bez zmeny, pokud byl soubor jiz pripojen.

Abychom napr. zabranili neumyslnemu zapisu do souboru, mame moznost pomocı parame-tru ACTION= urcit, zda soubor pouzijeme jen pro ctenı (ACTION=’READ’), jen pro zapis(ACTION=’WRITE’) nebo bez omezenı pro ctenı i pro zapis (ACTION=’READWRITE’). Po-slednı hodnota je zpravidla (ne vsak nutne) nastavena jako implicitnı. V nasledujıcım prıkladuotevreme jiz existujıcı soubor katalog.txt jen pro ctenı:

44

10 Prace se soubory

OPEN(9, FILE=’katalog.txt’, STATUS=’OLD’, ACTION=’READ’)

Rovnez i u prıkaz CLOSE muzeme pouzıt parametr STATUS=, ktery urcuje co se stane, kdyzsoubor zavreme. Hodnota ’KEEP’ ponecha soubor na disku, zatımco zvolıme-li ’DELETE’,soubor bude po svem zavrenı vymazan. Implicitne je nastavena hodnota ’KEEP’, to se ovsemnevztahuje na docasne soubory, ktere byly otevreny prıkazemOPEN jakoSTATUS=’SCRATCH’.

Pokud potrebujeme zjistit stav souboru, at’jiz otevreneho nebo jen souboru nekde na disku, mu-zeme pouzıt prıkaz INQUIRY. Ma radu moznych parametru, nektere z nich si nynı predstavıme.Jedna z variant tohoto prıkazu ma tvar

INQUIRE (FILE=jmeno_souboru, seznam_parametru)

a muzeme se jejı pomocı dotazovat na vlastnosti souboru s nazvem jmeno souboru.

Druha varianta tohoto prıkazu ma tvar

INQUIRE ([UNIT=]jednotka, seznam_parametru)

a muzeme se jejı pomocı dotazovat na vlastnosti jednotky danou (prirozenym) cıslemjednotka.Specifikator UNIT= pred cıslem jednotky je opet volitelny.

V seznamu parametru davame za rovnıtko promennou, do ktere se uklada hodnota parametru, naktery se dotazujeme. Parametru je cela rada, nektere z nich jsou analogicke parametrum prıkazuOPEN. Uved’me nektere parametry prıkazu INQUIRE vhodne pro praci s textovymi soubory:

• NAME=jmeno ulozı do promenne jmeno retezec se jmenem souboru.

• EXIST=existuje ulozı do logicke promenne existuje hodnotu .TRUE., pokudsoubor existuje a muze byt otevren nebo pokud uvedena jednotka existuje. Pokud sou-bor nebo jednotka neexistujı, nebo soubor existuje, ale nemuze byt otevren, promenneexistuje bude prirazena hodnota .FALSE.

• OPENED=otevren priradı logicke promenne otevren hodnotu .TRUE., pokud jeuvedeny soubor nebo jednotka pripojena a hodnotu .FALSE., pokud uvedeny soubornebo jednotka pripojeny nejsou.

• ACTION=akce vracı v promenne akce retezec, ktery ma hodnotu ’READ’ pokud jesoubor otevren pouze pro ctenı, ’WRITE’ pokud je soubor otevren pouze pro zapis a’READWRITE’ pokud je soubor otevren pro ctenı i pro zapis. Hodnota ’UNDEFINED’je prirazena v prıpade, ze soubor nenı pripojen.

• NUMBER=cislo priradı do celocıselne promenne cislo cıslo jednotky prave pripojenek souboru. Pokud nenı pripojena k souboru zadna jednotka, priradı se hodnota −1.

45

10 Prace se soubory

• POSITION=pozice umoznuje dotaz na polohu v souboru. V promenne pozice sevracı retezec obsahujıcı hodnotu ’REWIND’ pokud je soubor pripojen a jeho poloha je nazacatku souboru, ’APPEND’ pokud je soubor pripojen a jeho poloha je na konci souboru(pred znackou konce souboru – pokud existuje), ’ASIS’ pokud je soubor pripojen a jehopoloha se nemenı, nebo ’UNDEFINED’ pokud soubor nenı pripojen.

• READ=cteni, WRITE=psani, READWRITE=ctenipsani umoznujı zjistit, zda zesouboru muzeme cıst, zapisovast, nebo zaroven cıst i zapisovat. V promennych cteni,psani a ctenipsani bude vracen retezec obsahujıcı ’YES’ pokud ano, ’NO’ pokudne, a ’UNKNOWN’ pokud nelze odpoved’zjistit.

Jako prıklad uvedeme dotaz na existenci souboru ’pokus.dat’ a dale zjistıme stav jednotky cıslo9, kterou jsme otevreli v ukazce uvedene vyse:

CHARACTER(12) :: nm, ac, wrLOGICAL :: 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)

Ukoly

1. Vytvorte program, ktery do souboru data.txt napıse posloupnost celych cısel od 1 do100.

2. Sestavte program, ktery do souboru pythagor.txt napıse vzdy po trech do radkuPythagorejska cısla a, b, c, tj. cela cısla vyhovujıcı rovnici a2 + b2 = c2. Pokud souborpythagor.txt jiz existuje, prepiste jej.

3. Upravte program pro resenı kvadraticke rovnice tak, ze hodnoty zadane z klavesnice i resenırovnice budou (s podrobnejsım popisem resenı) zapsany do souboru kvadrov.txt.Pokud soubor kvadrov.txt jiz existuje, pripisujte vysledky na konec souboru.

4. Pomocı prıkazu INQUIRE zjitete, zda soubor ’data.txt’ existuje. Pokud ano, otevrete jejpouze pro ctenı a zobrazte na obrazovce jeho obsah. Pokud neexistuje, vytvorte jej pouzepro zapis a zapiste do nej vsechny udaje, ktere dokazete zjistit o jeho stavu pomocı prıkazuINQUIRE.

46

11 Pole II

Pole ve Fortranu skytajı oproti ostatnım jazykum velke moznosti.

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 vsechny prvky pole na jednicku. Pokud chceme do jednotlivych prvkupriradit ruzne hodnoty, muzeme nejprve z techto hodnot vytvorit pole a to priradit do pole a.Vytvorenı pole ze zadanych hodnot se provede tak, ze mezi (/ a /) vlozıme jednotlive hodnotyoddelene carkami, naprıklad

a = (/2,7,3,1,5/)

Toho lze vyuzıt uz pri inicializaci pole v samotne deklaraci, napr. (nezapomınat na dvojtecky zatypem)

REAL :: b(3) = (/1.0, 2.345, 34.0/)

Tımto zpusobem 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/) ! vysledek c = (/1,2,3,10,11/)c = (/1,5,b,0/) ! vysledek c = (/1,5,10,11,0/)

V prıpade, ze pole jsou velka, je vypisovanı vsech hodnot obtızne. Pro tento prıpad je casto moznepri konstrukci pole vyuzıt cyklu. Tento cyklus ma tvar podobny uplnemu DO-cyklu:

(vyraz,promenna=od,do,krok)

Tento cyklus se vklada mezi (/ a /) mısto vyctu hodnot. Naprıklad:

INTEGER :: a(5),ia=(/(i, i=1,5)/) !vysledek a=(/1,2,3,4,5/)a=(/(i, i=5,1,-1)/) !vysledek a=(/5,4,3,2,1/)a=(/(3*(i-1), i=1,5)/) !vysledek a=(/0,3,6,9,12/)a=(/(100*SIN(10.*i), i=1,5)/) !vysledek a=(/-54,91,-98,74,-26/)a=(/0, (i,i=104,106), 1/) !vysledek a=(/0,104,105,106,1/)

47

11 Pole II

Konstrukce (/../) vytvarı nove pole, muze se tedy vyskytovat nejen v prirazovacım prıkazu,ale kdekoliv, kde muze byt pole. Naprıklad

a=-2*(/(i,i=1,5)/) !vysledek a=(/-2,-4,-6,-8,-10/)CALL subr((/0,1,22/))

11.2 Casti pole

Jiz jsme zmınili moznost prace s celymi poli najednou. Dalsı moznostı je prace jen s castı pole.

Na mıste indexu lze uvest dve meze oddelene dvojteckou. Zıskame tım spojity usek pole zacınajıcıprvnı mezı a koncıcı druhou mezı napr a(2:5). Kteroukoliv z mezı lze vynechat, potom sepracuje s usekem od zacatku resp. do konce pole, napr. a(:5) nebo a(2:). Lze vynechati obe meze. U jednorozmerneho pole tım nic nezıskame, naprıklad a(:) je totez co samotnea. Vynechanı obou mezı u jednoho indexu je vsak velice caste u vıcerozmernych polı, tım lzenaprıklad z dvourozmerneho pole udelat jednorozmerne. Naprıklad a(3,:) je jednorozmernepole obsahujıcı tretı radek matice a, nebo a(:,j) je j-ty sloupec matice.

Z pole muzeme vybrat i jednotlive prvky, a to tak, ze mısto indexu uvedeme pole obsahujıcıindexy vybıranych 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) ! vysledek 20,30WRITE(*,*) a(:2) ! vysledek 10,20WRITE(*,*) a(2:3) ! vysledek 20,30WRITE(*,*) a((/4,2,3/)) ! vysledek 40,20,30c = a((/4,2,3,1/)) ! vysledek c = (/40,20,30,10/)c = a(b) ! vysledek c = (/40,20,10,30/)c(b) = a ! vysledek c = (/30,20,40,10/)

11.3 Standardnı podprogramy pro pole

Pro praci s poli existuje rada funkcı. Nejdulezitejsı z nich si nynı probereme. Funkce SUM aPRODUCT umoznujı secıst a vynasobit cele pole.

SUM(array) – Funkce secte prvky pole typu INTEGER, REAL nebo COMPLEX

PRODUCT(array) – Funkce vynasobı prvky pole typu INTEGER, REAL nebo COMPLEX

Funkce MAXVAL a MINVAL zjistı hodnotu nejvetsıho a nejmensıho prvku v poli. Casto ale nestacıznat hodnotu nejvetsıho nebo nejmensıho prvku, ale i jeho polohu. K tomu slouzı dalsı dve funkceMAXLOC a MINLOC

48

11 Pole II

MAXVAL(array) – Funkce vratı hodnotu maximalnıho prvku pole typu INTEGER nebo REAL

MINVAL(array) – Funkce vratı hodnotu minimalnıho prvku pole typu INTEGER nebo REAL

MAXLOC(array) – Funkce vratı polohu maximalnıho prvku pole

MINLOC(array) – Funkce vratı polohu minimalnıho prvku pole

Poloha extremnıho prvku se vracı jako celocıselne pole, jehoz delka odpovıda poctu indexuvstupnıho. Pokud je vstupnı pole naprıklad dvourozmerne dostaneme vektor o delce dve. Pokudje vstupnı pole jednorozmerne dostaneme vektor o delce jedna (pozor – to je neco jineho nezskalar). Tato neprıjemnost je jiz v jazyce Fortran95 odstranena tım, ze jako druhy parametr funkceMINLOC uvedeme cıslo indexu, ktery nas zajıma a jako vysledek pak dostavame skalar. Prıklad:

REAL :: a(4) = (/1.2, 3.6, -4.7, 2.2/), xINTEGER :: k,l(1)x = SUM(a) ! vysledek x = 2.3x = SUM(1+2*ABS(a)) ! vysledek x = 27.4x = PRODUCT(a) ! vysledek x = -44.6688x = MAXVAL(a) ! vysledek x = 3.6l = MAXLOC(a) ! vysledek l = (/2/)k = MAXLOC(a) ! !! chyba - k nenı polek = MAXLOC(a,1) ! vysledek k = 2

Pro operace s maticemi a vektory jsou naprıklad funkce:

DOT PRODUCT(a,b) – skalarnı soucin vektoru a a boba vektory musı mıt stejnou delku

MATMUL(a,b) – vynasobenı matic a a bpocet sloupcu matice a se musı rovnat poctu radku matice b

TRANSPOSE(a) – vratı transponovanou maticia musı byt dvojrozmerna matice

RESHAPE(a,tvar) – zmena tvaru polea – pole jehoz tvar se menıtvar – jednorozmerny celocıselny vektor

Za zmınku stojı predevsım funkceRESHAPE. Tato funkce umoznuje prevest napr. jednorozmernepole na dvojrozmerne nebo treba matici 4×5 na 10×2. Pocet prvku ve vstupnım a vystupnım poliby mel souhlasit. Tvar vysledneho pole je popsan druhym parametrem funkce, napr. (/2,3/) jematice 2×3, (/10/) je desetiprvkovy vektor. Pri transformaci se postupuje po sloupcıch (prvnıindex se menı nejrychleji). Teto funkce se nejcasteji pouzıva pri inicializaci vıcerozmerneho pole.Prıklady:

49

11 Pole II

INTEGER :: b(2,3)=RESHAPE((/1,2,3,4,5,6/),(/2,3/)) ! 1 3 5! 2 4 6

INTEGER :: c(3,2)=RESHAPE((/1,2,3,4,5,6/),(/3,2/)) ! 1 4! 2 5! 3 6

INTEGER :: l(2)c = RESHAPE(b,(/3,2/))l = MAXLOC(b) ! vysledek l = (/2,3/)

11.4 Dynamicke alokace

Pole, se kterymi jsme se doposud setkali, mela dopredu znamou velikost. Stejne jako v jinychprogramovacıch jazycıch (napr. v jazyce C) existuje i ve Fortranu moznost dynamicke alokacepolı. Pokud chceme velikost pole urcit az za behu programu, uvedeme pri jeho deklaraci spe-cifikaci ALLOCATABLE a mısto velikosti uvedeme pro kazdy rozmer jen dvojtecku. Samotnaalokace pameti se provadı prıkazem ALLOCATE. Jako parametr se uvede identifikator pole s po-zadovanymi rozmery. Pamet’se uvolnuje prıkazem DEALLOCATE. Zda bylo jiz pole alokovanolze zjistit funkcı ALLOCATED.

INTEGER,ALLOCATABLE :: a(:)INTEGER :: nREAD(*,*) na(1)=3 ! chyba - pole jeste nebylo alokovanoALLOCATE(a(0:n))a(n)=3...IF (ALLOCATED(a)) then

DEALLOCATE(a)ALLOCATE(a(10))

ENDIF...DEALLOCATE(a)

Ukoly

1. Naplnte pole A o 10 prvcıch postupne hodnotami od 10 do 19 a pole B o 10 prvcıchhodnotami sestupne od 50 do 41. Sectete obe pole a vytisknete vysledek.

2. Naplnte jednorozmerne pole o 100 prvcıch nahodnymi cısly od 1 do 1000. Zdvojnasobteprvnıch 50 prvku pole. Vytvorte z pole matici typu 10 × 10. Zjistete nejmensı a nejvetsıprvky pole a jejich umıstenı v poli. Zjistete soucet vsech prvku a jejich prumernou hodnotu.

50

11 Pole II

3. Nactete z klavesnice cela cısla N a M . Osetrete vstup tak, aby obe cısla byla v rozsahu od1 do 6. Dynamicky alokujte matici A typu N ×M a vektor x o M prvcıch. Nactete do tetomatice i do vektoru hodnoty (z klavesnice). Vynasobte matici A (maticove) vektorem x avysledek ulozte do vektoru y (kolik prvku bude mıt tento vektor?). Vytisknete matici A avektory x a y. Dealokujte matici a vektory.

51

11 Pole II

52

12 Grafika

Grafika nenı standardnı soucastı jazyka. To, co si uvedeme v teto kapitole platı pouze pro VisualFortran v prostredı operacnıho systemu Windows.

Pokud chceme pouzıvat grafiku je treba vybrat projekt s nazvem Fortran Standard or QuickWinApplication, a potom podtyp Standard Graphics. Vznikly program bude vypadat velice podobnejako konzolova aplikace, kterou jsme pouzıvali doposud, pouze okno je vetsı a lze menit jehovelikost.

Abychom mohli pouzıvat graficke prıkazy je treba na zacatku programu (hned za radkemPROGRAM ...) uvest prıkaz USE DFLIB, nebo u starsıch kompilatoru USE MSFLIB.

Pro grafiku existuje cela rada prıkazu. Ukazme si nekolik zakladnıch. Prvnı skupina prıkazupracuje s celocıselnymi souradnicemi obrazovkovych bodu (pixelu). Prvnı souradnice (x) urcujeporadı bodu od leveho okraje obrazovky. Druha souradnice (y) urcuje poradı bodu od hornıhookraje. Body se v obou smerech cıslujı od nuly.

res = SETPIXEL(x,y) Nakreslı bod.INTEGER x,y – souradnice boduINTEGER(2) res

res = LINETO(x,y) Nakreslı caru z aktualnı pozice do zadaneho bodu.INTEGER x,y – souradnice koncoveho boduINTEGER(2) res

CALL MOVETO(x,y,xy) Nastavı aktualnı pozici do zadaneho bodu.INTEGER x,y – souradnice boduTYPE(xycoord) xy – promenne uzivatelskeho typu (viz. kapitola xx), pro nas nenıdulezita

Navratove hodnoty nekterych funkcı (res) nejsou pro nas dulezite. Nynı si jiz muzeme ukazatjednoduchy graficky program – nakreslenı ctverce s bodem uprostred.

PROGRAM ctverecUSE dflibIMPLICIT NONEINTEGER :: sx,sy,lINTEGER :: rTYPE(xycoord) cxy

sx = 200 ! souradnice stredusy = 100 ! souradnice stredul = 50 ! polovina delky strany

53

12 Grafika

r = setpixel(sx,sy) ! bod do streduCALL moveto(sx+l, sy+l, cxy) ! ctverecr = 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

Rozlisenı obrazovky v bodech lze zjistit pomocı prıkazu GETWINDOWCONFIG, viz nasledujıcıkod:

TYPE (windowconfig) mscINTEGER :: resres=GETWINDOWCONFIG(msc)WRITE(*,*) ’sırka obrazovky : ’,msc%numxpixelsWRITE(*,*) ’vyska obrazovky : ’,msc%numypixels

Predchozı prıkazy pracovaly s jednotlivymi pixely. Pri kreslenı naprıklad grafu funkce vsakvetsinou chceme pracovat s realnymi souradnicemi o zadanem rozsahu. I toto Digital Fortranumoznuje. Predchozı prıkazy majı jeste tvar, kdy se souradnice zadavajı jako realna cısla:

res = SETPIXEL W(x,y) Nakreslı bod.REAL(8) x,y – souradnice boduINTEGER(2) res

res = LINETO W(x,y) Nakreslı caru z aktualnı pozice do zadaneho bodu.REAL(8) x,y – souradnice koncoveho boduINTEGER(2) res

CALL MOVETO W(x,y,xy) Nastavı aktualnı pozici do zadaneho bodu.REAL(8) x,y – souradnice boduTYPE(wxycoord) xy – promenne uzivatelskeho typu (viz. kapitola xx), pro nas nenıdulezita

Jak je videt nazvy se lisı pridanym W na konci. Souradnice jsou realne a ne celocıselne. Pozorna zmenu typu u MOVETO.

Souradnice bodu nemajı u techto prıkazu vztah k obrazovkovym bodum, ale jejich rozsah je trebanastavit. Pro nastavenı rozsahu je prıkaz

res = SETWINDOW(dir,x0,y0,x1,y1) Nastavı rozsah realnych souradnic.REAL(8) x0,y0 – souradnice leveho dolnıho rohuREAL(8) x1,y1 – souradnice praveho hornıho rohu

54

12 Grafika

LOGICAL dir – smer osy y, .TRUE. – zezdola nahoru, .FALSE. – zezhora doluINTEGER(2) res

Nasledujıcı ukazkovy program nakreslı graf funkce sinus.

PROGRAM sinusovkaUSE dflibIMPLICIT NONETYPE(wxycoord) cxyINTEGER :: r, i, n = 100REAL :: x, xkon = 4*3.1415926r = 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*ir = lineto_w(x,SIN(x))

ENDDOREAD(*,*)END PROGRAM

At’uz pracujeme se souradnicemi pixelu ci s realnymi souradnicemi, rada funkcı je spolecna. Tynejpouzıvanejsı jsou:

CALL CLEARSCREEN ($GCLEARSCREEN) Vymaze obrazovku.

res = SETCOLOR(c) Nastavı barvu cıslo c.INTEGER(2) c – cıslo barvy (0 – cerna, . . . , 15 – bıla)INTEGER(2) res

res = SETCOLORRGB(c) Nastavı barvu RGB.INTEGER(4) c – libovolna barvaINTEGER(2) res

Mimo trı zakladnıch funkcı ktere jsme si uvedli existuje rada dalsıch:

res = RECTANGLE(typ,x0,y0,x1,y1) Nakreslı obdelnık.INTEGER x0,y0 – levy dolnı rohINTEGER x1,y1 – pravy hornı rohINTEGER typ – $GBORDER – nakreslı jen obvod, $GFILLINTERIOR – vyplnenyobdelnık

res = ELLIPSE(typ,x0,y0,x1,y1) Nakreslı elipsu.INTEGER x0,y0 – levy dolnı roh ohranicujıcıho obdelnıkuINTEGER x1,y1 – pravy hornı roh ohranicujıcıho obdelnıkuINTEGER typ – jako u obdelnıku

55

12 Grafika

res = FLOODFILL(x,y,bc) Vyplnı oblast barvou. INTEGER x,y – bod uvnitr oblastiINTEGER bc – cıslo barvy hranice

c = GETPIXEL(x,y) Zjistı barvu pixelu. INTEGER x,y – souradnice boduINTEGER c – cıslo barvy

CALL OUTGTEXT(str) Vypıse retezec na aktualnı pozici.CHARACTER(*) str – vypisovany retezecPred pouzitım teto funkce je treba volat prıkazy INITIALIZEFONTS a SETFONT

res = INITIALIZEFONTS() Inicializuje graficke pısmo.

res = SETFONT(str) Vybere graficky font pro OUTGTEXT.CHARACTER(*) str – retezec popisujıcı pozadovany font, napr.’t’’Arial’’h16w7’ viz napoveda.

Ukazky pouzitı uvedenych prıkazu muzete najıt v programu GR DEMO.F90. Uvedene prıkazymajı i varianty pracujıcı s realnymi souradnicemi.

Ukoly

1. Napiste program, ktery zobrazı funkci y = cos x v intervalu 〈−2π, 2π〉 vcetne souradnico-vych os, znacek a popisku.

2. Napiste program, ktery bude na obrazovku na nahodna mısta zobrazovat nahodne geome-tricke tvary vyplnene nahodnymi barvami.

56

13 Moduly

Jazyk Fortran umoznuje rozdelit program do mensıch celku tzv. modulu. Moduly by mely bytpokud mozno samostatne a vıcenasobne pouzitelne jednotky.

Pri tvorbe vetsıho programu bychom se meli snazit rozdelit program do samostatnych celku.Tento tzv. modularnı prıstup ma radu vyhod. Modul lze ladit a zkouset postupne, lokalizace chybje potom jednodussı. Hlavnı vyhodou ale je, ze pri vhodnem navrhu lze moduly pouzıvat vıcekrat.Prıkladem modulu, se kterym jsme se jiz setkali, je modul pro praci s grafikou. Radu uzitecnychmodulu lze zıskat i z internetu – modul pro praci s libovolne presnymi realnymi cısly, modul protvorbu postscriptovych souboru.

Jednotlive moduly je vhodne umist’ovat do samostatnych souboru, opet s koncovkou .f90.Modul je velice podobny programu, ale s nekolika rozdıly:

• Zacına MODULE mısto PROGRAM.

• Koncı END MODULE mısto END PROGRAM.

• Nesmı obsahovat zadne vykonne prıkazy mezi deklaracemi a CONTAINS.

Do modulu muzeme umist’ovat podprogramy nebo promenne. Tyto muzeme pouzıvat v hlavnımprogramu nebo i v jinem modulu. Pokud chceme modul pouzıt, je treba bezprostredne za prvnımradkem (PROGRAM ... nebo MODULE ...) uvest USE a nazev modulu. Prıklad modul sfunkcı na vypocet mocniny.

Soubor mod mocnina.f90

MODULE mod_mocninaIMPLICIT NONEINTEGER :: exponentCONTAINSFUNCTION f(x)REAL :: f,xINTEGER :: If=xDO i=2,exponent

f=f*xEND DOEND FUNCTIONEND MODULE

Soubor test mocnina.f90

PROGRAM test_mocnina

57

13 Moduly

USE mod_mocnina ! chceme pouzıvat modulIMPLICIT NONEexponent = 4 ! nastavıme velikost exponentu v moduluWRITE(*,*) f(1.24) ! zavolanı funkce z moduluEND PROGRAM

Vsechny promenne a podprogramy z modulu lze pouzıvat v libovolne nadrazene jednotce (mo-dulu ci programu). Naopak ale promenne a podprogramy z nadrazene jednotky nelze v modulupouzıvat. Tj. „Promenne jsou videt pouze zezdola nahoru“. Pokud uvnitr modulu chceme mıtpromenne (podprogramy), ktere nejde zvencı pouzıt, muzeme pro vybranou promennou pouzıtspecifikaci PRIVATE. Naopak pro promenne prıstupne zvencı se pouzıva specifikace PUBLIC.Pokud pred deklaracı promennych uvedeme samotne PRIVATE nebo PUBLIC vztahuje se navsechny nasledujıcı deklarace.

Ukoly

1. Napiste modul, ktery bude definovat hodnoty globalnıch realnych promennych a, b, c provypocet korenu kvadraticke rovnice ax2 + bx + c = 0. Pouzijte tento modul v programuna resenı kvadraticke rovnice (viz kapitola 5.1).

2. Napiste modul, ve kterem budou zahrnuty funkce vytvorene pro zmenu velkych pısmen vretezci na mala, zmenu malych pısmen v retezci na velka a vymazanı vsech mezer z retezce(viz kapitola 9). Tyto funkce pouzijte v programu, ktery bude tento modul pouzıvat.

58

14 Parametry podprogramu

14.1 Podprogramy jako parametry

Nekdy byva potreba predat podprogramu odkaz na jiny podprogram. Prıkladem muze byt pod-program pro vykreslenı grafu funkce, kdy je treba urcit graf ktere funkce chceme vykreslovat.Fortran toto predavanı podprogramu jako parametru umoznuje.

V hlavicce podprogramu uvedeme nazev podprogramu, ktery chceme pouzıvat uvnitr pod-programu. Mısto typu tohoto identifikatoru, jako u ostatnıch promennych, uvedeme meziINTERFACE a END INTERFACE zkraceny popis funkce. Uvadıme pouze prvnı a poslednıradek podprogramu a specifikaci predavanych parametru.

PROGRAM fce_parIMPLICIT NONEWRITE(*,*) maximum(-1.0,6.0,f2)CONTAINS!===============================FUNCTION maximum(a,b,f)REAL :: a,b,maximumINTERFACE

FUNCTION f(x)REAL :: f,x

END FUNCTIONEND INTERFACEINTEGER :: i... ! viz prilozeny programEND FUNCTION!===============================FUNCTION f2(x)REAL :: f2,xf2 = 3-(x-2)**2END FUNCTION!===============================END PROGRAM

14.2 Volitelne parametry

Casto se setkavame s procedurami ktere mohou mıt ruzny pocet parametru (napr. subroutinaWRITE). Takove subroutiny muzeme deklarovat sami. U parametru, ktere nemusı byt vzdyprıtomne (nepovinne parametry), uvadıme specifikaci OPTIONAL. Povinne parametry musı vzdyv hlavicce vzdy pred nepovinnymi. Pokud pri volanı podprogramu uvedeme mene parametru,

59

14 Parametry podprogramu

dostane hodnotu pouze odpovıdajıcı pocet prvnıch nepovinnych parametru. Pokud chceme zadatnepovinny parametr, ktery nenı na uveden na zacatku, lze ho pri volanı podprogramu zadat ve tvaruidentifikator promenne = hodnota. Pokud uvnitr podprogramu chceme zjistit zdabyl volitelny parametr zadan, pouzijeme funkci PRESENT(prom). Tato funkce vracı .TRUE.pokud byl parametr zadan. Prıklad:

PROGRAM vol_parIMPLICIT NONECALL sub(1,2)CALL sub(1,2,3)CALL sub(1,2,d=4)CALL sub(a=2,c=4) ! chyba - chybı bCONTAINS!===============================SUBROUTINE sub(a,b,c,d)INTEGER :: a,bINTEGER, OPTIONAL :: c,dWRITE(*,’(”a=”,i3)’) aWRITE(*,’(”b=”,i3)’) bIF (PRESENT(c)) WRITE(*,’(”c=”,i3)’) cIF (PRESENT(d)) WRITE(*,’(”d=”,i3)’) dEND SUBROUTINE!===============================END PROGRAM

Ukoly

1. Vytvorte modul s nekolika ruznymi funkcemi (napr. f1 = cos2 x, f2 = sin 2x, apod.).Nactete z klavesnice promennou x a pomocı menu vyberte funkci, jejız hodnotu v danembode spocıtate.

2. Upravte program pro kreslenı grafu funkce kosinus (viz kapitola 12) tak, ze pomocı menuv uvodu programu bude mozne si vybrat funkci, kterou na grafu zobrazıte. Vyuzijte modulvytvoreny v predchozım ukolu.

3. Napiste podprogram, ktery bude mısto mezer v retezci doplnovat jine znaky. Znak, ktery sebude mısto mezer zapisovat, poslete jako volitelny parametr podprogramu. Pokud nebudevolitelny parametr zadan, doplnte retezec nulami. Tento podprogram otestujte v hlavnımprogramu.

60

15 Uzivatelsky typ

Mimo peti standardnıch typu (INTEGER, REAL, COMPLEX, CHARACTER, LOGICAL) exis-tuje dalsı uzivatelsky definovany typ. Predtım, nez definujeme promenne tohoto typu, je trebadefinovat samotny typ. Definice typu zacına TYPE nazev a koncı END TYPE. Mezi temitoradky definujeme jednotlive slozky typu, stejne jako bychom deklarovali obycejne promenne.Naprıklad

TYPE datumINTEGER :: den,mesic,rok

END TYPETYPE osoba

CHARACTER(30) :: jmenoLOGICAL :: muzTYPE(datum) :: narozenREAL :: plat

END TYPE

Pokud chceme deklarovat promennou uzivatelskeho typu, jako typ uvadımeTYPE(nazev typu). Naprıklad

TYPE(datum) vcera, zitraTYPE(osoba) ja, vedouci, uklizecka

Odkazy na jednotlive polozky se uvadejı pomocı znaku procento %. Naprıklad

vcera%rok = 2002ja%jmeno = ”Muller Thurgau”ja%narozen%rok = 1212

Rada prekladacu umoznuje pouzıvat mısto znaku procento tecku (ja.narozen.rok =1348). Tato moznost ale nenı soucastı normy a nektere prekladace ji nepodporujı. Pro za-chovanı prenositelnosti zdrojoveho kodu je tedy lepsı pouzıvat %. Stejne jako u ostatnıch typu iuzivatelsky typ muzeme pouzıt pro sestavenı pole:

TYPE(datum) svatky(20)

Na jednotlive prvky tohoto pole odkazujeme podobne:

svatky(1)%rok = 2004svatky(1)%mesic = 1svatky(1)%den = 1

61

15 Uzivatelsky typ

Pro pohodlnejsı zadavanı hodnot muzeme vyuzıt konstruktoru, ktery je predstavovan nazvemtypu a uvnitr kulatych zavorek jsou jednotlive hodnoty (v poctu a v poradı ve shode s definicıuzivatelskeho typu):

svatky(2) = datum(2004, 5, 1)

Pokud chceme uzivatelsky typ vypsat na obrazovku, muzeme vypsat bud’ jeho slozky, nebonajednou cely zaznam, napr.

PRINT *, svatky(1)%rok, svatky(1)%mesic, svatky(1)%denPRINT *, svatky(1) ! Totez co predchozı radek

S uzivatelskymi typy jsme se jiz setkali pri praci s grafikou – typy xycoord a windowconfig.Naprıklad typ xycoord slouzı pro uchovanı souradnic x a y na obrazovce a je definovan takto:

TYPE xycoordINTEGER(2) xcoord ! souradnice xINTEGER(2) ycoord ! souradnice y

END TYPE xycoord

Ukoly

1. Definujte vlastnı typ kniha, ktery bude obsahovat zaznamy o knihovne: evidencnı cıslo,autor, nazev, nakladatel, rok vydanı, pocet vytisku a zda je kniha zapujcena (logickapromenna). Naplnte tento seznam hodnotami a zapiste je do souboru.

2. Upravte predchozı program tak, ze se pri dalsım volanı programu seznam nactete ze souborua pak se pripisujı dalsı zaznamy.

3. Napiste program, ktery predchozı seznam knih nacte ze souboru, seradı knihy abecednepodle autora a setrıdeny seznam opet ulozı do souboru. Vyuzijte funkce pro lexikalnıporovnavanı retezcu: LGT, LLT popr. LGE, LLE.

62

16 Fortran 77

Fortran 77 je predchazejıcı verze jazyka Fortran. Z dnesnıho hlediska se jedna jiz o nemodernıjazyk, ktery postrada radu potrebnych rysu (dynamicke alokace, globalnı promenne, modularnıstruktura) a pro dnesnı pouzitı ho nelze doporucit. V jazyce Fortran 77 je vsak napsano obrovskemnozstvı programu, zvlaste v matematickych a fyzikalnıch aplikacıch. Fortran 77 je nastestıpodmnozina Fortranu 90. Kompilatory F90 by proto mely byt schopny prekladat i jazyk F77.

Je tedy treba pasivne rozumet jazyku F77 a je treba umet pripojit zdrojovy kod v F77 k programuF90. Pro pripojenı stacı ulozit kod s koncovkou .for a vlozit do projektu stejne jako kod veF90.

Prvnı rozdılem mezi F90 a F77 je formalnı vzhled zdrojoveho kodu. Jazyk F77 byl puvodne za-pisovan na derne stıtky, na kazdy stıtek jeden radek programu. Z toho dodnes vyplyva nasledujıcıformat radku.

• Sloupce 1 az 5 jsou vyuzıvany pro navestı.

• Pokud je v prvnım sloupci nektery ze znaku ’*’, ’C’, ’c’, je cely radek komentar.

• Sloupec 6 se normalne nepouzıva. Pokud je v tomto sloupci jakykoliv znak, je tento radekpokracovanım radku predchozıho.

• Do sloupcu 7 az 72 se zapisujı vlastnı prıkazy. Na kazdem radku muze byt pouze jedenprıkaz.

Prostredı MSDS podporuje psanı v tomto formatu viz obr. 5.

Ve Fortranu 77 najdeme nekolik prıkazu a rysu, ktere jsou jiz povazovany za zastarale a nenıdoporuceno je nadale pouzıvat. Z programatorskeho hlediska je treba zavrhnout prıkaz GOTO vevsech svych variantach, ktery umoznuje nepodmınene skoky na jina mısta v programu oznacenanavestım. Fortran 90 jiz zcela podporuje strukturovanı programu a skokum na jina mısta pomocıGOTO se lze vzdy vyhnout. Bohuzel, tento prıkaz byl drıve pouzıvan velice casto, coz vedlo keznacne neprehlednosti rady programu napsanych ve Fortranu 77. Dalsım prıkladem jsou blokyCOMMON, ktere slouzı pro ukladanı dat a sdılenı globalnıch promennych. Pro globalnı promenneje dnes daleko lepsı pouzıt modul, ve kterem jsou spolecne umısteny.

Podrobne popisuje Fortran 77 kniha [1], kde muzeme nalezt jeste nekolik dalsıch prıkazu, jejichzpouzitı dnes jiz nenı nutne. Jelikoz Fortran 77 je podmnozinou Fortranu 90, nalezneme tytoprıkazy i v napovede a dokumentaci kompilatoru Fortran 90.

63

16 Fortran 77

Obrazek 5: Kod ve Fortranu 77

64

Literatura

[1] Hrebıcek, J., Kopecek, I., Kucera, J., Polcar, P.: Programovacı jazyk FORTRAN 77 a vedec-kotechnicke vypocty. 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