C 64
Software

Datenkreislauf – Die sequentielle Datenspeicherung

Als es noch keine Diskettenlaufwerke gab, standen lediglich Bandgeräte zur Datenspeicherung zur Verfügung. Und auf Bändern ist nur sequentielles Speichern möglich. Auch mit der Floppy kann man Daten sequentiell speichern, obwohl der Vorteil der Diskette, der direkte Zugriff auf Daten, nicht ausgenutzt wird.

Wenn Sie sich das Diskettenlaufwerk gerade erst gekauft haben, werden Sie sicher zu Beginn einige Schwierigkeiten haben, es auch richtig einzusetzen. Das erste, was man macht, wird das Laden und Abspeichern von Programmen sein. Daß Sie mit der Floppy noch viel mehr machen können, wissen Sie ja auch schon längst. Und sicher fallen Ihnen einige Möglichkeiten ein, die Sie wohl gerne realisieren möchten. Meistens sind das am Anfang eine Adressenkartei, eine Schallplattensammlung erfassen oder etwa seine Dias ordnen und auswerten. Wir möchten Ihnen den Einstieg etwas erleichtern und Sie Schritt für Schritt mit den Methoden der Datenverwaltung vertraut machen.

Es gibt verschiedene Arten von Dateien und unterschiedliche Methoden ihrer Verwaltung. Hauptsächlich sind das die sequentielle, die relative Datei und der Direktzugriff auf die Diskette.

Gerade für Anfänger ist die sequentielle Datei eine geeignete Methode, Daten zu verwalten. Diese Einfachheit ist allerdings verbunden mit einer gewissen Langsamkeit. Aber wenn sie sich erst einmal mit der sequentiellen Datenspeicherung auskennen, wird auch die relative Datei und die Direktzugriffsmethode kein großes Problem mehr für Sie darstellen. Außerdem gibt es genügend Probleme, für die eine sequentielle Datenspeicherung völlig ausreichend ist.

Zuerst sollen Sie einige wichtige Begriffe kennenlernen.

Sequentiell bedeutet hintereinander. Also alle Daten, die wir benutzen, werden hintereinander, sequentiell auf der Diskette gespeichert (bei Kassetten ist eine andere Methode gar nicht möglich).

Immer, wenn man von und über Dateien spricht, werden solche Vokabeln wie FELD, DATENSATZ oder auch RECORDS genannt. Was ist das eigentlich?

Der Computer ersetzt Karteikarten

Die meisten von Ihnen kennen eine Karteikarte. Auf dieser Karteikarte können mehrere Eintragungen stehen. Angenommen, Sie besitzen eine Adressenkartei, dann stehen auf jeder Karteikarte normalerweise der Vorname, Nachname, Straße, Postleitzahl und Ort und die Telefonnummer, manchmal auch der Geburtstag und andere wichtige Daten. Das sind die einzelnen Felder eines Datensatzes. Die Gesamtheit aller Felder auf einer Karteikarte bezeichnet man als einen Datensatz, also alle Daten, die zusammengehören. Somit besteht ein Datensatz aus mehreren Feldern. Und der Begriff Record ist nur die englische Bezeichnung für Datensatz. Alle Karteikarten, also alle Datensätze, nennt man eine Datei. Damit wären die wichtigsten Begriffe geklärt und wir können zum Wesen der sequentiellen Datei kommen.

Wie schon gesagt, werden bei dieser Dateiart alle Daten hintereinander (sequentiell) auf der Diskette gespeichert. Das sieht dann zum Beispiel so aus wie in Bild 1.

In dieser Reihenfolge stehen die Daten in einer sequentiellen Datei (bezogen auf das Beispielprogramm)

Angenommen, unsere Datei besitzt schon 200 Adressen und eine Adresse enthält den Namen Huber,Anton. Wollen wir jetzt seine Anschrift wissen, so muß die Datei von Anfang an durchsucht werden, bis zu dem Datensatz, in der der Huber steht. Steht der gesuchte Name ziemlich am Ende der Datei, so kann die Suche einige Zeit in Anspruch nehmen; je größer die Datei, desto mehr Zeit beansprucht die Suche. Diese Suche, aber auch alle anderen Operationen wie Ergänzungen, Veränderungen oder Sortieren der Datei spielen sich im Speicher des Computers ab. Das bedeutet, daß, wenn man mit dieser Adressendatei arbeiten will, zuerst die gesamte Datei von der Diskette in den Speicher geladen werden muß. Und am Ende, nach getaner Arbeit, wird sie wieder auf die Diskette zurückgespeichert.

Wenden wir uns dem Beispiel in Bild 2 zu. Es ist ein kleines und noch nicht einmal fertiges Adressen-Datei-Programm (die Funktionen »Suchen«, »Löschen« und »Ändern«) sind noch nicht codiert worden. Jedoch kann sich jeder dieser Module selber schreiben. Auf eine Besonderheit möchte ich gleich hinweisen. In den Zeilen 133 bis 135 stehen die Erklärungen der verwendeten Steuerzeichen, die diesmal codiert ausgedruckt wurden. Deswegen brauchen Sie nicht mehr mit der Lupe und viel Fantasie, die manchmal schwierig zu erkennenden Commodore-Steuerzeichen versuchen, zu interpretieren. Drücken Sie einfach die entsprechende Cursortaste (innerhalb der PRINT-Anweisung) wenn die Zeichen »CRR« und »CRL« im Listing erscheinen. Auf Ihrem Bildschirm sollten sie dann die entsprechenden Grafikzeichen erkennen. Gefällt Ihnen diese Art der Darstellung? Wir würden gerne Ihre Meinung dazu erfahren.

Der Aufbau des Programms dürfte nicht schwer zu durchblicken sein. Aber es gibt einige Programmzeilen und -abschnitte, die man sich einmal näher anschauen sollte.

Zeile 9110: Die Variable ST ist eine Statusvariable, die der C 64 und der VC 20 für sich beanspruchen. Hier gibt sie Auskunft darüber, ob das Dateiende erreicht ist. In diesem Fall wird nämlich das 6. Bit gesetzt (2 hoch 6 ergibt 64). Da aber in dieser Systemvariablen auch andere Nachrichten abgelegt werden, die andere Bits beeinflussen und ST auch bei Dateiende einen von 64 ungleichen Wert zuweisen können, müssen wir mit der AND-Verknüpfung feststellen, ob speziell dieses 6. Bit gesetzt ist.

Aus Sicherheitsgründen habe ich vor jedem OPEN-Befehl ein CLOSE gesetzt, damit nicht durch einen Programmierfehler ein »FILE OPEN ERROR» entstehen kann. Zum CLOSE-Befehl sei noch so viel gesagt, daß er unbedingt existieren muß. Sonst kann es vorkommen, daß nicht alle Daten auf die Diskette übertragen werden, und noch schlimmer, daß die Datei nicht ordnungsgemäß geschlossen werden kann. Dadurch kann die gesamte Datei unrettbar verloren sein. Also Vorsicht.

Wenn Sie sich das Programm etwas näher anschauen, könnten Sie über die Variablen »SS« und »L« stolpern. Diese Variablen habe ich eingesetzt als »Flags«. Sie regeln, ob ein Aufruf dieses Menüpunktes sinnvoll ist und das entsprechende Unterprogramm ausgeführt werden soll. Zum Beispiel verhindert die Variable »L« in Zeile 8025, daß Daten gespeichert werden, wenn die Datei noch gar nicht in den Speicher des Computers geladen wurde. Das würde nämlich bewirken, daß (in diesem Fall die Datei »ADRESS«) überschrieben würde ohne es zu wollen; auf Diskette vorhandene Daten wären verloren. Also eine reine Sicherheitsmaßnahme.

Sicherheit ist Trumpf

Die Variable »SS« verhindert, daß das Programm beendet wird, ohne neu eingegebene Daten vorher abzuspeichern.

Zuletzt möchte ich noch auf einen Programmteil hinweisen, der ab Zeile 10000 steht. Dieses Unterprogramm wird immer dann angesprungen, wenn eine Datei eröffnet wird. Es können nämlich auch dann Fehler auftreten, wenn das Programm sonst einwandfrei funktioniert. Es kann zum Beispiel sein, daß sie eine schreibgeschützte Diskette benutzen wollen, um Daten abzuspeichern. Das funktioniert natürlich nicht. Damit das Programm dann nicht abstürzt, wird jedesmal nach einem Öffnen eines Floppy-Kanals diese Routine angesprungen. Sie können dann im Fehlerfall das Problem beseitigen, ohne das Programm neu starten zu müssen und damit eventuell alle eingegebenen Daten zu verlieren. Der Fehler »62« in Zeile 10062 weist übrigens darauf hin, daß ein »FILE NOT FOUND ERROR« gemeldet wurde. In diesem Fall kann eine neue Datei angelegt werden (ab 11000). Man kann natürlich auch andere Fehler direkt abfragen. Schauen Sie nach im Floppy-Handbuch von Commodore. Dort sind alle Fehlermeldungen erklärt.

Ich glaube, daß Sie viele Möglichkeiten finden werden, eine sequentielle Datei sinnvoll einzusetzen. Setzen Sie sich hin und fangen Sie an zu programmieren und zu experimentieren. Erweitern Sie Ihr Wissen durch eigene Erfahrungen. Tippen Sie nicht nur ab, seien Sie kreativ!

(Christian Schlüter/gk)
100 rem  ******************************
110 rem  * adressendatei 64'er/6      *
120 rem  ******************************
130 :
131 rem ***** steuerzeichen *****
132 rem  *                       *
133 rem  * <clr> = clr/home      *
134 rem  * <crr> = cursor rechts *
135 rem  * <crl> = cursor links  *
136 rem  *                       *
137 rem *************************
138 :
140 di=200
150 dim nv$(di),nn$(di),sr$(di)
160 dim pl$(di),ot$(di),te$(di)
170 poke 53281,0
180 close 15:open 15,8,15
1000 rem  ----------------------------
1010 rem  - menue                    -
1020 rem  ----------------------------
1030 :
1040 print "{clr}"
1050 print :print
1060 print "     adressendatei"
1070 print :print
1080 print "   x = programmende"
1090 print
1100 print "   1 = anzeigen gesamte datei"
1110 print
1120 print "   2 = suchen"
1130 print
1140 print "   3 = loeschen"
1150 print
1160 print "   4 = aendern"
1170 print
1180 print "   5 = neue adressen eingeben"
1190 print
1200 print "   6 = speichern"
1210 print :print :print :print
1220 print "waehlen sie ";
1230 get r$:if r$="" then 1230
1240 if r$="x" then 1500
1250 if r$="1" then gosub 2000:rem  anz.
1260 if r$="2" then gosub 3000:rem  such
1270 if r$="3" then gosub 4000:rem  del
1280 if r$="4" then gosub 5000:rem  aen
1290 if r$="5" then gosub 6000:rem  neu
1300 if r$="6" then gosub 8000:rem  spei
1310 goto 1000
1320 :
1500 rem  ----------------------------
1510 rem  - programm ende            -
1520 rem  ----------------------------
1530 rem  ss=2 wenn nicht gespeichert
1540 if ss=1 then gosub 8000
1550 close 15
1560 end
1570 :
1580 :
2000 rem  ------------------------------
2010 rem  - anzeigen gesamte datei
2020 rem  ------------------------------
2030 :
2040 if l=0 then gosub 9000:rem  laden
2050 for i=1 to nd
2060 :print "{clr}    anzeige der datei"
2065 :print
2070 :print " nummer ";i:print
2075 :print
2080 :print " name    : "nv$(i)" "nn$(i)
2100 :print " strasse : "sr$(i)
2110 :print " plz/ort : "pl$(i)" "ot$(i)
2130 :print " telefon : "te$(i)
2150 :print :print :print
2160 :print "  w = weiter     x = ende"
2170 :get r$:if r$="" then 2170
2180 :if r$="x" then 2200
2190 next i
2200 return
2210 :
6000 rem ------------------------------
6010 rem - eingabe neue daten         -
6020 rem ------------------------------
6030 :
6040 if l=0 then gosub 9000:rem  laden
6050 print "{clr}"
6060 print "    eingabe neue daten"
6070 print :print
6075 nd=nd+1
6076 print "    nummer ";nd
6078 print :print
6080 input "nachname {rght}{rght}{rght}.{left}{left}{left}";nn$(nd)
6090 input "vorname  {rght}{rght}{rght}.{left}{left}{left}";nv$(nd)
6100 input "strasse  {rght}{rght}{rght}.{left}{left}{left}";sr$(nd)
6110 input "postlz.  {rght}{rght}{rght}.{left}{left}{left}";pl$(nd)
6120 input "ort      {rght}{rght}{rght}.{left}{left}{left}";ot$(nd)
6130 input "telefon  {rght}{rght}{rght}.{left}{left}{left}";te$(nd)
6140 print :print
6150 print "w = weitere adresse   x = ende"
6160 get r$:if r$="" then 6160
6170 if r$="w" then 6050
6175 ss=1:rem   daten neu eingegeben
6180 return
6190 :
8000 rem  ----------------------------
8010 rem  - speichern datei auf disk -
8020 rem  ----------------------------
8025 rem  l=0 wenn noch nicht geladen
8030 if l=0 then 8170
8040 close 1:open 1,8,2,"@:adresse,s,w"
8050 gosub 10000:rem   diskettenfehler?
8060 if a1<>0 then 8040
8070 print# 1,nd
8080 for i=1 to nd
8083 :print "{clr}    speichern der daten"
8085 :print i" von "nd
8090 :print# 1,nv$(i)
8100 :print# 1,nn$(i)
8110 :print# 1,sr$(i)
8120 :print# 1,pl$(i)
8130 :print# 1,ot$(i)
8140 :print# 1,te$(i)
8150 next i
8160 close 1
8165 ss=2:rem  letzten stand gespeichert
8170 return
8180 :
9000 rem  ----------------------------
9010 rem  - laden der datei von disk -
9020 rem  ----------------------------
9030 i=0
9040 close 1:open 1,8,2,"adresse,s,r"
9045 gosub 10000:rem  diskettenfehler?
9046 if a1<>0 then 9030
9047 input# 1,nd$:nd=val(nd$)
9048 i=i+1
9049 print "{clr}"i" von "nd
9050 input# 1,nv$(i)
9060 input# 1,nn$(i)
9070 input# 1,sr$(i)
9080 input# 1,pl$(i)
9090 input# 1,ot$(i)
9100 input# 1,te$(i)
9110 if (st and 64)<>64 then 9048
9120 close 1
9130 l=1:rem   datei ist geladen
9140 return
9150 :
10000 rem  ----------------------------
10010 rem  - diskettenfehler          -
10020 rem  ----------------------------
10030 print "{clr}"
10050 input# 15,a1,a2$,a3,a4
10060 if a1=0 then 10170
10062 if a1=62 then gosub 11000:goto 10170
10065 print
10070 print a1,a2$;a3;a4
10080 print :print
10090 print "        diskettenfehler"
10100 print :print
10110 print "     beheben sie den fehler"
10120 print "        und druecken sie"
10130 print
10140 print "            >> f <<"
10150 get r$:if r$="" then 10150
10160 print "{clr}"
10170 return
10180 :
11000 rem  ---------------------------
11010 rem   - neue datei anlegen
11020 rem  ---------------------------
11030 :
11040 print "{clr}"
11050 print " die datei existiert noch nicht"
11060 print :print
11070 print "n = neue datei   x = ende"
11080 get r$:if r$="" then 11080
11090 if r$="x" then run
11100 if r$<>"n" then 11080
11140 close 1:open 1,8,2,"adresse,s,w"
11150 for i=1 to 7
11160 :print# 1,"."
11170 next i
11180 close 1
11200 return
Bild 2. Unsere kleine Adressendatei ist nicht ganz vollständig. Aber das ist zum Verständnis auch nicht notwendig. Beachten Sie bitte die Zeilen 131 bis 137 und 6080 bis 6130. Diese Symbole stehen anstelle der sonst so schwer zu erkennenden Steuerzeichen.
PDF Diesen Artikel als PDF herunterladen
Mastodon Diesen Artikel auf Mastodon teilen
← Vorheriger ArtikelNächster Artikel →