Programovanie makier v LibreOffice: Cykly (2)

LO.png V tomto článku využijeme druhý spôsob, ako vytvoriť cyklus v programovaní makier. Tiež si ukážeme príkaz skoku GoTo a príkaz Exit.  

Príkaz For...To...Step...Next

V minulom diele sme podrobne rozoberali tvorbu cyklu pomocou Do...Loop. Tento typ cyklu obvykle využijeme, ak nepoznáme počet iterácii, ktoré sa majú vykonať.

Konštrukcia For...To...Step...Next umožňuje definovať, koľko krát sa cyklus vykoná.

Poďme si pozrieť prvý príklad.

1. príklad: Využitie príkazu For...To...Step...Next

Sub mocninator   REM začiatok procedúry
Vstup% = InputBox("Zadajte celé číslo: ")   REM vstup od užívateľa
For n = 0 To 1 Step 1   REM začiatok cyklu
Vysledok = Vysledok * Vstup   REM výpočet
Next n   REM koniec cyklu a vyhodnotenie, či má pokračovať
Print "Mocnina čísla " & Vstup & " je " & Vysledok   REM vypísanie na obrazovku
End Sub   REM koniec procedúry

Výsledok: Ak zadá užívateľ napríklad celé číslo 5, tak výsledok je mocnina 5, čiže 25.

Výzva pre užívateľa Výzva pre užívateľa

Výsledok Výsledok

Rozbor makra: Cyklus je inicializovaný slovom For, za ktorým nasleduje premenná n.

Rozsah počtu vykonania cyklu je od hodnoty inicializovanej premennej n až po hodnotu definovanú v slove To. Veľkosť skokov je definovaná v slove Step. V našom prípade je to hodnota 1, čiže začne počítať, 0 (prvý cyklus), 1 (druhý cyklus) a cyklus skončí a vykonáva sa makro ďalej.

Zvyšok kódu je už jasný, užívateľské definované číslo sa násobí s výsledkom. Tak dostaneme mocninu rôzneho čísla.

Pozastavme sa ešte nad kľúčovým slovom Next s premennou n. Práve tu dôjde k navýšeniu premennej n o hodnotu definovanej v slove Step. Taktiež Next vyhodnotí, či je v intervale od 0 do 1(v našom konkrétnom prípade).

Príkaz GoTo

Príkaz GoTo využívame na skoky v programe. Najčastejšie sa využíva vtedy, ak je splnená/nesplnená podmienka a potrebujete skočiť na iné miesto vykonávania kódu.

2. príklad: Praktické využitie príkazu GoTo

Sub obvodStvorca   REM začiatok procedúry
sirkaHrany = InputBox("Zadajte celočíselnú šírku hrany štvorca")   REM vstup od užívateľa
If IsNumeric(sirkaHrany) = False Then GoTo Chyba   REM testovanie podmienky
Obvod% = 4 * Cint(sirkaHrany)   REM výpočet
Print "Obvod je: " & Obvod   REM vypísanie na obrazovku
GoTo Koniec   REM využitie príkazu skoku
Chyba: REM kam príkaz GoTo skočí
Print "Fakt mám vás naučiť písať celé čísla?!"   REM výpis
Koniec:  REM kam príkaz GoTo skočí
End Sub   REM koniec procedúry

Výsledok: obvod štvorca, čiže užívateľ zadá napríklad číslo 6, tak obvod štvorca bude 24.

Vstup od používateľa Vstup od používateľa

Výsledok Výsledok

Rozbor: Užívateľ najprv zadá vstupný udaj, ktorý sa vyhodnotí. Ak užívateľ nezadá číslo, tak GoTo príkaz nasmeruje vykonávanie kódu na inom mieste. V tomto prípade vypíše na obrazovku text a končí. Ak užívateľ zadá číslo, vypočíta sa obvod štvorca a následne GoTo ho presunie vykonávanie programu až na Koniec. To znamená, že ak napíšeme „Chyba:“, tam skočí program, ak za GoTo dáme slovo Chyba.

Ešte si povšimnite prevod z reťazca na číselnú hodnotu pomocou CInt.  Pomocou InputBox sme dostali údaj vo forme reťazca, ktorý ale musíme prekonvertovať na celočíselnú hodnotu.

Príkaz Exit

Potrebovali by ste v nejakom vetvení programu ukončiť makro, bez toho aby sa ďalej vykonávalo makro? Použijeme na to príkaz Exit.

Exit sa často využíva v cykloch, kde sú mnoho podmienok a ak jedna nastane, vykoná čo požadujete a skončite makro. Ukážeme si to na príklade, ktorý už poznáte.

3. príklad: Využitie príkazu Exit

Sub obvodStvorca  REM začiatok procedúry
sirkaHrany = InputBox("Zadajte celočíselnú šírku hrany štvorca")  REM vstup od užívateľa
If IsNumeric(sirkaHrany) = False Then GoTo Chyba   REM testovanie podmienky
Obvod% = 4 * Cint(sirkaHrany)   REM výpočet 
Print "Obvod je: " & Obvod   REM výpis na obrazovku
Exit Sub   REM ukončenie makra pomocou Exit
Chyba: REM kam skočí príkaz GoTo
Print "Fakt mám vás naučiť písať celé čísla?!" REM výpis na obrazovku 
End Sub  REM koniec procedúry 
(Jako ve škole) Průměr: 3.89 | Hodnotilo: 9
 

Komentáře

user avatar neutr
Odpovědět
Programovanie makier v LibreOffice: Cykly (2)
22. 06. 2016, 11:07:34
Tedy je to správně, ale ne úplné.

Například cyklus FOR .. Next má nepovinnou proměnnou Step. Tam je jenom příklad na inkrementaci. Ale já osobně jsem se dlouho trápil dekrementací, respektive záporným krokem. Ten je možné definovat stejně ale od 'n' do hodnoty startu která může být 0, nebo jedna ale také každé jiné číslo < 'n'.

Například při probírání a následném mazání řádků se musí jet od konce k začátku takže například :
Máme řádky od 5....50 a chceme smazat podle nějakého explicitního vyjádření podmínky. Například že je řádek ve sloupci A prázdný (Empty).
'---------------------------------------------
Sub NejakeMojeMakro
Dim Doc as Object
Doc=ThisComponent
Sheet=Doc.Sheets(0)
Dim Cell As Object
For i = 50 TO 5 Step - 1
Cell = Sheet.getCellByPosition(0, i)
IF Cell.string = "" Then
oRows = Sheet.getRows()
oRows.removeByIndex(i, 1)
End IF
Next i
End Sub
'---------------------------------------------
Také by bylo možné uvést jiný příklad cyklu - rekurzivní volání mezi makry nebo Funkcemi. V elementární rovině volá makro samo sebe :

Sub Main 'Voláme jenom jednou na začátku nebo iVar postavíme jako Global
Rekurze(0)
End Sub

Sub Rekurze(ByVal iVar as integer)
Dim iVal as integer
iVal = iVar + 1
print "Počet opakovaných volání je " & iVal
IF iVar = 10 Then
print "Tohle je 11. a poslední rekurzivní volání"
Exit Sub
End If
Rekurze(iVal)
End Sub
'---------------------------------------------

Rekurze je asi neobvyklé a také poměrně nebezpečené řešení protože stačí malá chyba a máte zacyklováno. Následně funguje jen úplné vypnutí Calcu.

Ale na podobném principu funguje GoSub i když se vrací jen podle Return těsně za místo svého volání (GoSub).

Ještě bych chtěl dodat, že pokročilejší mohou v cyklu For...Next nadefinovat například (Start TO End) jak proměnné a opakově je uvnitř cyklu (v rámci jeho běhu) přestavovat. Samozřejmě výhodou je to u vnořených cyklů. Například ze třetího vnořeného cyklu dojdeme k dalšímu hledání - a redefinujeme Start-Cíl (a třeba i krok) a hopneme pomocí GoTo Před 2. vnořený cyklus, respektive na konec 1. (základního cyklu ap). Můžeme například jen měnit následující proměnnou stejného cyklu 'Step' ap.

Já jsem používal podobný systém jako klopný obvod Sub1 volalo dokolečka Sub2 a to zase zpátky Sub1. Podmínky vyhodnocované pomocí Select Case v jednom makru a ve druhém se nastavoval čas pomocí Wait. Takovéhle smyčky musí mít v sobě zabudované Exit(y), Stop(y) nebo alespoň Print(y) aby bylo možné zabránit nekonéčnému cyklování. Mají ale jednu vyjímečnou vlastnost. Dovedou procházet stromové struktury v závoslosti na změně která není pravidelná. V takovém případě jsou Cykly For a Do určitou tvrdostí bez možnosti dobré optimalizace.

Případ s kontrolou pomocí Wait kontroloval externí vstupy, ale stavěl jsem i cyklování tohoto typu pro třídění do různých sloupců - respektive listů ap.
user avatar Eduard Boldižár
Odpovědět
Re:Programovanie makier v LibreOffice: Cykly (2)
23. 06. 2016, 11:54:04
vďaka za pár upresnení
user avatar lp.
Odpovědět
Re:Programovanie makier v LibreOffice: Cykly (2)
23. 06. 2016, 15:24:40
Většinu uvedených možností nepoužívám, domnívám se, že nepatří k dobrému stylu programování. Začátečníkům jejich použití rozhodně nedoporučují, pokročilejší vědí, jak to napsat slušně.

Abych to upřesnil.

Procedura mám mít jeden vstup a jeden výstup (gosub je prapravěk programování a více exit sub také nesvědčí o promyšleném návrhu)

Přepisování řídících proměnných cyklu for znamená, že zoufalý programátor se chce úplně zbláznit.
user avatar neutr
Odpovědět
Programovanie makier v LibreOffice: Cykly (2)
23. 06. 2016, 19:48:50
For lp.
Určitě vím že jste z nás nejlepší, ale nyní jste prokázal, že jste nepotkal správní zadání abyste mohl vyhodnotit to co uvádím jako další možnosti.

Představte si kód kde potřebuji často cyklus For a mnohdy neopakovatelně, vnořené cykly a podobně. Při tom stačí udělat jedinou funkci která načítá proměnné - tedy start-stop, krok a typ podmínky.

Takto nahradíme i několikanásobně vnořené cykly a voláte jen název s parametry. Představte si jen ukončení všech cyků (to jinak nežli Exit For nejde) a to nehovořím o zapsání cyklů do kódu.

Používání rekurzivního volání se mi osvědčilo právě při řešení úloh s rekurzivním řešením mnoha podle proměnných. Zabývám se kombinatorikou a tam existuje problém výběru podle obsahu (jednic, dvojic ap.) Například "rozebrat" množinu kombinací Combin(16,4) do čtverců (problém Latinských čtverců) tak aby každý jeden čtverec 4x4 obsahoval jen samé různé jednice.
Následně se musí čtverce jednic setřídit tak aby byl vytvořen systém obsahující všechny dvojice. Ale to není konec. Pak se ješty tyto sytémy musí setřídit do množin (sloupců) které obsahují všechny trojice. Podmínka je žádné opakování, použití všech různých tipů (řádků). Podobně Se řeší všechny čtverce (5x5, 6x6, 7x7, ...).
Teprve při takovém zadání byste docenil iterace rekurzivním voláním. Tedy i bez definovaných cyklů (For, Do..). Návratové hodnoty na začátek probíhají stejně jako "traverz" podle binárních stromů, respektive řízení grafem. A nejde o nějakou okrajovou úlohu. Tedy jak pro koho. Tohle se týká teorie čísel a podobné věci. To samozřejmě nikoho moc nebere. Takže se nedivím že by se o takových potřebách vědělo v širší laické veřejnosti. Tím se Vás nechci dotknout, ale ta potřeba je skutečná. nejde o přežitek - ale o Vaši neznalost obecných potřeb. Já také všechny alternativy a možnosti neznám.
user avatar lp.
Odpovědět
Programovanie makier v LibreOffice: Cykly (2)
24. 06. 2016, 09:32:03
Proti rekurzi nic nemám. Měla by se ale používat opatrně. Ve srovnání s normálním cyklem bývá srozumitelnější, běžně se používá v některých oborech matematiky, takže některé algoritmy lze snadno přepsat do kódu. V basicu její náhrada cyklem často vede k rychlejšímu kódu, proto dávám cyklu přednost. Pokud se setkáte s problémy s odezvou při použití rekurze, tak o tom uvažujte.

V basicu manipulace s krokem a podmínkou ukončení v cyklu for obvykle vede k těžko srozumitelnému kódu, který se obtížně ladí a obtížně upravuje.

Tyto manipulace lze nahradit cykly do, while, until. K tomu jsou určené. Opakovaně vnořované cykly lze často zpřehlednit vhodnou procedurou/funkcí. A ani rekurzi bych nevyloučil.

K příkazu exit for jsem se nevyjadřoval. Prostě je užitečný, v článku ale nebyl zmíněn. Snažím se nekomentovat to co v článku není. Je to věcí autora a já nevím co plánuje pro další pokračování.

Přidat názor

 

Nejsou podporovány žádné značky, komentáře jsou jen čistě textové. Více o diskuzích najdete v nápovědě. Diskuzi můžete sledovat pomocí RSS kanálu.

 
Eduard Boldižár

Eduard Boldižár

Som redaktorom stránky astrotech.cz. Mám 24 rokov. Čas trávim v IT škole. Medzi moje záľuby patrí astronómia, sci-fi literatúra a programovanie.

 
 
 
woo jaw demo hz