Generické programování
Princip
generického programování
Generický
program je popis algoritmu pro automatizované vytváření (generování)
programů. Povětšině jeden generický program dokáže generovat jednu třídu
programových modulů, vzácně jednu třídu ucelených programů.
Program
je v podstatě text, návod pro práci počítače. I když každý program je
jedinečný, části programu (moduly) jsou si na sebe podobné. Při respektování
společných znaků lze tedy vytvořit algoritmus generující textový soubor
(program) pomocí neměnného textu, popisujícího kostru modulů nebo celého
programu, která je doplňována proměnnými údaji, odpovídajícími potřebám
programátora.
Proměnné
údaje jsou v generickém algoritmu zadávány ve tvaru výrazů libovolného (přípustného)
typu a v případě potřeby jsou v závěrečné fázi automaticky převáděny
na znakový typ. (Na tomto principu je založeno i generování programů prostředky
třídy CASE - Low Level Case). Aby v generickém programu bylo možně snadno
odlišit výraz definující proměnnou část od kostry (nejde přece o opsání
výrazu) je tento obvykle uzavírán do speciálních oddělovačů. Nejčastěji
jsou to zdvojené ostré závorky << >>. V případě výskytu těchto
znaků v generovaném programu lze definovat jiné oddělovače.
Současně
si nutno uvědomit, že výsledek spojování kostry s proměnnými údaji nutno
zapsat do nějakého souboru nebo alespoň ho zobrazit (obecně do výstupního
souboru). Proto nutno mít nástroj, který otevírá takový soubor, umí přesměrovat
výstup do tohoto souboru a mimo něj, apod. Aby tento nástroj mohl rozeznávat
řádky generovaného textu od řádků programu, používá se pro předznačení
řádků generovaného textu speciálních znaků. (Nejčastěji znaků zpětné
lomítko \ back slash).
Generický
program se tedy velice podobá generovanému. Kromě toho, že generický
program umožní generovat více programů, daleko výstižněji popisuje
algoritmus než vygenerovaný program. Proto se doporučuje (ale nedodržuje) každý
program psát jako generický. V originální literatuře se generickým programům
říká TEMPLATE (šablony, vzory).
My
si pro první přiblížení představíme situaci, že máme v databázi adresy
a chceme rozeslat dopisy stejného textu (například pozvánky) na tyto adresy.
Neměnnou částí bude text dopisu a položky adresy budou proměnné údaje. Při
generování programů bude sice tento proces složitější, bude ho nutné
programově řídít, ale v podstatě jde o stejně řešený problém.
Nastavení
režimu generického programování
Režim
generování se ve FoxPro nastavuje příkazem:
SET
TEXTMERGE [TO
[<soubor>] [ADDITIVE]]
[WINDOW
<okno>] [SHOW | NOSHOW]
kde
klauzule ADDITIVE přesměruje výstup do rozpracovaného textového souboru
(generovaného programu). Když není zadaná fráze ADDITIVE a soubor
neexistuje, pak se vytvoří a otevře, jestliže existuje, bude jeho obsah přepsán,
Při otevření souboru se mu přiřadí manipulační číslo a uloží se do
systémové proměnné _TEXT. Soubor se uzavírá příkazem SET TEXTMERGE TO
bez parametrů. Fráze WINDOW přesměruje výstup do zadaného okna. Okno musí
být předtím vytvořeno, ale nemusí být aktivní. Zadáním fráze NOSHOW se
zabraňuje zobrazení výstupů na obrazovku nebo v okně. Zobrazení výstupů
na obrazovku nebo v okně se opět obnovuje příkazem SET TEXTMERGE SHOW.
Jelikož
bude nutno v generickém programu střídat režim výpočtů a generování,
nutno mít k dispozici přepínač těchto režimů. Přepínač má tvar:
SET
TEXTMERGE [ON | OFF]
SET
TEXT to pr309.prg
&& V praxi se klíčové slovo TEXTMERGE zkracuje na TEXT
SET
TEXT on
&& Standardně je off.
Definování
nestandardních oddělovačů
Když
není možné požít standardních oddělovačů výrazů vyhodnocovaných při
výstupu textu (to znamená znaků << >>), pak nutno programovat příkaz:
SET
TEXTMERGE DELIMITERS [TO]
[<expC1> [, <expC2>]]
kde
výraz <expC1> definuje levý oddělovač. Výraz <expC2> definuje
pravý oddělovač. Příkaz bez výrazů nastavuje standardní oddělovače.
(Není-li <expC2> zadáno, platí pro oba hodnota <expC1>.)
SET
TEXT DELI to "$$"
&& Nastavení zvolených oddělovačů
.....
SET
TEXT DELI
&& Nastavení standardních oddělovačů
Výstup
řádků textu (řádků generovaného programu)
Pro
vyznačení začátku vystupujícího řádku textu se používá znaku
\
s významem = text bude
vystupovat na novém řádku
\\
s významem = text bude
vystupovat na stejném řádku
\Zobrazení
textu
&& Na obrazovce se
zobrazí text, počínaje 0. sloupcem
Zobrazení
textu
SET
TEXT ON
SET
DATE TO GERMAN
\Dnes
je <<DATE()>>.
&&
Všimnete si tečky za datem
\\
Zítra bude <<DATE()+1>>.
&& Všimnete si mezery na začátku textu
Dnes
je 11.03.92. Zítra bude 12.03.92.
Výstup
větších textu
Pro
výstup větších textů, jako jsou například pozvánky nebo dopisy, by vyznačování
řádků vystupujících textů pomocí speciálních znaků bylo nepraktické.
Proto se používá textových závorek:
TEXT
<řádky
textu>
ENDTEXT
Cvičení
Generování
textu
Příklad
tisku pozvánek podle obsahu databázového souboru ADRESY. Komentář za čárou
není součástí programu.
SET
TEXT ON
&& Nastavení textu, výstup na obrazovku
SET
ESCAPE OFF
SET
DATE GERMAN
SET
TALK OFF
akce
= "KURS ZÁKLADŮ PROGRAMOVÁNÍ PC"
&&
Název akce
SET
DATE TO GERMAN
&& Naše
interpretace data
denz
= {2.3.92}
&& Datum
zahájení
denu
= {7.3.92}
&&
Datum ukončení
USE
adresy
&& Otevření souboru adres
SCAN
&&
Přes všechny záznamy souboru adres
CLEAR
&&
Začátek textu
osloveni=IIF(SUBSTR(rod_cis,3,2)>'12',"Vážená paní",;
&&
Vystupující text
"Vážený pane")
TEXT
Vojenská akademie
Brno
<<OSLOVENI>>
&&
Rozlišen mužský a ženský rod
<<allt(hodnost)>>.
<<allt(jmeno) + ' ' + allt(prijmeni)>>
&&
Výstup jména
&&
Výstup prázdného řádku
VÚ<<str(utvar,4)>>
&& Výstup
čísla útvaru
<<allt(mesto)>>
&&
Výstup města bez nadbyt. mezer
<<repl('-',len(allt(mesto)))>>
&&
Podtržení dlouhé jako název města
Dovolujeme
si Vás pozvat na
<<akce>>,
konaného
ve dnech <<denz>> až
<<denu>>
Zahájení
v 9.00 na učebně 8/20, Kasárna Šumavská.
<<date()>>
......................
vedoucí kursu
ENDTEXT
WAIT "Zmáčknete lib. klávesu" ;
+ ", K = konec" WINDOW
TO aa
IF aa$'kK'
RETURN
&&
Konec
ENDIF (aa$'kK')
ENDSCAN
Generování
programu
Ukázka
jednoduchého generátoru výstupů na obrazovku nebo do okna. Parametry příkazů
jsou uloženy v databázovém souboru (SAY309.DBF a SAY309.FPT). Všimneme si,
že výrazy jsou ukládány do memo položek. Důvod je jasný. Nemůžeme předem
vědět a omezit délku výrazu délkou znakové položky.
Struktura
souboru SAY309
┌───────────────────────────────────────────────────────
│ Structure for database: C:\KURS.PRG\SAY309.DBF
│ Number of data records: 3
│ Date of last update : 04/13/92
│ Memo file block size : 64
│ Field Field Name Type Width Dec Index
│ 1 RD1 Numeric 2
│ 2 SL1 Numeric 2
│ 3 OBJEKT Character 8
│ 4 VYRAZ Memo 10
│ 5 RD2 Numeric 2
│ 6 SL2 Numeric 2
│ ** Total ** 27
│
└───────────────────────────────────────────────────────
Obsah
souboru SAY309
┌─────────────────────────────────────────────────────────────────────
│ Record# RD1 SL1 OBJEKT VYRAZ RD2 SL2
│
│ 1 5 6 SAY "Pokusný text 1., objekt SAY" 0 0
│ 2 2 2 TO double 10 50
│ 3 7 6 SAY "Pokusný text 2., objekt SAY" 0 0
└─────────────────────────────────────────────────────────────────────
Programové
řešení
CLEAR
&& Výmaz
obrazovky
nazev="
Generování programu podle dat souboru say309"
@
1,1 SAY nazev
&&
Zobrazení názvu příkladu
@0,0
TO 2,LEN(nazev)+2 DOUBLE
&&
Rámeček kolem názvu
?
DEFINE
WINDOW pokus FROM 10,20 TO 24,78 COLOR SCHEME 12
&&
Okno pro zobrazení vygenerovaného programu
SET
TEXT TO pokus309_2.prg
&&
Název generovaného programu
SET
TEXT ON
&&
Nastavení režimu TEXTMERGE
\CLEAR
&&
Začátek programu
USE
say309
&&
Soubor s parametry
SCAN
DO generuj_vystup
&&
Vlastní generování
ENDSCAN
SET
TEXT OFF
&& Konec
generování
SET
TEXT TO
WAIT
"Konec CTRL+ENTER" WINDOW NOWAIT
MODIFY
COMM pokus309_2.prg WINDOW pokus
&&
Zobrazení programu, lze
editovat
RELEASE
WINDOW pokus
&& Výmaz
okna
CLEAR
CLEAR
PROGRAM
&& Výmaz
programu
PROCEDURE
generuj_vystup
\@
<<rd1>>, <<sl1>> <<alltrim(objekt)>>
&&
Řádek, sloupec objekt
IF
!EMPTY(rd2)
<<rd2>>, <<sl2>>
&& Souřadnice
ukončení jen když jsou
ENDIF
(!empty(rd2))
&& zadány
<<vyraz>>
Výsledný
program
┌──────────────────────POKUS309.PRG───────────────────────
│ CLEAR
│ @ 5, 6 SAY "Pokusný text 1., objekt SAY"
│ @ 2, 2 TO 10, 50 double
│ @ 7, 6 SAY "Pokusný text 2., objekt SAY"
└─────────────────────────────────────────────────────────