Programmeren in REXX/Functies deel 2: verschil tussen versies

Verwijderde inhoud Toegevoegde inhoud
GuyDC (overleg | bijdragen)
Kleine aanpassingen
GuyDC (overleg | bijdragen)
Aanvullingen en verbeteringen
Regel 5:
 
Zoals steeds zullen resultaten tussen « en » worden getoond. Als er sprake is van een '''pad''' karakter, dan dient dit karakter om de (kortste) string op te vullen. Standaard wordt daar de spatie voor gebruikt.
 
=Beheer van datums en tijd=
Omdat datums en tijden geen gebruik maken van het tientallig stelsel is het werken ermee niet altijd eenvoudig en vraagt het grote aandacht. Fouten zijn snel gemaakt.
==TIME==
'''time'''([optie])
Met deze functie kan men de huidige tijd opvragen. Deze kan in verschillende formaten worden verkregen (enkel eerste karakter is daarbij nodig):
*Time('''N'''ormal) «15:57:48» (dit is de standaard-optie)
*Time('''C'''ivil) «3:57pm» (bij ons weinig gebruikt)
*Time('''L'''ong) «15:57:48.315000» (microseconden)
*Time('''H'''ours) «15» (uren sinds het begin v/d dag)
*Time('''M'''inutes) «957» (minuten sinds het begin v/d dag)
*Time('''S'''econds) «57468» (seconden sinds het begin v/d dag)
En nog twee speciale opties:
*Time('''E'''lapsed) «0.45455» (misschien)
*Time('''R'''eset) «10.03100» (misschien)
De eerste reeks behoeft weinig meer uitleg, behalve dat bij het '''L'''ong formaat, men op PC systemen geen grotere nauwkeurigheid dan milliseconden moet verwachten.
 
Als de functie '''time''' meermaals in hetzelfde statement wordt opgeroepen dan zal ze steeds dezelfde waarde teruggeven. Het is alsof de tijd dan even stilstaat. Bovenstaande resultaten zijn allemaal samen in één statement uitgevoerd, dus slaan de uitkomsten op dezelfde tijd.
 
De twee laatste opties vragen wel wat meer uitleg. Ze laten toe de tijd te meten die een taak erover heeft gedaan. Het is dus een soort chronometer.
<br>Bekijk deze volgorde:
call time 'R' /* zet de chronometer op 0, Reset dus */
/* ...een eerste reeks bewerkingen... */
say 'Reeks 1 nam' time('E') 'seconden in beslag.'
/* ...een tweede reeks bewerkingen... */
say 'Reeksen 1 en 2 namen samen' time('R') 'seconden in beslag.'
/* ...een derde reeks bewerkingen... */
say 'Reeks 3 duurde' time('E') 'seconden.'
In het eerste statement doen we een '''Reset''' van de chronometer. We zetten hem op nul. Vermits we niet geïnteresseerd zijn in de tijd die de chronometer op dat moment had gebruiken we een '''call''' bevel.
<br>Na de eerste reeks bewerkingen vragen we de '''Elapsed''' (verlopen) tijd op. De chronometer wordt daarbij niet terug op nul gezet, en zal dus blijven voortlopen.
<br>Na de tweede reeks bewerkingen vragen we weer de verlopen tijd op, maar tegelijkertijd zetten we de chronometer terug op nul.
<br>Uiteindelijk vragen we hoeveel tijd de derde reeks bewerkingen in beslag namen.
 
Noteer ook dat REXX slechts één chronometer bezit. Als hij wordt gestart in een subroutine, dan zal hij zijn waarde verliezen (en terug op nul vallen) bij het verlaten van de subroutine.
 
Hier volgen een aantal voorbeelden van tijdsrekening:
parse value time() time('S') with TijdNu DagSeconden
parse var TijdNu uu ':' mm ':' ss /* splits tijd in uren, minuten en seconden */
AantalSeconden=uu*3600 + mm*60 + ss /* hoeveel is dat in seconden */
say AantalSeconden=DagSeconden /* &#171;1&#187; want anders maakten we een fout */
Plus4min= AantalSeconden + 4*60 /* doe er 4 minuten bij */
/* Nu terug omzetten naar uu:mm:ss formaat... */
uu = Plus4min % 3600 /* Gehele deling */
if uu>23 then uu=uu-24 /* Misschien middernacht overschreden bij optelling */
rest = Plus4min // 3600 /* Rest na deling door 3600 (= aantal sec in 1 uur */
mm = rest % 60 /* Omzetten naar minuten via gehele deling */
ss = Plus4min // 60 /* Seconden zijn rest na deling door 60 */
Say 'Binnen 4 minuten zal het' right(uu,2,0)':'right(mm,2,0)':'right(ss,2,0) 'zijn.'
Het laatste deel is zeker een functie waard als men deze omzetting vele malen moet uitvoeren. Ze kan er dan in een zeer compacte vorm als volgt uitzien:
S2T: Procedure /* Zet een aantal Seconden om in normale Tijdformaat */
parse arg secs .
if secs > 86400 then secs=secs-86400 /* Meer dan 24 uur ? */
return right(secs % 3600,2,0) &#124;&#124; ':' &#124;&#124;,
right(secs // 3600 % 60,2,0) &#124;&#124; ':' &#124;&#124;,
right(secs // 60,2,0)
Bestudeer deze functie nog eens aandachtig zodat alle aspecten ervan duidelijk worden. Ze lijkt misschien nogal cryptisch, maar ze is alvast performant omdat er geen werkvariabelen worden aangemaakt.
 
==DATE==
'''date'''([optie])
Het oorspronkelijk formaat, met slechts één mogelijke parameter ''optie'', is nogal rudimentair. Men kan ermee de huidige datum in verschillende formaten opvragen. De ''optie'' (eerste letter is daarbij voldoende) bepaalt het formaat. We vernoemen enkel de voornaamste die men in alle REXX implementaties zal terugvinden:
*'''N'''ormal - dit formaat is standaard als geen optie wordt meegegeven. We krijgen de datum in de vorm '''dd mnd jjjj''', bv. 16 mar 2011 (maand in 3 karakters, Engelse namen);
*'''B'''asedate - het aantal dagen sinds 1 januari van het jaar 1. Er wordt hier geen rekening gehouden met de aanpassingen aan de kalender zoals o.a. Paus Gregorius ze doorvoerde in 1582. Voor meer informatie over
tijdrekening, zie [[w:Jaartelling|dit artikel]];
*'''D'''ays - het aantal dagen sinds het begin van dit jaar;
*'''E'''uropean - de datum in verkort Europees formaat (dd/mm/jj);
*'''M'''onth - de maand in dit jaar, niet afgekorte Engelse naam, bv. "May";
*'''O'''rdered - de datum in formaat jj/mm/dd. Kan dienen om te sorteren, maar het jaartal heeft slechts 2 posities;
*'''S'''orted - vandaar dat dit formaat beter aangepast is om te sorteren: jjjjmmdd;
*'''U'''sa - in Amerikaans formaat: dd/mm/jj;
*'''W'''eekday - de dag van de week in niet afgekorte Engelse tekst, bv. "Saturday".
OORexx biedt ook nog het '''L'''anguage formaat aan, waarbij de datum in lokaal formaat wordt gegeven, bv. 17 januari 2011. Het lokaal formaat wordt in de systeeminstellingen bepaald. Een REXX programma mag geen veronderstellingen maken omtrent het resultaat omdat het programma op een ander systeem in de prak kan lopen als er een andere land-instellingen is gemaakt.
 
Kortom, de meest zinvolle formaten zijn N, B, S, D, M en W.
 
Bij de eeuwwisseling, en om de jaar-2000 problematiek te kunnen aanpakken werd deze functie drastisch uitgebreid. De datum kan nu variabel zijn (dus niet enkel die van vandaag). Meer nog, de datum kan via de functie worden omgezet van één formaat in een ander waarbij scheidingstekens kunnen gekozen worden. Dit is een voorbeeld:
Gisteren = date('Normal',date('B')-1,'B')
''Gisteren'' zal de waarde &#171;18 Nov 2011&#187; hebben als het vandaag 19 november 2011 zou zijn.
 
Laten we hierbij een beetje meer uitleg geven:
*de eerste parameter bepaalt nog steeds het formaat waarin we de datum willen terugkrijgen;
*de tweede parameter is de datum die moet worden omgevormd. In dit geval gebruiken we '''date('B')''' om de basisdagen te krijgen en trekken we er één van af om naar gisteren over te gaan;
*de derde parameter maakt aan de functie duidelijk in welk formaat de tweede parameter is opgegeven.
Bovenstaand voorbeeld is het enige waarmee we met datums kunnen rekenen. Daarom is de '''basedate''' zo belangrijk. Dagen bijtellen of aftrekken van andere formaten heeft weinig zin of is zelfs onmogelijk. '''date('N')-1''' zal bijvoorbeeld een ''bad arithmetic operation'' geven, want date('N') is geen getal.
 
Dus, als we een datum ter beschikking hebben in een variabele, dan kunnen we die omvormen. Laten we nog een voorbeeld bekijken:
sdate=19530422 /* Dit is een Sorted datum */
say 'Kris is geboren op' date('W',sdate,'S')',' date(,sdate,'S')
Het antwoord dat we hier mogen verwachten is &#171;Kris is geboren op Wednesday, 22 Apr 1953&#187;. Mooi is dat nog niet. Willen we het volledig in het Nederlands vertalen, dan moeten we wat meer moeite doen, bijvoorbeeld zo:
sdate=19530422 /* Dit is een Sorted datum */
dagen='maandag dinsdag woensdag donderdag vrijdag zaterdag zondag'
maanden='januari februari maart april mei juni',
'juli augustus september oktober november december'
basisdatum=date('B',sdate,'S') /* omzetten van sdate naar basisdatum */
/* Restdeling van basisdatum door 7 geeft een cijfer van 0 tot 6 */
/* waarbij 0 staat voor maandag en 6 voor een zondag */
dagnr=(basisdatum // 7)
dag = word(dagen,dagnr + 1) /* index mag niet nul zijn */
parse var sdate jjjj 5 mm 7 dd /* opsplitsen van sdate */
say 'Kris is geboren op' dag',' dd word(maanden,mm) jjjj
Nu wordt het resultaat &#171;Kris is geboren op vrijdag, 22 april 1953&#187;. We kunnen dat wat inkorten:
dag=word(dagen,date('B',sdate,'S')//7+1)
say 'Kris is geboren op' dag',' substr(sdate,7) word(maanden,substr(sdate,5,2)) left(sdate,4)
Om te besluiten geven we nog een paar voorbeelden waarbij speciale scheidingstekens worden gebruikt. Die tekens kunnen we als 4de en 5de parameter geven bij de oproep van de '''date''' functie. De 4de parameter zegt welk teken in het resultaat moet verschijnen, en de 5de parameter zegt in de plaats van welk teken dit moet komen. Als het vandaag 19 november 2011 is, dan geven:
IsoDate = date('S',,,'-') &#171;2011-11-19&#187; (toevoegen scheidingsteken)
bdate = date('B',IsoDate,'S',,'-') &#171;734459&#187; (weglaten scheidingsteken)
mindate = date(,,,'-') &#171;19-Nov-2011&#187;(toevoegen scheidingsteken)
In het eerste geval voegen we mintekens toe aan een Sorted datum (jjjjmmdd). REXX weet waar het moet&nbsp;!
<br>In het tweede geval zetten we die IsoDate weer om naar een Basedate, waarbij we de functie meegeven dat er mintekens in de IsoDate zitten.
<br>In het derde geval vragen we mintekens toe te voegen in de Normale datum, en weer weet REXX hoe het moet.
 
=NUMERIC - nauwkeurigheid van bewerkingen bepalen=
Regel 27 ⟶ 136:
 
=Manipulatie van getallen=
De meeste functies en bewerkingen die we hier beschrijven zullen tot fouten leiden indien de tokens geen geldig getal voorstellen. DaaromDe is denu volgende functie omlaat toe te kunnen anticiperen op dat soort fouten.
<!------------------------------------------------->
==DATATYPE - controle op type gegevens==
Regel 51 ⟶ 160:
say datatype('3','Logical') datatype(12,'O') &#171;0 0&#187;
say datatype('01000001'b,'B') &#171;0&#187;
In het laatste geval is de binaire string gelijk aan '41'x, of de letter &#171;A&#187; in het ASCII stelsel, en dat is geennoch combinatieeen vankarakter 1- en('31'x) noch een karakter 0-karakters ('30'x).
 
Met de gelijkwaardige types '''V'''ariable en '''S'''ymbol wordt getest of de string een syntactisch geldige naam isheeft voorom eenals REXX variabele, dusgebruikt ofte hij kan gebruiktkunnen worden als linker lid van een assignatie.
say datatype("AB%","Symbol") &#171;0&#187;
 
Regel 64 ⟶ 173:
*'''&#171;VAR&#187;''' als het een geldige naam is en ook is geïnitialiseerd.
Hier is het belangrijk te begrijpen dat we het te onderzoeken token als een constante moeten schrijven, anders onderzoeken we de '''inhoud''' van het token op geldigheid.
 
Voorbeelden:
a=10
say symbol("A") &#171;VAR&#187;
say symbol(a) &#171;BAD&#187;
say symbol(hello) &#171;LIT&#187;
say symbol("Hello") &#171;LIT&#187;
In het tweede geval maken we de fout de variabele niet als constante te schrijven, en dus testen we "10", en dit is geen geldig token. In het derde geval lukt het nog net omdat ''hello'' nog niet geïnitialiseerd is, en dus zichzelf als waarde heeft. Maar het laatste voorbeeld is dus veel veiliger.
<!------------------------------------>
==ABS - Absolute waarde van een getal==
'''abs'''(''getal'')
Deze functie geeft de absolute waarde (positieve waarde) van het getal terug. HetDe getal alsopgegeven parameter kan natuurlijk een uitdrukking zijn die na interpretatie in een getal resulteert, anders is er een uitvoeringsfout (93: Target must be a number).
eerst moet worden geïnterpreteerd. Het resultaat moet een getal worden, anders is er een uitvoeringsfout (93: Target must be a number).
say abs(24-12) &#171;12&#187;
say abs(12-24) &#171;12&#187;
Regel 79 ⟶ 195:
say max(a,b,24) min(4,-1*b,24) &#171;24 -14&#187;
<!------------------------------------>
==RANDOM - een willekeurig getal genereren==
'''random'''([''maximum''])
of
'''random'''([''minimum,maximum''['',zaadje''])
Deze functie geeft een willekeurig, (positief geheel) getal, standaardterug. Zonder parameters is het getal gelegen tussen 0 en 999. Maar er kan een ''minimum'' en/of een ''maximum'' worden meegegeven waartussen het getal moet liggen (het bereik is wel beperkt tot 100000).
 
Indien men een herhaling van dezelfde willekeurige reeks getallen wil bekomen, dan kan men een ''zaadje'' (een getal) meegeven bij de eerste oproep. DeMet vanhetzelfde danzaadje afzullen gegenereerdede getallen zullendie dan gegenereerd worden steeds in dezelfde volgorde wordenterugkomen. gegenereerdHandig als men een spelletje wil later herbeginnen met dezelfde kaarten of teerlingworpen.
<!------------------------------------>
==SIGN - wat is het teken van een getal&nbsp;?==
'''sign'''(''getal'')
Het antwoord is &#171;-1&#187; voor een negatief ''getal'', &#171;0&#187; indien het ''getal'' nul is en &#171;1&#187; voor een positief getal.
say sign(-12 * -4) &#171;1&#187;
<!------------------------------------>
==TRUNC - decimalen laten vallenweglaten==
'''trunc'''(''getal''[,''decimalen''])
Kapt het ''getal'', '''zonder afronding''', af bij het aantal opgegeven ''decimalen''. StandaardBij wordenontstentenis allevan decimaleneen weggelatenaantal en''decimalen'' houdt men eenenkel het geheel getal over.
 
Wil men een afgerond getal bekomen, dan moet men gebruik maken van de nu volgende '''format''' functie die we nu beschrijven.
<!------------------------------------>
==FORMAT - een getal formatteren voor uitvoer==
Regel 111 ⟶ 227:
Merk het verschil tussen '''trunc''' en '''format''' wat de afronding betreft.
<!---------------------------------------------------------------------------->
==Omzetten van formaten==
==Vertalen tussen karakter, decimaal, hexadecimaal of binair==
Een reeks functies laat toe getallendata om te zetten van één formaat [karakter(C), decimaal(D), hexadecimaal(X) of binair(B)] naar een ander om te zetten.
<!------------------------------------>
===C2D - van karakter naar decimaal omzetten===
'''c2d'''(string[,lengte])
Deze functie zal de binaire waarde van karakterreeks ''string'' omzetten naar een decimaal getal. Hiermee wordt bedoeld dat de ''string'' als een opeenvolging van bits wordt gezien, en dat die reeks dan als decimaal getal wordt geïnterpreteerd.
 
Indien een lengte wordt opgegeven, dan wordt de string als een getekend getal (negatief als linkse bit=0) van die lengte beschouwd.
Een binaire waarde kan geïnterpreteerd worden als een absolute waarde, of een getal met teken. In het laatste geval zal het getal negatief zijn als de eerste bit op 1 staat. Lees voor meer informatie over negatieve binaire getallen het artikel [[w:2-complement|Two's complement]].
Dit zijn voorbeelden op een PC
 
(met ASCII karaktertabel):
Dit zijn voorbeelden op een PC, dus voor een ASCII karaktertabel:
say c2d('A') &#171;65&#187;
say c2d('a') &#171;97&#187;
say c2d(' ',5) &#171;32&#187;
say c2d('AB') &#171;16706&#187;
say c2d('FF'x) &#171;255&#187;
say c2d('FF'x,1) &#171;-1&#187;
say c2d('FF'x,2) &#171;255&#187;
In het laatste 2 gevallen hebben we een lengte meegegeven. Met een lengte 1 hebben we binair "11111111", en dus eenhet negatief
(complementair2-complement) getal -1. Met de lengte 2 hebben we binair echter "0000000011111111", en dat is dan weer het positief getal 255 voorstelt.
<!------------------------------------->
===C2X - karakterreeksvan hexadecimaalkarakter noterennaar hexadecimaal===
'''c2x'''(string)
Onze string wordt nu omgezet in zijn hexadecimale notatie.
Regel 136 ⟶ 253:
say c2x(' A') &#171;2041&#187;
say c2x('11111111'b) &#171;FF&#187;
===D2C - van decimaal naar karakter vertalen===
'''d2c'''(getal)
Het getal wordt omgezet naar een karakterreeks.
say d2c(12) &#171;♀&#187; (dit is een controlekarakter&nbsp;!)
say d2c(65) &#171;A&#187;
say d2c(6645351) &#171;efg&#187;
<!------------------------------------->
===D2X - van decimaal naar hexadecimaal vertalen===
'''d2x'''(getal)
Het getal wordt omgezet innaar eenhexadecimale hexadecimaal getalnotatie.
say d2x(10) &#171;A&#187; (dit is '0A'x, een controlekarakter)
say d2x(c2d('K')) &#171;4B&#187;
<!------------------------------------->
===X2C - van hexadecimaal naar karakter vertalen===
'''x2c'''(hexadecimale-string)
De hexadecimale string wordt terug naar karakters omgezet. DezeDe karakters zijn dan niet noodzakelijk leesbaar en als ze resulteren in controlekarakters kunnen onverwachte dingen gebeuren.
say x2c('4B') &#171;K&#187;
say x2c('7E7E') &#171;~~&#187;
say x2c('4B'x) Fout: Only 0-9, a-f, A-F, and blank are valid; found "K"
Het laatste voorbeeld is een fout die regelmatig gemaakt wordt. De parameter moet niet in hexadecimale REXX notatie geschreven worden, enkel de hexadecimale karakters zijn nodig.
say x2c('7E7E') &#171;~~&#187;
<!------------------------------------->
===X2D - van hexadecimaal naar decimaal vertalen===
'''x2d'''(hexadecimale-string)
Ditmaal wordt de hexadecimale string omgezet naar de decimale waarde ervan.
Regel 157 ⟶ 280:
say x2d('4B') &#171;75&#187;
<!------------------------------------->
===B2X - van binair naar hexadecimaal vertalen===
'''b2x'''(binaire-string)
De bits worden omgezet in een meer leesbare hexadecimale vorm.
Regel 163 ⟶ 286:
say b2x(11110000) &#171;F0&#187;
<!------------------------------------->
===X2B - van hexadecimaal naar binair vertalen===
'''x2b'''(hexadecimale-string)
Het omgekeerde van voorgaande functie.
say x2b(4B) &#171;01001011&#187;
say x2b(b2x(11110000)) &#171;11110000&#187;
Regel 171 ⟶ 294:
<!----------------------------------------------------------------------->
==Binair rekenen==
Met onderstaande functies kan binair worden gerekend.
{|border="1" style="border-collapse:collapse;border:1px solid silver;"
* 1 AND 1 = 1 / 1 AND 0 = 0 / 0 AND 0 = 1
|-
* 1 OR 1 = 1 / 1 OR 0 = 1 / 0 OR 0 = 0
|&nbsp;1&nbsp;||&nbsp;AND&nbsp;||&nbsp;1&nbsp;||=||&nbsp;1&nbsp;
* 1 XOR 1 = 0 / 1 XOR 0 = 1 / 0 XOR 0 = 0
|-
|&nbsp;1&nbsp;||&nbsp;AND&nbsp;||&nbsp;0&nbsp;||=||&nbsp;0&nbsp;
|-
|&nbsp;1&nbsp;||&nbsp;OR&nbsp;&nbsp;||&nbsp;1&nbsp;||=||&nbsp;1&nbsp;
|-
|&nbsp;1&nbsp;||&nbsp;OR&nbsp;&nbsp;||&nbsp;0&nbsp;||=||&nbsp;1&nbsp;
|-
|&nbsp;1&nbsp;||&nbsp;XOR&nbsp;||&nbsp;1&nbsp;||=||&nbsp;0&nbsp;
|-
|&nbsp;1&nbsp;||&nbsp;XOR&nbsp;||&nbsp;0&nbsp;||=||&nbsp;1&nbsp;
|}
<!------------------------------------->
===BITAND - bit per bit AND-en===
'''bitand'''(string1[,string2][,pad])
say c2x('A') &#171;41&#187;
say x2b(41) &#171;01000001&#187;
say bitand('11111111'b,'A') &#171;A&#187;
say bitand('00001111'b,'A') &#171;@&#187;
<!------------------------------------->
===BITOR - bit per bit OR-en===
'''bitor'''(string1[,string2][,pad])
say c2x(bitor('11111111'b,'A')) &#171;FF&#187;
say bitor('00001111'b,'A') &#171;O&#187; ('4F'x)
<!------------------------------------->
===BITXOR - bit per bit XOR-en===
'''bitxor'''(string1[,string2][,pad])
say c2x(bitxor('11111111'b,'A')) &#171;BE&#187; ('10111110'b)
=Beheer van datums en tijd=
==TIME==
'''time'''([optie])
Met deze functie kan men de huidige tijd opvragen. We kunnen de tijd in verschillende formaten opvragen (enkel eerste karakter is daarbij nodig):
*Time('''N'''ormal) &#171;15:57:48&#187; (dit is standaard-optie)
*Time('''C'''ivil) &#171;3:57pm&#187;
*Time('''L'''ong) &#171;15:57:48.315000&#187;
*Time('''H'''ours) &#171;15&#187; (uren sinds begin van de dag)
*Time('''M'''inutes) &#171;957&#187; (minuten sinds begin van de dag)
*Time('''S'''econds) &#171;57468&#187; (seconden sinds begin van de dag)
En nog twee speciale opties:
*Time('''E'''lapsed) &#171;0.45455&#187; (misschien)
*Time('''R'''eset) &#171;10.03100&#187; (misschien)
De eerste reeks behoeft weinig meer uitleg. Onthou alleen dat als de functie '''time''' meermaals in hetzelfde statement wordt opgeroepen het steeds dezelfde waarde zal teruggeven. Het is alsof de tijd stilstaat. Bovenstaande resultaten zijn allemaal samen in één statement uitgevoerd, dus zijn de uitkomsten gelijkwaardig.
 
{{75%}}
De twee laatste opties vragen wel wat meer uitleg. Ze laten toe de benodigde tijd van een taak te meten. Het geeft een soort chronometer dus.
Bekijk deze volgorde:
call time 'R' /* zet de chronometer op 0, Reset dus */
/* ...een aantal bewerkingen... */
say 'De bewerking nam' time('E') 'seconden in beslag.'
/* ...presteer nog wat extra werk... */
say 'Tot hiertoe duurde alles samen al' time('R') 'seconden.'
/* ...en nog wat extra bewerkingen... */
say 'Deze laaste bewerkingen duurden' time('E') 'seconden.'
In het eerste statement doen we een '''Reset''' van de chronometer. We zijn niet geïnteresseerd in de tijd die nu in de chronometer zat, vandaar dat we een '''call''' instructie gebruiken.
<br>Na een eerste reeks bewerkingen vragen we de '''Elapsed''' (verlopen) tijd op. De chronometer wordt niet terug op nul gezet, en zal dus blijven voortlopen.
<br>Na een tweede reeks bewerkingen vragen we weer de verlopen tijd op, maar tegelijkertijd zetten we de chronometer terug op nul.
<br>Uiteindelijk vragen we hoeveel tijd de derde reeks bewerkingen in beslag namen.
 
Noteer ook dat REXX slechts één chronometer heeft. En als men hem start in een subroutine, dan zal hij zijn waarde verliezen (en terug op nul vallen) bij het verlaten van de subroutine. Men kan er m.a.w. geen extra aanmaken lokaal voor elke subroutine.
 
Hier volgen een aantal voorbeelden van tijdsrekening:
parse value time() time('S') with TijdNu DagSeconden
parse var TijdNu uu ':' mm ':' ss /* splits tijd in uren, minuten en seconden */
AantalSeconden=uu*3600 + mm*60 + ss /* hoeveel is dat in seconden */
say AantalSeconden=DagSeconden /* &#171;1&#187; want anders maakten we een fout */
Plus4min= AantalSeconden + 4*60 /* doe er 4 minuten bij */
/* Nu terug omzetten naar uu:mm:ss formaat... */
uu = Plus4min % 3600 /* Gehele deling */
if uu>23 then uu=uu-24 /* Misschien middernacht overschreden bij optelling */
rest = Plus4min // 3600 /* Rest na deling door 3600 (= aantal sec in 1 uur */
mm = rest % 60 /* Omzetten naar minuten via gehele deling */
ss = Plus4min // 60 /* Seconden zijn rest na deling door 60 */
Say 'Binnen 4 minuten zal het' right(uu,2,0)':'right(mm,2,0)':'right(ss,2,0) 'zijn.'
Het laatste deel is zeker een functie waard als men deze omzetting vele malen moet uitvoeren. Ze kan er dan in een zeer compacte vorm als volgt uitzien:
ZetOmUUMMSS: Procedure /* Zet een aantal seconden om in uu:mm:ss formaat */
parse arg secs
if secs > 86400 then secs=secs-86400 /* Meer dan 24 uur ? */
return secs % 3600 &#124;&#124; ':' &#124;&#124; secs // 3600 % 60 &#124;&#124; ':' &#124;&#124; secs // 60
Bestudeer deze functie nog eens aandachtig om er alle aspecten van te begrijpen. Ze lijkt misschien nogal cryptisch, maar ze is alvast performant omdat er geen werkvariabelen worden aangemaakt.
 
==DATE==
'''date'''([optie])
Het oorspronkelijk formaat van deze functie was erg eenvoudig. Men kon er de huidige datum mee opvragen, in verschillende formaten. Deze formaten bekomt men door een optie mee te geven (eerste letter is daarbij voldoende). We vernoemen enkel de voornaamste (er kunnen er meer bestaan op bepaalde systemen):
*'''N'''ormal - dit is de standaard. De datum wordt in de vorm '''dd mnd jjjj''' gegeven, dus bv. 16 nov 2011;
*'''B'''asedate - het aantal dagen sinds 1 januari van het jaar 1. Er wordt hier geen rekening gehouden met de aanpassingen aan de kalender zoals o.a. Paus Gregorius ze doorvoerde in 1582. Voor meer informatie over
tijdrekening, zie [[w:Jaartelling|hier]];
*'''D'''ays - het aantal dagen sinds het begin van dit jaar; = 323 <<dagen verlopen in het huidig jaar
*'''E'''uropean - de datum in Europees, verkort formaat (dd/mm/jj)
*'''M'''onth - de maand in dit jaar, volle Engelse tekst, bv. "August";
*'''O'''rdered - de datum in formaat jj/mm/dd. Kan dienen om te sorteren, maar jaartal slechts in 2 posities;
*'''S'''orted - vandaar dat dit formaat te verkiezen is om te sorteren: jjjjmmdd;
*'''U'''sa - in Amerikaans formaat: dd/mm/jj;
*'''W'''eekday - de dag van de week in volle Engelse tekst, bv. "Saturday".
OORexx biedt ook nog het '''L'''anguage formaat aan, waarbij de datum in locaal formaat wordt gegeven, bv. 17 januari 2011. Een REXX programma mag geen veronderstellingen maken omtrent het geretourneerd formaat, want op andere systemen, met andere land-instellingen kan het totaal verschillen.
 
Kortom, de formaten die het meest zinvol zijn, zijn N, B, S, D, M en W.
 
Bij de eeuwwisseling, en om de jaar-2000 problematiek te kunnen aanpakken werd deze functie drastisch uitgebreid. De datum kan nu variabel zijn (dus niet enkel die van vandaag). Meer nog, de datum kan via de functie worden omgezet van één formaat in een ander waarbij scheidingstekens kunnen gekozen worden. Dit is een voorbeeld:
Gisteren = date('Normal',date('B')-1,'B')
''Gisteren'' zal de waarde &#171;18 Nov 2011&#187; hebben als het vandaag 19 november 2011 zou zijn.
 
Laten we hierbij een beetje meer uitleg geven:
*de eerste parameter bepaalt nog steeds het formaat waarin we de datum willen terugkrijgen;
*de tweede parameter is de datum die moet worden omgevormd. In dit geval gebruiken we '''date('B')''' om de basisdagen te krijgen en trekken we er één van af om naar gisteren over te gaan;
*de derde parameter maakt aan de functie duidelijk in welk formaat de tweede parameter is opgegeven.
Bovenstaand voorbeeld is het enige waarmee we met datums kunnen rekenen. Daarom is de '''basedate''' zo belangrijk. Dagen bijtellen of aftrekken van andere formaten heeft weinig zin of is zelfs onmogelijk. '''date('N')-1''' zal bijvoorbeeld een ''bad arithmetic operation'' geven, want date('N') is geen getal.
 
Dus, als we een datum ter beschikking hebben in een variabele, dan kunnen we die omvormen. Laten we nog een voorbeeld bekijken:
sdate=19530422 /* Dit is een Sorted datum */
say 'Kris is geboren op' date('W',sdate,'S')',' date(,sdate,'S')
Het antwoord dat we hier mogen verwachten is &#171;Kris is geboren op Wednesday, 22 Apr 1953&#187;. Mooi is dat nog niet. Willen we het volledig in het Nederlands vertalen, dan moeten we wat meer moeite doen, bijvoorbeeld zo:
sdate=19530422 /* Dit is een Sorted datum */
dagen='maandag dinsdag woensdag donderdag vrijdag zaterdag zondag'
maanden='januari februari maart april mei juni',
'juli augustus september oktober november december'
basisdatum=date('B',sdate,'S') /* omzetten van sdate naar basisdatum */
/* Restdeling van basisdatum door 7 geeft een cijfer van 0 tot 6 */
/* waarbij 0 staat voor maandag en 6 voor een zondag */
dagnr=(basisdatum // 7)
dag = word(dagen,dagnr + 1) /* index mag niet nul zijn */
parse var sdate jjjj 5 mm 7 dd /* opsplitsen van sdate */
say 'Kris is geboren op' dag',' dd word(maanden,mm) jjjj
Nu wordt het resultaat &#171;Kris is geboren op vrijdag, 22 april 1953&#187;. We kunnen dat wat inkorten:
dag=word(dagen,date('B',sdate,'S')//7+1)
say 'Kris is geboren op' dag',' substr(sdate,7) word(maanden,substr(sdate,5,2)) left(sdate,4)
Om te besluiten geven we nog een paar voorbeelden waarbij speciale scheidingstekens worden gebruikt. Die tekens kunnen we als 4de en 5de parameter geven bij de oproep van de '''date''' functie. De 4de parameter zegt welk teken in het resultaat moet verschijnen, en de 5de parameter zegt in de plaats van welk teken dit moet komen. Als het vandaag 19 november 2011 is, dan geven:
IsoDate = date('S',,,'-') &#171;2011-11-19&#187; (toevoegen scheidingsteken)
bdate = date('B',IsoDate,'S',,'-') &#171;734459&#187; (weglaten scheidingsteken)
mindate = date(,,,'-') &#171;19-Nov-2011&#187;(toevoegen scheidingsteken)
In het eerste geval voegen we mintekens toe aan een Sorted datum (jjjjmmdd). REXX weet waar het moet&nbsp;!
<br>In het tweede geval zetten we die IsoDate weer om naar een Basedate, waarbij we de functie meegeven dat er mintekens in de IsoDate zitten.
<br>In het derde geval vragen we mintekens toe te voegen in de Normale datum, en weer weet REXX hoe het moet.
{{25%}}
{{sub}}
Informatie afkomstig van https://nl.wikibooks.org Wikibooks NL.
Wikibooks NL is onderdeel van de wikimediafoundation.