In vielen Programmiersprachen steht das assoziative Array als Datenstruktur zur Verfügung. Doch was ist eigentlich ein assoziatives Array? Nun, bei normalen Arrays werden die Feldelemente über einen numerischen Index angesprochen. So bezeichnet z.B. A[5] das fünfte Feldelement. Bei einem assoziativen Array kommt nun statt des numerischen Index ein in der Regel eine beliebige Zeichenkette ins Spiel. Es könnte so z.B. ein Feldelement über A[„Birnen“] und ein zweites über A[„Aepfel“] angesprochen werden.
Zeichenkettenlisten in DOCUcontrol
Die Programmiersprache DOCUcontrol von GSD scheint zunächst keine assoziative Arrays zu unterstützen. Doch verfügt DOCUcontrol über die „Zeichenkettenliste“ als Datentyp. In den Elementen dieser Zeichenkettenlisten können nun Schlüssel-Wert-Paare in der Form Feldname=Feldwert hinterlegt werden. DOCUcontrol bietet für das Setzen und Auslesen des Wertes zu einem Schlüssel entsprechende Makrofunktionen an. Zur Veranschaulichung zunächst ein kleines Beispielprogramm:
DBSTRINGSET AssocArray; STRING Key; STRING Value; INT i; Key = "Birnen"; IF( DBStrGetFieldValue( AssocArray, Key, Value ) ) DBStrSetField( AssocArray, Key, IntToStr( StrToInt( Value ) + 1 ) ); ELSE DBStrSetField( AssocArray, Key, "1" ); ENDIF IF( DBStrGetFieldValue( AssocArray, Key, Value ) ) DBStrSetField( AssocArray, Key, IntToStr( StrToInt( Value ) + 1 ) ); ELSE DBStrSetField( AssocArray, Key, "1" ); ENDIF Key= "Aepfel"; IF( DBStrGetFieldValue( AssocArray, Key, Value ) ) DBStrSetField( AssocArray, Key, IntToStr( StrToInt( Value ) + 1 ) ); ELSE DBStrSetField( AssocArray, Key, "1" ); ENDIF FOR( i=1; i<= DBStrGetCount( AssocArray); i++ ) DBStrGetIndexField( AssocArray, i, Key, Value ); Trace( "String: " + AssocArray[i] ); Trace( "Key: " + Key + " Value: " + Value ); NEXT
Was macht nun dieses Beipiel? Es sollen Birnen und Äpfel gezählt werden. Zunächst werden die verwendeten Variablen deklariert. Die wichtigste Variable ist „AssocArray“, die als Zeichenkettenliste (DBSTRINGSET) abgebildet ist. Die Variable Key wird zunächste mit dem String „Birnen“ vorbelegt. Danach wird mittels der Makrofunktion „DBStrGetFieldValue“ versucht den Wert zum Key „Birnen“ zu ermitteln. Da das Array aber noch gar keine Key-Value-Paare enthält, liefert die Funktion „FALSE“ zurück un die IF-Abfrage verzweigt in den „ELSE“-Zweig. Die Makrofunktion „DBStrSetField“ legt nun ein neues Schlüssel-Wert-Paar für den Key „Birnen“ an und setzt den Wert auf „1“.
Wir führen nun die gleiche Programmsequenz nochmals aus und lassen auch den Key unverändert. Jetzt ist die Abfragebedingung erfüllt – es existiert ja bereits ein Schlüssel-Wert-Paar mit dem Schlüssel „Birnen“ – und es wird der beim Aufruf ermittelte Wert (die „1“) zunächst in eine Zahl umgewandelt, 1 addiert, die resultierende 2 wieder in einen String („2“) gewandelt und mit der schon bekannten Funktion „DBStrSetField“ wieder den Schlüssel „Birnen“ zugeordnet.
Im dritten Abschnitt des Programm wird zunächst der Key auf „Aepfel“ geändert. Der Programmteil ist wieder identisch zu den beiden ersten Abschnitten. Da es noch kein Key-Value-Paar zum Schlüssel „Aepfel“ gibt, ist nun wieder der ELSE-Zweig von Bedeutung. Es wird ein neues Paar mit dem Key „Aepfel“ angelegt und der Wert „1“ zugeordnet.
Die abschließende FOR-Schleife dient nur der Ergebnisausgabe, die folgendermaßen aussieht:
String: Birnen=2 Key: Birnen Value: 2 String: Aepfel=1 Key: Aepfel Value: 1
Bei jedem Schleifendurchlauf wird zunächst der jeweilige String aus der Zeichenkettenliste ausgegeben. Hier sieht man, dass jedes Key-Value-Paar in der Form „Schlüssel=Wert“ in jeweils einem String der Zeichenkettenliste abegelgt ist. Die Makrofunktion „DBStrGetIndexField“ ermöglicht es über den Schleifenindex auf jeden String in der Liste zuzugreifen und getrennt den Schlüssel und den dazu gehörigen Wert zu erhalten.
Beipiel mit „benannten Makro“
DOCUcontrol ist eine prozedurale Programmiersprache (siehe dazu auch den Beitrag „Die Makroprogrammiersprache DOCUcontrol von GSD“) und ermöglicht die Erstellung von eigenen Makrofunktionen, den sog. „Benannten Makros“. Daher können wir die wiederholt genutzte Programmsequenz mit der IF-Abfrage und dem ELSE-Zweig in eine eigene Makrofunktion packen, um dies dannn wiederholt aufzurufen.
Mit der Makrofunktion „OFLOAssocArrayAddInc“
BOOL OFLOAssocArrayAddInc( DBSTRINGSET &AssocArray, STRING Key, INT Inc ) BOOL Result = FALSE; STRING Value; Result = DBStrGetFieldValue( AssocArray, Key, Value ); IF( Result ) Result = DBStrSetField( AssocArray, Key, IntToStr( StrToInt( Value ) + Inc ) ); ELSE Result= DBStrSetField( AssocArray, Key, IntToStr( Inc ) ); ENDIF RETURN( Result );
würde sich der Programmcode von oben wesentlich übersichtlicher und kürzer gestalten:
DBSTRINGSET AssocArray; INT i; STRING Key; STRING Value; OFLOAssocArrayAddInc( AssocArray, "Birnen", 1 ); OFLOAssocArrayAddInc( AssocArray, "Birnen", 1 ); OFLOAssocArrayAddInc( AssocArray, "Aepfel", 1 ); FOR( i=1; i<= DBStrGetCount( AssocArray); i++ ) DBStrGetIndexField( AssocArray, i, Key, Value ); Trace( "String: " + AssocArray[i] ); Trace( "Key: " + Key + " Value: " + Value ); NEXT
Für die Beschleunigung der Zugriffe stellt DOCUcontrol eine weitere Makrofunktion zur Verfügung: "DBStrUseFieldMap".
Der beschleunigte Zugriff muss vor den ersten Zugriff auf das assoziative Array aktiviert und nach dem letzten Zugriff wieder deaktiviert werden:
- Einschalten:
DBStrUseFieldMap( AssocArray, TRUE );
- Ausschalten:
DBStrUseFieldMap( AssocArray, FALSE );
Und nun viel Spaß bei der Verwendung von "Assoziativen Arrays" in DOCUcontrol.
[of_autor]