1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
|
#limit (11.0)##pagelength (16.5)##block#
#start (2.0,0.0)#
#page (151)#
#headodd#
#center#EUDAS#right#%
#end#
#headeven#
%#center#EUDAS
#end#
#center#1
14 Ausdrücke in ELAN
14.1 Was sind Ausdrücke ?
In diesem Kapitel wollen wir uns mit ELAN-Ausdrücken beschäfti
gen, wie sie für EUDAS gebraucht werden. Natürlich kann dies keine
ernsthafte Einführung für ELAN-Programmierer sein - mit solchen
Ambitionen halten Sie sich am besten an die entsprechende ELAN-
Literatur.
Dieser Text richtet sich eher an den Benutzer, der kaum Erfah
rung mit ELAN hat, aber die Möglichkeiten von EUDAS optimal nut
zen will. Viele fortgeschrittene Fähigkeiten von EUDAS laufen ja
über ELAN-Programme.
#on("b")#Vorkommen#off("b")# Sie haben ELAN-Ausdrücke bereits an
verschiedenen
Stellen eingesetzt, wenn Sie sich mit den vorhergehenden Kapiteln
befaßt haben. ELAN-Ausdrücke werden in nahezu allen Verarbei
tungsfunktionen benötigt.
Im Druckmuster dienen sie dazu, den Inhalt eines Feldmusters
festzulegen. Die Definition einer Abkürzung besteht immer aus dem
Namen der Abkürzung und einem Ausdruck. Ebenso wird in einer
Gruppendefinition ein Ausdruck angegeben.
Beim Kopiermuster und beim Änderungsmuster besteht jeweils
die rechte Seite einer Anweisung aus einem Ausdruck. Weiterhin
werden Ausdrücke auch in anderen ELAN-Konstruktionen benötigt,
wie zum Beispiel direkt am Anfang einer IF-Anweisung.
#on("b")#Bedeutung#off("b")# Ein Ausdruck steht allgemein für einen Wert. Im
ein
fachsten Fall kann dies eine Konstante sein, der Wert des Aus
drucks ändert sich also nicht. Anderenfalls spricht man von einem
zusammengesetzten Ausdruck. Dessen Wert ergibt sich dann durch
die Ausführung der im Ausdruck angegebenen Operationen. Dieser
Wert kann je nach dem aktuellen Zustand des Systems verschieden
sein, da er jedes Mal neu berechnet wird, wenn er gebraucht wird.
Ein Beispiel für einen zusammengesetzten Ausdruck ist 2+2
Dieser Ausdruck steht für den Wert 4.
Der Wert eines Ausdrucks ist das, was uns eigentlich interes
siert. Beim Druckvorgang wird dieser Wert dann gedruckt, beim
Kopieren und Verändern in ein Feld eingetragen.
#on("b")#Zusammensetzung#off("b")# Ausdrücke lassen sich aus verschiedenen
Ele
menten zusammensetzen. Grundlage bilden die Konstanten. Konstan
ten können durch #on("i")#Operatoren#off("i")# miteinander verknüpft werden. So ist
in dem Ausdruck 2+3 das '+' ein Operator, der die Konstanten 2
und 3 verknüpft. Das Ergebnis der Verknüpfung hängt natürlich vom
jeweiligen Operator ab.
Wie Sie schon in der Schule gelernt haben ("Punktrechnung vor
Strichrechnung"), muß man die Reihenfolge der Operatoren festlegen,
wenn mehrere Operatoren im Spiel sind. Ähnliche Regeln gibt es für
alle Operatoren in ELAN.
Wenn eine andere Reihenfolge der Operatoren erwünscht ist,
können Sie diese durch Einsatz von Klammern verändern. Auch dies
dürfte Ihnen aus der Schule noch in Erinnerung sein. Der Unter
schied in ELAN ist lediglich, daß es dort einige zusätzliche Opera
toren gibt, die Ihnen nicht aus der Mathematik vertraut sind.
Ein weiteres Konstruktionselement von Ausdrücken sind #on("i")#Funk
tionen#off("i")#. Auch diese kennen Sie aus der Schule. Lediglich die
Schreibweise muß für den "dummen" Computer etwas ausführlicher
gehalten werden (Beispiel: sin (3.14 * x)).
Die Argumente der Funktion hinter dem Funktionsnamen müssen
auf jeden Fall in Klammern stehen. In der Terminologie der Pro
grammiersprachen spricht man von #on("i")#Parametern#off("i")#. Parameter können
wieder komplexe Ausdrücke sein. Bei Funktionen mit mehreren
Parametern werden diese durch Komma getrennt:
min (2.5 * x, x + 1.25)
14.2 Datentypen
Bevor wir beginnen, konkrete Ausdrücke zu behandeln, müssen wir
erst das Konzept der #on("i")#Datentypen#off("i")# einführen. Grundidee dabei ist,
daß es verschiedene Klassen von Werten gibt, die nicht einfach
untereinander gemischt werden können.
So gibt es in ELAN einen grundlegenden Unterschied zwischen
#on("i")#Zahlen#off("i")# und #on("i")#Texten#off("i")#. Texte bestehen aus einer beliebigen Aneinan
derreihung von Zeichen, die im Normalfall nur für den betrachten
den Menschen eine Bedeutung haben. Mit Zahlen kann man dagegen
Berechnungen anstellen.
Der tiefere Grund für die Trennung in verschiedene Typen ist
also, daß für jeden Typ gewisse Operationen definiert snd, die nur
für diesen Typ sinnvoll sind. So ist zum Beispiel die Addition der
beiden Texte "abc" und "-/-" völlig sinnlos.
Aber nicht nur die Operationen sind verschieden, sondern auch
die interne Darstellung im Rechner. So werden der Text "1234" und
die Zahl 1234 völlig anders gespeichert, obwohl man ihnen die glei
che Bedeutung beimessen könnte.
#on("b")#Grundtypen#off("b")# In ELAN gibt es vier verschiedene Grundtypen,
die für
uns wichtig sind. Sie können sich in ELAN auch eigene Typen
schaffen, dies geht jedoch weit über unsere Bedürfnisse hinaus.
Der in EUDAS am meisten verwendete Typ heißt #on("i")#TEXT#off("i")#. TEXT-
Objekte bestehen aus einer Folge von 0 bis 32000 Zeichen. Die Zei
chen entstammen einem Satz von 256 verschiedenen Symbolen, die
jeweils eine andere Darstellung haben. Einige der Zeichen lassen
sich überhaupt nicht darstellen, sondern führen bestimmte Funktio
nen aus (zum Beispiel Bildschirm löschen).
Sämtliche Feldinhalte einer EUDAS-Datei sind TEXTe, ebenso
die Zeilen von Textdateien. Auch Datei- und Feldnamen sind
TEXTe. Von daher besteht eigentlich kein Grund, warum Sie sich
außer zur Programmierung noch mit anderen Datentypen beschäfti
gen sollten.
Neben den Texten gibt es noch die Zahlen. Diese sind in ihrer
internen Darstellung so beschaffen, daß ein effizientes Rechnen mit
ihnen möglich ist. Andererseits können sie nicht mehr beliebige
Informationen darstellen, sondern haben eine sehr eingeschränkte
Bedeutung.
Um unterschiedichen Bedürfnissen gerecht zu werden, gibt es in
ELAN zwei verschiedene Zahltypen. Der Typ #on("i")#INT#off("i")# umfaßt nur ganze
Zahlen ohne Kommastellen. Damit die Zahl möglichst wenig Spei
cherplatz belegt, ist der Wertebereich bei den meisten Rechnern auf
-32768..32767 beschränkt (die krummen Zahlen ergeben sich wegen
der Binärarithmetik des Rechners). Dieser Typ eignet sich am besten
zum Abzählen und zum Auswählen aus einer festen Anzahl von
Objekten (zum Beispiel Feld 1 bis Feld 255).
Zum eigentlichen Rechnen gibt es den Typ #on("i")#REAL#off("i")#. Dieser umfaßt
auch Kommazahlen. Genauigkeit, Wertebereich und Darstellung sind
nahezu identisch mit den Möglichkeiten eines Taschenrechners. der
Typ REAL wird immer dann verwendet, wenn mit realen Größen
(Geldbeträge, physikalische Werte) gerechnet werden muß.
Zuletzt gibt es noch den Typ #on("i")#BOOL#off("i")#. Er hat nur zwei mögliche
Werte, nämlich TRUE (wahr) und FALSE (falsch). Er wird dazu benö
tigt, Ausdrücke zu schreiben, die den Zweig einer IF-Anweisung
bestimmen.
#on("b")#Denotation#off("b")# ELAN verfügt über einen strengen Typenschutz;
das
heißt, Objekte verschiedenen Typs dürfen nicht gemischt werden.
Daher muß schon bei der Schreibweise der Konstanten festgelegt
sein, welchen Typ die Konstante hat.
Bei Texten geschieht dies durch den Einschluß in Anführungs
striche. Die Anführungsstriche sorgen gleichzeitig auch für eine
Abgrenzung der Zeichen des Textes und des umgebenden Programms.
Sie kennen diese Schreibweise bereits von vielen Stellen in EUDAS.
Ebenfalls keine Probleme bereitet der Typ BOOL, da die
Schreibweise der beiden möglichen Werte TRUE und FALSE eindeutig
ist.
Problematisch wird es bei den Zahlen. Da die ganzen Zahlen in
den rationalen Zahlen enthalten sind, muß für die ganzen Zahlen
durch die Schreibweise festgelegt werden, zu welchem der beiden
Typen sie gehören. Man hat festgelegt, daß REAL-Zahlen immer mit
Komma geschrieben werden müssen, während Zahlen ohne Komma den
Typ INT haben (das Komma wird in ELAN bei den REAL-Zahlen in
internationaler Schreibweise als Punkt notiert).
So ist 4 eine INT-Zahl, während 4.0 den Typ REAL besitzt.
Denken Sie in Zukunft immer daran, welcher Zahltyp jeweils ver
langt wird und richten Sie die Schreibweise danach.
#on("b")#Unterschied zu Feldtypen#off("b")# Verwechseln Sie die hier
vorgestellten
Datentypen nicht mit den Feldtypen einer EUDAS-Datei. Die Feld
typen beziehen sich immer auf den gleichen Datentyp, nämlich
TEXT. Die Feldtypen bestimmen lediglich die spezielle Behandlung
des Feldes beim Suchen und Sortieren, während Datentypen tat
sächlich Unterschiede in der Speicherung und den anwendbaren
Operationen bedeuten.
Daher können Sie Feldtypen auch nach Bedarf ändern, während
der Datentyp eines Objekts ein für alle Mal feststeht. Merken Sie
sich, daß Feldinhalte in EUDAS immer den Typ TEXT haben.
#on("b")#Umwandlungen#off("b")# Obwohl verschiedene Datentypen nicht
miteinander
gemischt werden dürfen, können sie mit speziellen Funktionen in
einander umgewandelt werden. So ist zum Beispiel die Addition von
1 und 1.5 verboten, aber der folgende Ausdruck
real (1) + 1.5
liefert den Wert 2.5 mit dem Typ REAL. Umgekehrt geht die Um
wandlung mit der Funktion 'int', dabei werden jedoch die Nachkom
mastellen abgeschnitten. Weitere Hinweise dazu erhalten Sie im
Abschnitt 14.4.
Wichtiger jedoch ist die Umwandlung von Zahlen in TEXT-Ob
jekte. Was Sie auf Ihrem Bildschirm oder Ausdruck sehen, sind ja
immer nur Zeichenfolgen und damit Texte. Zahlen (INT oder REAL)
in ihrer internen Darstellung können Sie prinzipiell nicht sehen. Sie
müssen zur Darstellung immer in Texte umgewandelt werden.
Auch beim Rechnen mit Werten aus EUDAS-Dateien müssen
mehrere Umwandlungen stattfinden. Der Feldinhalt, der ja ein TEXT
ist, muß zunächst in eine Zahl umgewandelt werden. Dann wird mit
dieser Zahl gerechnet. Wenn das Ergebnis wieder in ein Feld einge
tragen oder gedruckt werden soll, muß eine Rückumwandlung in
einen Text vorgenommen werden.
Die zum Umwandeln benötigten Funktionen werden ebenfalls im
Abschnitt 14.4 besprochen.
#on("b")#Funktionsbeschreibung#off("b")# In den zwei folgenden Abschnitten
sollen
die wichtigsten Funktionen und Operatoren anhand von Beispielen
beschrieben werden. Da jede Funktion nur auf bestimmte Datentypen
angewendet werden kann, gibt es eine Notation, die genau die Form
eines Funktionsaufrufs festlegt.
INT PROC min (INT CONST a, b)
Die obige Schreibweise hat folgende Bedeutung: Spezifiziert wird die
Funktion 'min', die als Ergebnis einen INT-Wert liefert (das INT
ganz links). Die Bezeichnung PROC gibt an, daß es sich um eine
Funktion handelt. In Klammern ist dann angegeben, welche Parame
ter verwendet werden müssen. Die Funktion hat zwei Parameter,
beide vom Typ INT. Die Bezeichnung CONST gibt an, daß auch Kon
stanten verwendet werden dürfen (Normalfall).
Zu beachten ist, daß bei jedem Aufruf beide Parameter vorhan
den und vom Typ INT sein müssen. Anderenfalls gibt es eine Feh
lermeldung.
Die gleiche Schreibweise wird auch zur Spezifikation von Ope
ratoren verwendet:
INT OP + (INT CONST a, b)
Jedoch dürfen Operatoren nicht mit Parametern in Klammern ge
schrieben werden, sondern der Operator wird zwischen die Parameter
geschrieben.
Eine Besonderheit von ELAN ist es, daß es verschiedene Opera
toren und Funktionen mit gleichem Namen geben kann. Die Funktio
nen werden nur unterschieden nach dem Typ ihrer Parameter. So
gibt es nicht nur den oben genannten Operator '+', sondern auch
den folgenden:
REAL OP + (REAL CONST a, b)
Obwohl im Aussehen gleich, handelt es sich doch um verschiedene
Operatoren mit möglicherweise völlig verschiedener Wirkung. Dies
sieht man an diesem Beispiel:
TEXT OP + (TEXT CONST a, b)
Dieser Operator führt nun keine Addition aus, sondern eine #on("i")#Verket
tung#off("i")# zweier Texte. Je nach Typ der Parameter wird der entspre
chende Operator ausgesucht.
14.3 TEXT-Funktionen
In diesem Abschnitt wollen wir die wichtigsten Funktionen und
Operatoren zur Behandlung von Texten beschreiben. Wie Sie noch
sehen werden, spielt dabei aber auch der Typ INT eine gewisse
Rolle.
#on("b")#EUDAS-Abfragen#off("b")# Die wichtigste Funktion zur Abfrage von
Inhal
ten der aktuellen Datei sollten Sie bereits kennen:
TEXT PROC f (TEXT CONST feldname)
Neu ist eigentlich nur die Schreibweise der Spezifikation. Sie sollten
aber in der Lage sein, daraus einen konkreten Ausdruck zu kon
struieren. Bisher haben wir immer die Schreibweise
f ("Feldname")
verwendet. Dies ist jedoch nur ein Beispiel. Die korrekte Angabe
finden Sie oben.
Die Funktion 'f' darf natürlich nicht angewendet werden, wenn
keine Datei geöffnet ist. In die Verlegenheit kommen Sie aber nur
beim Ausprobieren, denn alle gefährlichen EUDAS-Funktionen sind
sonst gesperrt.
Falls das angegebene Feld nicht existiert, wird mit einer Feh
lermeldung abgebrochen. Beachten Sie, daß dies immer erst bei der
Ausführung festgestellt werden kann. Bei der Eingabe, zum Beispiel
eines Druckmusters, kann dies noch nicht überprüft werden.
Eine weitere Abfrage, die EUDAS während des Druckens ermög
licht, ist die Funktion
TEXT PROC lfd nr
Diese hat keine Parameter und liefert die laufende Nummer des
gedruckten Satzes.
Diese beiden Funktionen können als Ausgangsbasis dienen zur
Manipulation mit weiteren Funktionen.
#on("b")#Verkettung#off("b")# Zur Verkettung von Teiltexten gibt es den oben
schon
beschriebenen Operator '+'. Wenn Sie mehr als zwei Texte verketten
wollen, können Sie den Operator beliebig hintereinander verwenden:
f ("PLZ") + " " + f ("Ort")
Wie in diesem Beispiel können Sie sowohl Konstanten als auch Tex
te, die von anderen Funktionen geliefert werden, verketten. Beach
ten Sie, daß die Texte immer ohne Zwischenraum aneinandergehängt
werden; daher wird im obigen Beispiel ein Leerzeichen extra ange
geben.
Wenn Sie eine bestimmte Anzahl von gleichen Zeichen haben
möchten (zum Beispiel für horizontale Linien oder große Zwischen
räume), können Sie dafür folgenden Operator verwenden:
TEXT OP * (INT CONST anzahl, TEXT CONST einzeltext)
Hier sehen Sie als Beispiel einen Operator, der mit verschiedenen
Datentypen arbeitet. Sie müssen die Parameter jedoch immer in der
angegebenen Reihenfolge benutzen. Das folgende Beispiel ist kor
rekt:
20 * "-"
während dies nicht erlaubt ist:
"-" * 20
Wieder können Sie diesen Operator mit anderen Funktionen verknü
pfen:
"!" + 10 * " " + "!" + 5 * "-" + "!"
Da der Multiplikationsoperator Vorrang vor der Addition hat, kom
men Sie hier sogar ohne Klammern aus (überlegen Sie sich, wo ein
Fehler auftreten würde, wenn dies nicht so wäre). Als Ergebnis
dieses komplexen Ausdrucks ergäbe sich der folgende Text:
"! !-----!"
#on("b")#Teiltexte#off("b")# Um auch Teile von Texten bearbeiten zu können,
werden
die Zeichen eines Textes von 1 an (mit INT-Zahlen) durchnumeriert.
Anhand dieser Positionen können Sie Teiltexte extrahieren.
Damit Sie die Position des letztes Zeichens (und damit die An
zahl der Zeichen) erfragen können, gibt es die Funktion
INT PROC length (TEXT CONST text)
Wieviel Zeichen in einem Feld stehen, können Sie also mit
length (f ("Feldname"))
erfahren.
Einen Teiltext bekommen Sie mit der Funktion 'subtext'. Diese
gibt es in zwei Ausführungen.
TEXT PROC subtext (TEXT CONST text, INT CONST anfang)
liefert den Teiltext von einer bestimmten Position an (einschließ
lich) bis zum Textende. Mit
TEXT PROC subtext (TEXT CONST t, INT CONST anf, ende)
können Sie auch die Position des letzten Zeichens (einschließlich)
angeben. Daher würden die beiden folgenden Aufrufe
subtext (f ("Feldname"), 1)
subtext (f ("Feldname"), 1, length (f ("Feldname")))
den Feldinhalt unverändert liefern. Ein weiteres Beispiel:
subtext ("Ein Text als Beispiel", 5, 8)
liefert als Ergebnis "Text".
Es gibt noch den Operator 'SUB', der jeweils nur ein Zeichen
aus dem Text liefert:
TEXT OP SUB (TEXT CONST text, INT CONST stelle)
Der Aufruf ist gleichwertig zu einem Aufruf von 'subtext', in dem
beide Stellen gleich sind.
Bei beiden Funktionen wird nicht vorhandener Text einfach
ignoriert. So liefert
subtext ("Hallo", 4, 8)
das Ergebnis "lo" und
"Hallo" SUB 10
den leeren Text "".
#on("b")#Verschachtelte Ausdrücke#off("b")# Wie Sie bereits gesehen haben,
kann
man Ausdrücke ineinander verschachteln. Dies ist in unserem Fall
sehr nützlich, wenn Teiltexte bestimmt werden sollen, deren Posi
tion nicht konstant ist. Ein Beispiel, in dem 'length' bei der Fest
legung der Endposition verwendet wird, haben Sie weiter oben
bereits gesehen.
Als weitere Möglichkeit können Sie mit Positionen, die ja INT-
Zahlen sind, ganz normal rechnen. Folgender Ausdruck liefert zum
Beispiel die letzten drei Zeichen eines Feldes:
subtext (f ("Feldname"), length (f ("Feldname")) - 2)
Wichtig ist, daß ein Ausdruck, der wieder als Parameter für einen
anderen Ausdruck verwendet werden soll, den richtigen Typ hat,
der von dem anderen Ausdruck verlangt wird.
In dem obigen Beispiel muß als Position ein INT verwendet
werden. Diese Position wird vom Operator '-' berechnet. Es gibt
aber nur einen Subtraktionsoperator, der einen INT liefert, nämlich
den, der wiederum zwei INTs subtrahiert. Glücklicherweise sind
sowohl 'length' als auch die 2 vom Typ INT, anderenfalls wäre der
Ausdruck fehlerhaft. 'length' wiederum benötigt einen TEXT als
Parameter, der von der Funktion 'f' stammt, die als Parameter eben
falls einen TEXT verlangt.
Wie Sie sehen, kann es durchaus verwickelt zugehen, wenn ein
Ausdruck aus den verschiedensten Teilausdrücken unterschiedlichen
Typs zusammengesetzt ist. Die gleiche Überprüfung wie eben ge
schildert sollten Sie bei jedem Ausdruck vornehmen, damit keine
Fehlermeldung erscheint.
#on("b")#Variable Positionen#off("b")# Zur Berechnung von Positionen gibt es
noch eine weitere nützliche Prozedur, nämlich
INT PROC pos (TEXT CONST text, teiltext)
Sie liefert die Position, an der der angegebene Teiltext zum ersten
Mal in dem Text vorkommt, oder 0, wenn der Teiltext nicht darin
vorkommt. So ist
pos ("Hallo", "l") = 3
und
pos ("Hallo", "lo") = 4
und
pos ("Hallo", "xx") = 0
Diese Funktion kann zum Beispiel dazu verwendet werden, ein Feld
in mehrere Teile aufzuspalten. Sind zum Beispiel Name und Vorname
in einem Feld durch Leerzeichen getrennt hintereinandergeschrie
ben, liefert
subtext (f ("Name"), 1, pos (f ("Name"), " ") - 1)
den Vornamen und entsprechend
subtext (f ("Name"), pos (f ("Name"), " ") + 1)
den Nachnamen. Soll die Position erst ab einer gewissen Stelle ge
sucht werden, gibt es noch die folgende Variation der Funktion:
INT PROC pos (TEXT CONST text, teiltext, INT CONST ab)
Bei dieser Funktion wird erst ab der angegebenen Stelle einschließ
lich gesucht.
14.4 Rechenfunktionen
#on("b")#Umwandlungen#off("b")# Bevor mit dem Inhalt eines Feldes gerechnet
wer
den kann (auch wenn das Feld den Feldtyp ZAHL hat), muß der Wert
des Feldinhaltes als REAL-Zahl berechnet werden. Dazu gibt es die
Funktion
REAL PROC wert (TEXT CONST feldname)
Die Funktion 'wert' ignoriert alle Sonderzeichen in dem Feld außer
dem Minuszeichen (als Vorzeichen) und dem eingestellten Dezimal
komma. Wenn das Feld 'Summe' beispielsweise "-***20,09 DM" ent
hält, ergibt sich
wert ("Summe") = 20.09
Zum kaufmännischen Rechnen ist es manchmal erforderlich, den Wert
auf eine bestimmte Anzahl von Nachkommastellen zu runden. Diese
Anzahl kann man bei einer Variante von 'wert' als Parameter ange
ben:
REAL PROC wert (TEXT CONST feldname,
INT CONST kommastellen)
Mit den so erhaltenen Werten können Sie dann die weiter unten
beschriebenen Berechnungen durchführen. Bevor Sie das Ergebnis
jedoch drucken oder in ein Feld eintragen können, müssen Sie den
REAL-Wert wieder in einen TEXT verwandeln. Dazu dient die Funk
tion
TEXT PROC zahltext (REAL CONST wert,
INT CONST kommastellen)
Der übergebene Wert wird mit der gewünschten Anzahl von Komma
stellen als Text formatiert. Dazu wird der Wert gerundet. Außerdem
wird statt eines Punktes das eingestellte Dezimalkomma eingesetzt.
Die Länge des Textes richtet sich nach der Anzahl von benötigten
Stellen, es werden also keine führenden Nullen oder Leerzeichen
eingesetzt (dafür kann man den Text beim Drucken ja rechtsbündig
einsetzen).
Wird 0 als Kommastellen angegeben, wird auch kein Dezimal
komma erzeugt (Darstellung wie ein INT). Als Abkürzung können Sie
auch
TEXT PROC zahltext (TEXT CONST feldname,
INT CONST kommastellen)
als Ersatz für
zahltext (wert ("Feldname"), kommastellen)
verwenden. So kann ein Feld einheitlich zum Drucken formatiert
werden.
#on("b")#Arithmetik#off("b")# Sowohl mit INT- als auch mit REAL-Zahlen
(jedoch
nicht gemischt) können Sie die üblichen Rechenoperatoren '+', '-'
und '*' verwenden. Auch Minimum ('min') und Maximum ('max') sind
für zwei Parameter dieser Typen definiert.
Lediglich die Division wird bei beiden Typen unterschiedlich
gehandhabt. Für REAL-Zahlen gibt es den Operator '/' für die
übliche Division. Da die ganzzahlige Division eine andere Bedeutung
hat, wird dafür der Operator 'DIV' verwendet. Den Rest der ganz
zahligen Division liefert 'MOD'.
'abs' liefert den Wert eines REAL oder INT ohne das Vorzeichen.
Die Umwandlungsfunktionen 'int' und 'real' hatten wir ja bereits
weiter oben erwähnt.
Für REAL-Zahlen gibt es noch weitere mathematische Funktio
nen (Exponentialfunktion, Trigonometrie), die Sie am besten im
EUMEL-Benutzerhandbuch nachschlagen, wenn Bedarf dafür besteht.
14.5 Abfragen
#on("b")#IF-Abfragen#off("b")# Wie Sie schon im vorigen Kapitel gesehen
haben,
kann man in Druckmustern auch IF-Abfragen als Ausdrücke ver
wenden. Die IF-Abfragen können zwar auch ineinander verschach
telt werden, sie dürfen jedoch nicht mehr innerhalb eines normalen
Ausdrucks angewendet werden.
Eine IF-Abfrage enthält 3 Teilausdrücke in folgender Form:
IF 'BOOL-Ausdruck' THEN
'Ausdruck1'
ELSE
'Ausdruck2'
END IF
Der erste Ausdruck muß einen Wert vom Typ BOOL liefern, der ent
scheidet, welcher der beiden Teilausdrücke ausgewertet wird. Wir
werden gleich noch sehen, was für Möglichkeiten es da gibt.
Die beiden Teilausdrücke dürfen auch wieder IF-Abfragen sein,
sind sie es jedoch nicht, dürfen in ihnen dann keine IF-Abfragen
mehr vorkommen. Die IF-Abfragen liegen also immer auf der äußer
sten Ebene.
Die beiden Teilausdrücke dürfen einen beliebigen Typ haben, er
muß jedoch für beide gleich sein.
Als Ergebnis der IF-Abfrage wird 'Ausdruck1' geliefert, wenn
der BOOL-Ausdruck wahr ist, sonst 'Ausdruck2'.
#on("b")#Vergleiche#off("b")# Die wesentlichen Operationen, die boolesche
Ausdrücke
zur Verwendung in IF-Abfragen bilden, sind die Vergleichsoperato
ren:
= <> <= >= < >
Sie vergleichen jeweils zwei Elemente vom Typ TEXT, INT oder REAL
und liefern TRUE (wahr) oder FALSE (falsch). Selbstverständlich
können auch sie zwei zusammengesetzte Teilausdrücke vergleichen.
Eine Anwendung ist zum Beispiel der Test, ob ein Text in einem
anderen enthalten ist:
IF pos (f ("Betrag"), "DM") > 0 THEN
"deutsches Geld"
ELSE
"ausländisches Geld"
END IF
Die Funktion 'pos' wird hier dazu benutzt, festzustellen, ob es sich
um deutsches oder ausländisches Geld handelt.
Oft müssen jedoch mehrere Vergleiche miteinander kombiniert
werden. Zu diesem Zweck gibt es die beiden Operatoren AND (und)
und OR (oder). Damit AND das Ergebnis TRUE liefert, müssen beide
Vergleiche wahr sein, bei OR muß mindestens einer der beiden wahl
sein.
Die Reihenfolge aller dieser Operatoren ist so gewählt, daß
normalerweise keine Klammern benötigt werden. Funktionen haben
immer Vorrang vor Operatoren, bei den Operatoren kommt die Multi
plikation vor der Addition, dann kommen die Vergleiche, danach das
AND und danach das OR. Alle anderen Operatoren (#on("i")#insbesondere
SUB#off("i")#) teilen sich den letzten Rang.
Wenn Sie also in einem Ausdruck mehrere Vergleiche mit AND
und OR verknüpfen, und das OR soll stärker binden als das AND,
müssen Sie dies durch Klammern ausdrücken.
Den oben besprochenen Operator SUB sollten Sie immer in
Klammern setzen, wenn Sie ihn in einem Vergleich benutzen. Da er
die niedrigste Priorität hat, gäbe es sonst mit Sicherheit Fehler:
IF (f ("Name") SUB 1) = "M" THEN
"vielleicht Müller"
ELSE
"bestimmt nicht"
END IF
#on("b")#Refinements#off("b")# Bisher hatten wir gesagt, daß IF-Abfragen
nicht
innerhalb von anderen Ausdrücken verwendet werden dürfen. Diese
Einschränkung kann man umgehen, indem man #on("i")#Refinements#off("i")# verwen
det.
Ein Refinement hat im Druckmuster eine ähnliche Wirkung wie
eine Abkürzung, lediglich der Name darf nur mit Kleinbuchstaben
und Ziffern geschrieben sein und kann nicht als Feldmuster ver
wendet werden.
&abk :
subtext (f ("Name"), namensanfang) .
namensanfang :
IF pos (f ("Name"), " ") > 0 THEN
pos (f ("Name"), " ") + 1
ELSE
length (f ("Name"))
END IF .
Innerhalb von Refinements dürfen auch wieder andere Refinements
verwendet werden.
Auch in Kopier- und Änderungsmustern können Sie Refinements
verwenden. Hier müssen Sie jedoch darauf achten, daß alle Refine
ments am Ende gesammelt werden und vor dem ersten Refinement
ein Punkt stehen muß. Ebenso müssen die Refinements wie im
Druckmuster durch Punkte voneinander getrennt sein:
"Anrede" K anrede;
.
anrede :
IF f ("m/w") = "w" THEN
"Frau"
ELSE
"Herr"
END IF .
|