Autor Beitrag
Johannes86
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Mo 24.10.05 13:41 
Ich bin dabei, einen Vokabeltrainer zu programmieren. Dabei wollte ich die Datenbank wie folgt definiert haben:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
  PTMother = ^TMother;
  TMother = record
             Meaning: string;
             next:PTMother;
            end;

  PTVoc = ^TVoc;
  TVoc = record
           foreign: string;
           mother: PTMother;
           Last_Tested: TDateTime;
           Create_Date: TDateTime;
           Tested_Times: Byte;
           Correct_Times: Byte;
           Was_Last_Correct: boolean;
           previous,next:PTVoc;
         end;

//Als globale Variablen:
var Form1: TForm1;  
    Vocs: PTVoc;

Nun das Problem:

Mit dieser Struktur hab ich ein schnelles Einlesen und Auslesen schon erreicht, aber wenn man Vokabeln nicht speichern kann... Deshalb habe ich mir Tutorials zu Stream (Filestreams) durchgelesen usw... Und hab eine noch nicht funktionierende Lösung:

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
procedure load_data(filename:stringvar Voc_List:PTVoc);
var  f: TFileStream;   i,k: integer;    j:Byte;  s:TStrings;  zs:string;  ZVL:PTVoc;
begin
  Form1.Caption:='Personal Vocabulary Trainer - ' + copy(filename,1+length(PChar(ExtractFilePath(ParamStr(0)))),length(filename)-length(PChar(ExtractFilePath(ParamStr(0))))+1);
  f:=TFileStream.Create(filename,fmOpenRead);
  try
   f.Position:=0;     ZVL:=nil;   s:=TStringList.Create;
   while f.Position<f.Size do
    begin
     Voc_List:=nil; new(Voc_List);
     Voc_List.previous:=nil; Voc_List.next:=nil;
     f.Read(i,SizeOf(i));  f.Read(Voc_List.foreign,i);   //foreign
     s.Clear;
     f.Read(j,SizeOf(j));                                // = Quantity of mothers
     for k:=1 to j do
      begin
       f.Read(i,SizeOf(i));
       f.Read(zs,i); s[k-1]:=zs;
      end;
     Voc_List.mother:=Create_Mother(s);  //(Create_Mother hat den Typ TStringList)
     f.Read(Voc_List.Last_Tested,SizeOf(TDateTime));           //Last_Tested
     f.Read(Voc_List.Create_Date,SizeOf(TDateTime));           //Create_Date
     f.Read(Voc_List.Tested_Times,1);                          //Tested_Times
     f.Read(Voc_List.Correct_Times,1);                         //Correct_Times
     f.Read(Voc_List.Was_Last_Correct,SizeOf(boolean));        //Was_Last_Correct?
     if ZVL<>nil then
      begin ZVL.next:=Voc_List; ZVL.next.previous:=ZVL; end;
     ZVL:=Voc_List;
    end;
  finally
   f.Free;
  end;
end;

//-------------------------------------------------------------------------------------------------------------------
//                                              save_data
procedure save_data(filename:string;Voc_List:PTVoc);
var  f: TFileStream;   i: integer;   j:Byte;
begin
  Form1.Caption:='Personal Vocabulary Trainer - ' + copy(filename,1+length(PChar(ExtractFilePath(ParamStr(0)))),length(filename)-length(PChar(ExtractFilePath(ParamStr(0))))+1);
  f:=TFileStream.Create(filename,fmCreate);
  Reset_Vocs(Voc_List);  //Set Pointer to the first record
    //Save!!
  try
   while Voc_List<>nil do
    begin
     i:=length(Voc_List.foreign);
     f.Write(i,SizeOf(i));              //foreign
     f.Write(Voc_List.foreign,i);
     j:=Count_Mother(Voc_List.mother);
     f.Write(j,SizeOf(j));              //mother
     while Voc_List.mother<>nil do      //each Mother
      begin
       i:=length(Voc_List.Mother.Meaning);
       f.Write(i,SizeOf(i));
       f.Write(Voc_List.Mother.Meaning,i);
       Voc_List.mother:=Voc_List.mother.next;
      end;
     f.Write(Voc_List.Last_Tested,SizeOf(TDateTime)); //Last_Tested
     f.Write(Voc_List.Create_Date,SizeOf(TDateTime));
     f.Write(Voc_List.Tested_Times,1);
     f.Write(Voc_List.Correct_Times,1);
     f.Write(Voc_List.Was_Last_Correct,SizeOf(boolean));  // Is that possible?!?
     Voc_List:=Voc_List.next;
    end;
  finally
   f.Free;
  end;
end;



Also: Wer findet den Fehler und was hab ich dabei nicht beachtet!!

Vielen Dank schon im Voraus für Vorschläge.

Moderiert von user profile iconraziel: Delphi-Tags hinzugefügt.
Moderiert von user profile iconraziel: Titel geändert.
Udontknow
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2596

Win7
D2006 WIN32, .NET (C#)
BeitragVerfasst: Mo 24.10.05 14:24 
Hallo!

Es ist immer hilfreich, anzugegeben, was für ein Fehler überhaupt auftritt. Desweiteren solltest du dein Problem genauer eingrenzen. Wenn du weisst, daß du Schwierigkeiten mit dem Speichern hast, warum baust du nicht erst einmal Testcode, um dich speziell nur um dieses Problem zu kümmern? Wieso sollte sich nun irgendjemand die Mühe machen, dein unübersichtliches und kommentarloses Projekt zu debuggen?

Da es teilweise um Strings bzw. Records mit dynamischen Strings geht, wage ich mal einen Schuss ins Blaue:

Dynamische Strings sind nichts anderes als Zeiger auf einen bestimmten Bereich im Speicher. Wenn du sie ganz normal speicherst, landet nur der 4 Byte grosse Zeiger-Inhalt auf der Festplatte. Du musst also beim Lesen und Schreiben von Strings in einen Stream anders vorgehen. Suche mal nach Suche in: Delphi-Forum LOADSTRFROMSTREAM / Suche in: Delphi-Forum SAVESTRTOSTREAM.

Cu,
Udontknow
AG
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 22



BeitragVerfasst: Mo 24.10.05 14:47 
was für ein Fehler tritt denn übergaupt auf???

also, wenn ich mit Filestreams arbeite, und eigentlich eine vorhersehbare Struktur hab (also weiß, was (welcher Typ) genau als nächstes steht), arbeite ich mit TReader und TWriter, und den Funktionen
Reader.ReadInteger, ...Float, ...String, und so weiter... (beim einlesen) und
Writer.WriteInteger usw. beim abspeichern;

dann machste dir zu deinem Vokabeltyp 2 Funktionen
VokabelAbspeichern(var Reader:TReader) und
VokabelLesen(var Writer;TWriter); und 2 ListenFunktionen

ListeAbspeichern und ListeEinlesen;

in Listeabspeichern kommt dann
FileStream öffnen, Writer definieren, Anzahl der Vokabeln abspeichern (Writer.WriteInteger) und Vokabeln abspeichern (AktuelleVokabel.VokabelAbspeichern(Writer) ),
am Ende Writer und Stream freigeben;

In ListeEinlesen kommt:
ev. alte Liste freigeben
Liste erzeugen
FileStream öffnen
Reader definieren
Anzahl der Vokabeln einlesen (mit Reader.ReadInteger
pro Vokabel
Objekt erstellen (AktuelleVokabel:=TVokabel.Create)
Objekt einlesen (AktuelleVokabel.VokabelEinlesen(Reader) )
Objekt verketten
am Ende Reader und Stream freigeben
Johannes86 Threadstarter
Hält's aus hier
Beiträge: 2



BeitragVerfasst: Di 25.10.05 09:52 
Titel: Vielen Dank erstmal für eure schnellen Antworten
Vielen Dank erstmal.

Ich werde mir jetzt erst mal eure Vorschläge anschauen und dabei gucken, was sich meiner Meinung nach am besten realisieren lässt. Ohne eure Hilfe wäre ich wahrscheinlich nicht so schnell darauf gekommen... Also vielen Dank...

Die Fehlermeldung ist übrigens:

"Im Projekt VocTrainer.exe ist eine Exception der Klasse EStringListError aufgetreten. Meldung: 'Listenindex überschreitet das Maximum (0)'. Prozeß wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen.

Das ist die Fehlermeldung, wenn ich öffne. Und ich hab mal langsam durchgegangen, was der so macht, also während des Programmablaufs. Und: Wenn die Dateilänge Null ist, so springt er trotzdem in

while f.Position<f.Size do
begin
...
end;

herein!! Dabei ist eigentlich, wenn man sich die Zahlen anschaut f.Position garnicht kleiner als f.Size!! Irgendwie seltsam...

Aber da ich nun andere Anregungen habe, werde ich erstmal diese ausprobieren...