Archiv verlassen und diese Seite im Standarddesign anzeigen : datenbank
moin moin,
ich wollt eine dynamische datenbank erstellen, soll heißen man kann beliebig viele datensätze (nur name und vorname) in eine datei schreiben.
um dann die datensätze zu ändern oder welche hinzuzufügen, wollte ich sie in einen container einlesen und nach dem ich feritg bin die geänderten datensätze zurückspeichern. nun weiß ich aber nicht wie ich den container dynamische größe verpasse! wenn ich ihn statisch mach, z.B. mit 255 Elementen und in datei nur 10 drin sind, bleiben ja 245 elemente ungenutzt.
so long, hoff ihr könnt mir helfen
case
Dann schau dir mal Records und Pointer an.
nunja das hab ich nun wrklich schon längst! aber wie bring ich dann beide in verbindung?
es ist ja nicht damit getan, dass ich auf einen record zeige. wenn ich bei einem die elemente beschrieben habe, kan ich ja nicht auf den nächsten zeigen ohne die addresse des letzten zu speichern.
oder ich versteh bei der sache noch absolut nichts... ;-)
case
Du bastelst dir einen Record, der als 1 Datensatz fungiert. Der bekommt ausserdem eine Variable die ein Pointer ist und auf den nächsten Datensatz zeigt ..usw. Der letzte Datensatz, also die Zeigervariable zeigt auf nil. Das ist das Prinzip der einfach verketteten Liste, cleverer wäre die doppelt verkettete zu nutzen.
aha also in etwas so:
[...]
TYPE
PData = ^TData;
TData = RECORD
name:string[10];
vname:string[10];
pointer : PData;
END;
[...]
was ist eine doppel verkettete liste?
geht es nicht irgendwie einfacher, weil sortieren ist dann ja recht schwer...
also danke erstmal!
ich hab grad was schönes zu den listen gefunden - wenn man weiß wonach man suchen muss - jaja!
werd's mir jetzt mal durchlesen und dann meine fragen wieder posten!!!
thx
case :D
eht es nicht irgendwie einfacher, weil sortieren ist dann ja recht schwer. ...sortieren ist (fast) genauso einfach wie das Sortieren eines Arrays.
...sortieren ist (fast) genauso einfach wie das Sortieren eines Arrays.
nunja ich kann aber nunmal nur nachbarn vergeichen, also auch nur nen bubblesort nutzen - oder?!?
thx case.
Wenn du die Liste clever, d.h. sortiert aufbaust, brauchst du gar keinen Sortieralg.!
Diogenes
20.03.2005, 14:10
Wenn du die Liste clever, d.h. sortiert aufbaust, brauchst du gar keinen Sortieralg.!
Stimmt nicht ganz. Was ist, wenn sich ein fürs Sortieren kritisches Datum zur Programmlaufzeit ändert?
Dann sind es 2 simple Umhängungen des Listenelements und ein linearer Durchlauf der Liste.
Ja, das mit den mehreren Pointern geht zwar auch, ist aber
halt auch etwas... hm. umständlich.
Ich hab mir halt vor ner Weile mal eine dynamische
Speicherverwaltung gebaut, die auch nachträglich Pointergrößen
ändern kann.
Bei mir würde das dann so aussehen:
type NameRec=Record Name,Vorname:string[20];end;
type RecArray=array[0..65535 div sizeof(NameRec)-1]of NameRec;
{Das maximale Array halt}
var P:Pointer;
var Name:^RecArray absolute P;
begin
{Man weist einfach dem Pointer P immer soviele Bytes zu,
wie man braucht, also AnzahlDatensaetze*sizeof(NameRec).}
{Bei mir heisst die Subroutine dann SetPointer(P,Groesse,Typ)
Also P waere der Pointer (MUSS eine Variable sein!!)
Groesse die neue Pointergroesse - er behaelt natuerlich,
wenn der Pointer schon vorhanden ist, die alten Daten,
wenn man ihn nur vergroessert. Optional kann man dann
auch den Bereich, der dazukommt, mit irgendwas (z.B.
Nullen) fuellen lassen.
Warum der Pointer eine Variable sein MUSS - erstens wird
in diesen Pointer dann die Speicherposition eingetragen -
zweitens kann er auch nachtraeglich "verschoben" werden
und das wird dann automatisch WIEDER mit eingetragen.
Verschoben wird er, wenn man Pointer, die man VORHER
definiert hat - und die dann VORHER im Speicher liegen -
nachtraeglich vergroessert/verkleinert/loescht.
Typ ist fuer normale Pointer halt 0. (Man kann z.B. auch
NUR Segmente (WORD) reservieren lassen, mit Offset=0). Oder
Pointer, bei der der Offset nur Byte ist. Oder Segment
und Offset vertauscht... - hängt halt damit zusammen, wie
die Pointervariable aussieht.)
end.
Man kann so Pointer auch mit NEW und DISPOSE (siehe
PASCAL-Hilfe) oder mit GETMEM und FREEMEM (ebenfalls siehe
PASCAL-Hilfe) definieren. Allerdings muß man sich dann
halt drauf verlassen, daß, wenn man zusätzlichen Speicher
deklariert, oder wenn man halt
FREEMEM(P,AlteAnzahlDatensaetze*sizeof(NameRec));
GETMEM (P,NeueAnzahlDatensaetze*sizeof(NameRec));
Speicher deklatiert, P wieder an genau derselben Stelle
landet. (Oder man deklariert NUR den neuen Speicher und
prüft, ob der Pointer genau "hinten" an den anderen
anschließt.)
Achja: Dazu müßte man den Pointer auch auf eine absolute
Speicherstelle von 0 bis etwas über 1 MB umrechnen. - Für
sowas hat meine Unit für dynamisches Speichermanagement
schon so Subroutinen, nur da die das ohnehin automatisch
macht, bräuchte man das garnicht.
Also ich belege halt per Default erstmal den größten
zusammenhängenden Speicherbereich, den ich kriegen kann
und verteile/verwalte dann den Speicher selbst.
(Man kann aber angeben, wie groß dieser Bereich sein soll.
Wahlweise a) Alles, b) Größe des zu reservierenden
Bereichs oder c) Größe des "freizulassenden" Bereichs.)
Nachteil obiger Methode: Man kann damit nur 1560 Datensätze
haben (65535 div 42) - mit der Verkettung wären es
natürlich mehr. (Man könnt's natürlich einfach schon
auf 3120 verdoppeln, indem man zwei Arrays draus macht,
eins für Vorname, eins für Name...)
Achja: Dieser Nachteil entsteht natürlich NUR dadurch, daß
in Pascal Variablen nur max. 64kB minus 1 groß sein dürfen!
Die Pointergrößen, die man sich geben lassen kann, dürfen
natürlich auch viel größer sein - muß man dann selbst
wissen, wie man den Speicher abfragen/bearbeiten will.
Man kann ja auch ohne weiteres mit mem[segment:offset]
(oder memW und memL) DIREKT auf den Speicher zugreifen...
Wieso nun dieses Ding mit dem "maximalen Array"? - Naja,
er ORGANISIERT nur alles ab dem Pointer wie so ein Array -
d.h. es ist ohne weiteres möglich, nur Speicher für 12
Datensätze anzulegen und dann was in Datensatz Nummer 25
zu schreiben... (sollte man halt SEINLASSEN!)
Wie gesagt, so würde ICH sowas theoretisch machen.
(Andererseits hab ich ja so ein für Datenbanken
prädestiniertes Dingens gecodet, das man mit ner Art
Script-Sprache (tokensiertes BASIC) steuern kann und das
einem gleich (GRAFISCH) Eingaberoutinen, Fenster, Buttons,
Mausabfragen/Hotkeys und all den anderen Kram zur Verfügung
stellt, um es wie EXCEL oder ACCESS aussehen zu lassen -
ohne Windows dafür zu brauchen... Und: Ja, auch mit
Proportionalschrift.
Variablen sind alle dynamisch. Und Strings verbrauchen nur
wirklich soviele Bytes, wie sie Zeichen haben. Dinge, um
in Arrays einzele Felder einzufügen/zu löschen, sind schon
fest implementiert. Sortieren auch.
RECORDS hab ich auf ne ziemlich elegante Art gelöst - man
kann Arrays gleicher verschiedener Typen miteinander
"verknüpfen", so daß jede Vergrößerung/Verkleinerung und
auch Einfügen und Löschen eines Elements in EINEM Array
auch für alle verknüpften Arrays mitpassiert. Dieser ganze
EXCEL-Kram (also, z.B. eine Formatangabe wie "#.##0,00 DM",
um die Zahl 12345.67 halt in der Form "12.345,76 DM"
anzeigen zu lassen) ist ebenfalls eingebaut...
Formeln dürfen auch komplex sein - ebenfalls existiert
Vorrangautomatik...
Keine Ahnung, was mich geritten hat, so ein Ding zu coden.
Eigentlich war das, weil da mal einer was in EXCEL wollte
und EXCEL da etwas nicht konnte - (er wollte eigentlich eine
Mischung aus EXCEL und ACCESS) und deswegen hab ich halt
selbst so einen Ersatz gebaut... Allerdings hat dem zum
Schluß DOCH ein vereinfachtes Ding gereicht, was ich für
EXCEL gemacht hab - der wollte halt nicht auf das Programm
warten und danach hatte er sich in das EXCEL-Teil schon
eingearbeitet. (Wobei ich das aber bedientechnisch genauso
hingekriegt hätte.)
Achja, ein so cooles Feature, was ich speziell für
Datenbanken eingebaut hatte, sind indirekte Arrays. Man
kann einem Array bei der Definition halt sagen, daß es
"indirekt" sein soll und dann legt er intern zwei Arrays an.
Eins, was nur Indizes enthält und eins, was die wirklichen
Werte enthält. (Der Index zeigt halt auf die Stelle im
zweiten Array.) Von der BENUTZUNG her ändert sich nichts -
nur daß, wenn man z.B. bei 20 Leuten als Ort "Berlin"
eingibt, jeder den gleichen Index hat und auf denselben
String zeigt. Spart Speicher. Und, was noch dazukommt:
Wenn man bei einer Eingabe ein Pulldown haben will, kann
man als "Variable" einfach auch dieses zweite interne Array
benutzen - damit steht dann jeder Wert auch wirklich nur
EINMAL im Pulldown drin...
Und: Diese dynamische Variablenverwaltung - zusammen mit
einer Umwandelroutine von jedem in jedes Zahlensystem
UND mit einer ebenfalls dynamischen Verwaltung für
NICHT-ARRAY-Variablen (halt einfache Typen wie BYTE, WORD,
STRING oder sowas (wobei Strings wieder nur soviel Speicher
belegen, wie sie wirklich BRAUCHEN) ist von dem ganzen
"GUI-Ding" entkoppelt und funktioniert auch "einfach so"
(als eigenständige Unit) falls man eine Datenbank machen,
aber auf den grafischen Kram verzichten will...)
Ich überlege halt: So langsam sollte ich den Kram, den ich
schon jahrzehntelang programmiere (nützliche Units etc)
vielleicht mal irgendwo für die Öffentlichkeit freigeben.
Sicherlich könnten manche Leute sowas wirklich gebrauchen...
(Achja... und falls jemand dann auch noch Verwendung für
ne XMS-Speicherverwaltung hätte...)
Ja, das mit den mehreren Pointern geht zwar auch, ist aber
halt auch etwas... hm. umständlich.
...Hä? Sowas nennt sich effektive Programmierung.
also zum tipp mit dem direkten sortieren, also ich habe es als ein einfügen an die richtige stelle schon bei der eingabe verstanden, das geht so wiet so gut! nur würde ich die sache ganz gern auch nach Vornamen Namen und z.B. alter sortieren lassen wollen. mit einer liste könnte ich ja dann nur eine sortierung nutzen. also hab ich mir geadcht dass ich gleich zu jedem datensatz noch einen index für die position (name, vorname, alter) integriere. der wird dann auch mit gespeichert.
wie geb ich das denn aber am effektivsten aus? wenn ich's dann auslese und in einer liste speicher, müsste ich für jede position alle listenelemente mit nem linearen suchen durchgehen und das so lange wiederholen bis er feritg ist?
ist das die beste variante?!?
thx dür die vielen antowrten!!!
case
geht das als doppelt verkettete liste durch?
PROCEDURE getListFromFile(VAR datei:TDatei; dateiName:TName; VAR first, last : PData);
VAR p : PData;
BEGIN
first:=NIL;
assign(datei,dateiName);
reset(datei);
new(p);
last:=p;
WHILE NOT eof(datei) DO
BEGIN
read(datei,data);
p^.name:=data.name;
p^.vname:=data.vname;
p^.next:=first;
first:=p;
new(p);
first^.prev:=p;
END;
END;
Wieso Listen, wieso keinen Tree?!
Such mal nach Binären Suchbäumen. Die sind schön sortiert, was das suchen auch relativ einfach macht.
Wennst nichst findest zu BBäumen (Binären Bäumen) meld dich, dann schick ich dir ein bisschen was.
Das blöde an Bäumen ist halt das Einfügen, da meist der ganze Baum umgestellt werden muss. Und bei DBs ist das Einfügen nunmal nicht zu vernachlässigen!
wiso ist das blöd, bei einem Binären Suchbaum musst nichts umstellen, da hängst die neuen Nodes einfach ans Ende an. Das ist rekursiv sehr schön zu lösen (geht iterativ natürlich genauso).
Hier mal eine kleines Beispiel:
procedure Insert(var t : Tree; n : Node);
begin
if t=NIL then
t:=n
else if n^.value<t^.value then
Insert(t^.left, n)
else
Insert(t^.right, n);
end; { Insert }
Ausserdem funktionieren zB hierarchische Datenbanksysteme auch mit Baumstruktur.
Klar, bei B-Bäumen ist der Aufwand noch relativ gering, jedoch ist dies auch nicht der Weisheit letzter Schluß. Die meisten anderen Baum- oder Graphenstrukturen sind allerdings viel aufwändiger zu behandeln. Und jenachdem, wie der (Primär-)Schlüssel ausfällt kann evtl kein B-Baum benutzt werden. Man denke nur an BLOBs.
Stimmt schon. Nur ich glaub das reicht für .case. Wenn ich das richtig verstanden hab, will er nur irgendeine Datenstruktur um seine Daten zu speichern, ich glaub nicht das .case auch Schlüssel und Relations haben will.
Naja es kommt halt darauf an, wie oft der Baum aufgebaut, durchgegangen und danach abgespeichert werden muss. Besonders der Aufbau kann schon ein wenig dauern. Aber von mir aus kann er auch Bäume statt Listen nehmen, wobei ich denke, das mein Listenvorschlag etwas einfacher umzusetzen ist.
Da geb ich dir auf jeden Fall recht, also für jemanden der noch nichts mit pointern bzw. Datenstrukturen wie Listen und Bäume gemacht hat, sind Listen sicher einfacher zu verstehen.
vBulletin® v3.8.6, Copyright ©2000-2012, Jelsoft Enterprises Ltd.