Magic Disk 64

home to index to text: MD9206-KURSE-FLOPPY-KURS_1-B.txt

Kommen wir zu der flexibleren Methode.
Hierbei halten wir wie oben an den Feldlängen fest. Da wir nun ja wissen, wie lang ein Feldeintrag maximal sein kann, können wir im Prinzip vorausberechnen, an welcher Stelle im Datensatz welches Feld zu finden, bzw. abzulegen ist, ohne daß sich zwei Felder überschneiden. Hierbei müssen wir darauf achten, daß entweder ein Feld immer so lang ist, wie es maximal sein darf ( bei kürzeren Einträgen wird der Rest einfach mit SPACE-Zeichen aufgefüllt), oder aber wir verwenden den Trick mit der GET#- Abfrage beim Lesen. Letzeres ist wohl die eleganteste Lösung, da sie weniger Programmieraufwand erfordert und gleichzeitig die Leseund Schreibzugriffe beschleunigt, da immer nur so viele Zeichen gelesen werden, wie auch wirklich benötigt werden ( und nicht immer die maximale Feldlänge) . Wollen wir nun einmal ausrechnen, an welchen Bytepositionen die einzelnen Felder abgelgt werden:

Feldename   Beginn      Länge           
Name        1.Byte   20 Bytes           
Vorname    21.Byte   15 Bytes           
Straße     36.Byte   30 Bytes           
PLZ        66.Byte    4 Bytes           
Ort        70.Byte   30 Bytes           
Telefon   100.Byte   15 Bytes           

Anhand der Länge eines Feldes können wir immer die erste Position des folgendenden Feldes berechnen, indem wir die Anfangsposition im Datensatz mit der Feldlänge addieren.
Nun wissen Sie ja, daß man beim Positionierbefehl nicht nur die Datensatznummer, sondern auch die Byteposition innerhalb des gewählten Datensatzes angeben kann. Und über diese Methode können wir nun ganz bequem jede der 6 Feldpositionen einstellen und den Feldeintrag hineinschreiben. Beim Lesen können wir, da wir für jedes Feld ja die An- fangsposition innerhalb eines Datensatzes kennen, dieses ebenfalls direkt anwählen und Lesen. Das ist vor allem beim Sortieren einer REL-Datei von Vorteil, da wir nun nach allen sechs Feldern eine Datei beliebig sortieren können, ohne die übrigen fünf Felder noch extra einlesen zu müssen. Das erhöht die Arbeitsgeschwindigkeit ungemein. Ein anderer Geschwindigkeitsvorteil ergibt sich beim Ändern von Datensätzen. Wollen wir zum Beispiel in einer Adressdatei nur die Straße verändern, weil die betreffende Person umgezogen ist, so genügt es auf das Feld " Straße"( Byte 36 im entsprechenden Datensatz) zu positionieren und den neuen Eintrag hineinzuschreiben. Hierbei müssen Sie jedoch auch beachten, daß der neue Straßenname unter Umständen kürzer ist, als der alte. Wir müssen dann nämlich noch ein CHR$(255) nachschicken, damit unsere GET#- Schleife auch ihre Endmarkierung findet. Andernfalls würde Sie die rest- lichen Zeichen des alten Straßennamens mitlesen. Ein Beispiel:

Alte Straße      --> "Bahnhofstrasse 76"
Neue Straße      --> "Am Brunnen 2"     
Ergebnis beim                           
Lesen OHNE eine                         
neue Endmar-                            
kierung          --> "Am Brunnen 2se 76"

Schreiben Sie aber aich bitte nur dann ein CHR$(255) danach, wenn der neue Straßenname kleiner als die maximale Feldlänge ist. Andernfalls würden Sie wieder über die Feldgrenze hinausschreiben und so das erste Zeichen des darauffolgenden Feldes überschreiben!

SORTIEREN ODER INDIZIEREN:              

Oben habe ich schon einmal die Möglichkeit der Sortierung einer Datenbank angesprochen. Die augenscheinlich einfachste Art der Sortierung wäre wohl das alphabetische Ordnen der Einträge eines Feldes ( z. B. des Namensfeldes), und das anschließende Umkopieren der Datensätze, so daß im ersten Datensatz auch wirklich der alphabetisch erste und im letzten Datensatz der alphabetisch letzte Name steht. Diese Lösung verwendet aber wohl keiner, da man sich vorstellen kann, daß die Sortierung durch das Umkopieren der Datensätze einen extremen Zeitaufwand bedeutet ( gerade bei einfachen Sortieralgorithmen ist die Anzahl der Austausche zwischen zwei Einträgen ungemein hoch) . Zusätzlich erfordert diese Methode nach jedem Neueintrag das Umkopieren der kompletten REL-Datei, da ein neuer Datensatz ja ebenfalls irgendwo einsortiert werden muß, und damit alle folgenden Datensätze einen Datensatz weiter nach hinten rücken. Lassen Sie uns also diese Methode in dem Mülleinmer werfen und die schnelle, komfortable und flexible Methode herauskramen:" Indizierung" heißt das Zauberwort!
Im Prinzip bedeutet dieses Wort nicht mehr als " Sortieren", jedoch ist die Handhabung etwas anders. Hier möchte ich noch einmal auf das Beispiel der Adressverwaltung zurückgreifen. Gehen wir also davon aus, daß wir unsere Adressen nach den Namen der eingetragenen Personen ordnen wollen. Zu diesem Zweck lassen wir unseren Sortieralgorithmus nach und nach alle Namen aus der REL-Datei auslesen und alphabetisch in eine Liste einordnen. Dabei wollen wir uns zu jedem Namen auch seine Datensatznummer merken.
Letztere können wir dann als Referenz auf den alphabetisch richtigen Datensatz verwenden. Ich möchte Ihnen dies anhand eines Beispiels verdeutlichen. Nehmen wir einmal eine Adressdatei, die die folgenden vier Namenseinträge, in der Reihenfolge in der sie eingegeben wurden, enthält:

Satznummer   Eintrag (Name)             
     1       Müller                     
     2       Becker                     
     3       Schmidt                    
     4       Meier                      

Nun sortieren wir unsere Datei nach Namen und erhalten folgende Reihenfolge:

     2       Becker                     
     4       Meier                      
     1       Müller                     
     3       Schmidt                    

Die aphabetisch richtige Reihenfolge legen wir nun z. B. in einem Variablenfeld ab. Dieses Variablenfeld nennt man Index. Wenn wir nun den alphabetisch ersten Eintrag lesen wollen, so schauen wir uns einfach den ersten Eintrag in der Indexliste an, und lesen den Daten- satz ein, der dort steht - im Beispiel also den zweiten.
Damit wir nicht jedes mal neu sortieren müssen ist es ratsam die Indexliste in einem sequentiellen File auf Diskette abzuspeichern. Wenn wir nun jedesmal, wenn die Adressverwaltung gestartet wird das Indexfeld einlesen, so können wir ganz einfach und schnell alphabetisch geordnete Datensätze finden und bearbeiten. Ebenso sollten wir darauf achten, daß neue Datensätze in die Indexliste richtig einsortiert werden und der Index wieder neu auf Diskette gespeichert wird.
Die Indizierung bietet jedoch noch weitere Vorteile. So können wir auch ganz beliebig nach verschiedenen Feldern sortieren und gleichzeitig beide sortierten Dateien weiterverwenden. Wenn Sie Ihre Adressen manchmal besser über den Vornamen finden können, so ist es sinnvoll auch nach dem Vornamen zu indizieren und diesen Index als Alternative Verwenden zu können. Beim Umschalten zwischen zwei Indizes müssen Sie dann jeweils die neue Indexdatei einlesen. Dies ist sogar bequem möglich, da wir zu der einen offenen REL-Datei auch noch eine SEQ-Datei öffnen dürfen, ohne daß der 64 er verrückt spielt. Wir können so als deh eit den Index wechseln, ohne dabei noch umständlicherweise die REL-Datei schließen und anschließend wieder öffnen zu müssen.

EIN WORT ZU NUMERISCHEN EINTRÄGEN:      

Vielleicht wollen Sie irgenwann einmal auch numerische Einträge in einer REL-Datei speichern. Das wäre bei unserer Adressverwaltung zum Beispiel bei dem Postleitzahlenfeld sehr gut denkbar. In manchen Fällen kann uns das auch einen Speicherplatzvorteil im Gegensatz zu der Speicherung als String geben. Hierbei müssen wir jedoch immer gewisse Regeln beachten, sonst werden Sie ganz schön Probleme mit den Datensatzlängen bekommen. Schreiben Sie nämlich eine numerische Variable ( wie z. B." A" als Float-, oder " A%" als Integervariable) mittels " PRINT#2, A"( oder " PRINT#2, A%") in eine Datei, so wandelt die PRINT#- Routine Ihre Variable immer in eine Zeichenkette, also eine String, um. Wenn diese numerische Variable nun verschieden viele Stellen besitzen kann, so werden Sie ganz schöne Schwierigkeiten bekommen.
Logischerweise hat die Zahl "100" eine Stelle weniger als die Zahl "1000" . Hinzu kommt, daß auch noch ein "-" als Vorzeichen davor stehen kann und daß der PRINT#- Befehl immer noch ein SPACE-Zeichen ("") vor einer Zahl ausgibt, oder daß ganz kleine oder ganz große Zahlen in der wissenschaftlichen Schreibweise ( also z. B."3 .456+ E10") ausgegeben werden.
Wie lang sollen wir dann unser Feld nun machen? Eine Antwort darauf ist schwierig, da das dann immer auch ganz von dem Verwendungszweck abhängt. Entweder müssen Sie dem Benutzer schon bei der Eingabe der Zahlen gewisse Einschränkungen auferlegen, oder aber durch eigene Umkonvertierung einer Zahl eine bestimmte Bytelänge festlegen können.
Letzteres möchte ich hier als Beispiel aufzeigen. Wir wollen uns auf positive Integerzahlen beschränken, also ganze Zahlen ( ohne Nachkommastellen), die von 0 bis 65535 gehen. In diesem Fall genügt es eine solche Zahl in Lowund Highbyte aufzuspalten und die beiden CHR$- Codes zu speichern. In der Praxis sieht das ähnlich wie in der Syntax des Positionierbefehls für REL-Dateien aus:

ZA=1992                                 
HI=INT(ZA/256): LO=ZA-256*LO            
PRINT#2,CHR$(LO);CHR$(HI);              

Damit können S) e nun alle oben genannten Zahlen schreiben. Aber eben nur diese.
Möchten Sie z. B. Float-Zahlen schreiben, so sollten Sie sich überlegen, wie groß oder klein diese maximal sein können.
Dann können Sie sie sich einmal mit dem normalen PRINT-Befehl auf dem Bildschirm ausgeben lassen und die Stellen, die sie einnehmen abzählen. Wenn Sie sicher sein können, daß dies die maximale Länge einer Ihrer Zahlen ist, so können Sie sie als Feldlänge definieren. Beachten Sie aber auch immer, daß der PRINT#- Befehl vor einer Zahl immer ein Leerzeichen druckt und daß zusätzlich immer noch ein Minus-Zeichen vor einer Zahl stehen kann. Außerdem können Sie solche Zahlen auch nur mittels des INPUT#- Befehls wieder einlesen, weshalb Sie noch ein Zeichen mehr für das CR mitrechnen sollten.
Ein anderer Weg um Float-Zahlen zu speichern wäre das direkte übernehmen der 5- Byte-Mantissen- Darstellung, wie das Betriebssystem des 64 ers sie benutzt, jedoch ist diese Möglichkeit relativ kompliziert, da sie den intensiven Gebrauch von Betriebssystemsroutinen erfordert, wovon wir momentan die Finger lassen wollen ( in einer der späteren Folge: dieses Kurses werde ich aber noch einmal auf dieses Thema zurückkommen) .
So. Das wäre es dann wieder einmal für diesen Monat. In der nächsten Ausgabe der " Magic Disk" wollen wir uns mit den Direktzugriffsbefehlen der Floppy befassen, die es uns ermöglichen, auf die Diskettenblocks direkt zuzugreifen.

                                    (ub)

Valid HTML 4.0 Transitional Valid CSS!