Magic Disk 64

home to index to html: MD9206-KURSE-FLOPPY-KURS_1-B.html
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 vorausbe-
rechnen, an welcher Stelle im  Datensatz
welches  Feld  zu finden, bzw. abzulegen
ist, ohne daß  sich  zwei  Felder  über-
schneiden.  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 gleich-
zeitig  die  Lese-  und  Schreibzugriffe
beschleunigt, da immer nur so viele Zei-
chen gelesen werden, wie  auch  wirklich
benötigt  werden  (und  nicht  immer die
maximale Feldlänge). Wollen wir nun ein-
mal  ausrechnen, an welchen Bytepositio-
nen 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 folgenden-
den Feldes berechnen, indem wir die  An-
fangsposition   im   Datensatz  mit  der
Feldlänge addieren.                     
Nun wissen Sie ja, daß man beim Positio-
nierbefehl  nicht  nur die Datensatznum-
mer, sondern auch die  Byteposition  in-
nerhalb  des  gewählten  Datensatzes an-
geben kann. Und über diese Methode  kön-
nen wir nun ganz bequem jede der 6 Feld-
positionen einstellen und  den  Feldein-
trag  hineinschreiben. Beim Lesen können
wir, da wir für jedes Feld  ja  die  An-
fangsposition  innerhalb eines Datensat-
zes  kennen,  dieses  ebenfalls   direkt
anwählen  und  Lesen.  Das ist vor allem
beim Sortieren einer REL-Datei von  Vor-
teil,  da  wir nun nach allen sechs Fel-
dern eine Datei beliebig sortieren  kön-
nen,  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 be-
treffende Person umgezogen ist,  so  ge-
nügt  es  auf das Feld "Straße" (Byte 36
im entsprechenden Datensatz) zu positio-
nieren  und  den neuen Eintrag hineinzu-
schreiben.  Hierbei  müssen  Sie  jedoch
auch  beachten, daß der neue Straßenname
unter Umständen kürzer ist, als der  al-
te.  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 hinausschrei-
ben und so das erste Zeichen des darauf-
folgenden Feldes überschreiben!         
SORTIEREN ODER INDIZIEREN:              
Oben  habe ich schon einmal die Möglich-
keit der Sortierung einer Datenbank  an-
gesprochen. Die augenscheinlich einfach-
ste 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  Sortier-
algorithmen  ist  die Anzahl der Austau-
sche zwischen  zwei  Einträgen  ungemein
hoch). Zusätzlich erfordert diese Metho-
de nach jedem Neueintrag das  Umkopieren
der  kompletten  REL-Datei, da ein neuer
Datensatz ja ebenfalls irgendwo  einsor-
tiert werden muß, und damit alle folgen-
den 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 flexi-
ble 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 Adress-
verwaltung 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 ausle-
sen  und alphabetisch in eine Liste ein-
ordnen. 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 folgen-
den vier Namenseinträge, in der  Reihen-
folge  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 Na-
men und erhalten folgende Reihenfolge:  
     2       Becker                     
     4       Meier                      
     1       Müller                     
     3       Schmidt                    
Die   aphabetisch  richtige  Reihenfolge
legen wir nun z.B. in  einem  Variablen-
feld  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 bearbei-
ten.  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 wei-
tere Vorteile. So können wir  auch  ganz
beliebig nach verschiedenen Feldern sor-
tieren und gleichzeitig beide sortierten
Dateien weiterverwenden. Wenn  Sie  Ihre
Adressen manchmal besser über den Vorna-
men 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  be-
quem  möglich, da wir zu der einen offe-
nen REL-Datei auch noch  eine  SEQ-Datei
öffnen   dürfen,   ohne   daß  der  64er
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 bekom-
men. Schreiben Sie nämlich eine  numeri-
sche  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 Zeichenket-
te, also eine  String,  um.  Wenn  diese
numerische Variable nun verschieden vie-
le Stellen besitzen kann, so werden  Sie
ganz  schöne  Schwierigkeiten  bekommen.
Logischerweise hat die Zahl  "100"  eine
Stelle weniger als die Zahl "1000". Hin-
zu kommt, daß auch noch ein "-" als Vor-
zeichen  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  schwie-
rig, da das dann immer auch ganz von dem
Verwendungszweck  abhängt. Entweder müs-
sen Sie dem Benutzer schon bei der  Ein-
gabe  der Zahlen gewisse Einschränkungen
auferlegen, oder aber durch  eigene  Um-
konvertierung  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 Low- und Highbyte
aufzuspalten und die  beiden  CHR$-Codes
zu  speichern.  In  der Praxis sieht das
ähnlich wie in der Syntax  des  Positio-
nierbefehls 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 ei-
ner 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 wie-
der  einlesen, weshalb Sie noch ein Zei-
chen mehr für das CR mitrechnen sollten.
Ein anderer Weg um Float-Zahlen zu spei-
chern  wäre  das  direkte übernehmen der
5-Byte-Mantissen-Darstellung,  wie   das
Betriebssystem  des  64ers  sie benutzt,
jedoch  ist  diese  Möglichkeit  relativ
kompliziert,  da  sie den intensiven Ge-
brauch von  Betriebssystemsroutinen  er-
fordert,  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 befas-
sen, die es  uns  ermöglichen,  auf  die
Diskettenblocks direkt zuzugreifen.     
                                    (ub)



Valid HTML 4.0 Transitional Valid CSS!