obsah - ujepphysics.ujep.cz/~mlisal/fortran-chomutov/mvicher_fortran.pdf · 2014-02-01 · 2...
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
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
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
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
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
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