Delphi-PRAXiS
Seite 2 von 3     12 3      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   FreePascal Eine lineare Liste an Strings als Datei speichern (https://www.delphipraxis.net/177561-eine-lineare-liste-strings-als-datei-speichern.html)

Sir Rufo 14. Nov 2013 08:46

AW: Eine lineare Liste an Strings als Datei speichern
 
Mal eine Frage vorweg:

Wozu hast du alle Methoden als
Delphi-Quellcode:
virtual
deklariert? :gruebel:
Als
Delphi-Quellcode:
virtual
deklariert man Methoden, wo man bei der Entwicklung schon absehen kann, dass diese Methoden wohl meistens überschrieben werden.
Als
Delphi-Quellcode:
virtual abstract
deklariert man Methoden, die überschrieben werden müssen.
Alle anderen Methoden können auch überschrieben werden, allerdings war das eigentlich nicht im Sinne des Entwicklers (was alles und nichts bedeuten muss).

Zum Thema:

Also ich würde das Speichern nicht in die Liste reinpacken (allerdings würde ich in die Liste auch nicht das Auswürfeln der Vokabeln reinpacken).

Delphi-Quellcode:
type
  // Container für die Vokabeln
  TListe = class
  public
    procedure Clear;
    function Add( AItem : TVokabel ) : Integer;
    property Count : Integer read GetCount;
    property Items[const Index : Integer] : TVokabel read GetItem;
  end;

  // Der Vokabeltrainer (braucht aber einen Container)
  TTrainer = class
  private
    FListe : TListe;
    procedure SetListe( const Value : TListe );
  public
    procedure Reset; virtual; abstract;
    property Liste : TListe read FListe write SetListe;
  end;

  // Das Speichermodul für den Container
  TStorage = class
  private
    FFilename : string;
  protected
    procedure DoSave( AListe : TListe ); virtual; abstract;
    procedure DoLoad( AListe : TListe ); virtual; abstract;
  public
    constructor Create( const AFilename : string );

    procedure Save( AList : TListe );
    procedure Load( AList : TListe );

    property Filename : string read FFilename;
  end;

  TStorageClass = class of TStorage;

procedure TTrainer.SetListe( const Value : TListe );
begin
  if Value = FListe then
    Exit;

  FListe := Value;
  Reset;
end;

constrcutor TStorage.Create( const AFilename : string );
begin
  inherited;
  FFilename := AFilename;
end;

procedure TStorage.Save( AListe : TListe );
begin
  if not Assigned( AListe ) then
    raise Exception.Create( 'Keine Listen-Instanz übergeben!' );
  DoSave( AListe );
end;

procedure TStorage.Load( AListe : TListe );
begin
  if not Assigned( AListe ) then
    raise Exception.Create( 'Keine Listen-Instanz übergeben!' );
  DoLoad( AListe );
end;
Von der Klasse
Delphi-Quellcode:
TStorage
leitet man nun die konkreten Klassen (z.B.
Delphi-Quellcode:
TIniStorage
,
Delphi-Quellcode:
TPlainTextStorage
,
Delphi-Quellcode:
TMyBaseStorage
, ...) ab.

Um nun die Liste in eine Datei zu speichern macht man folgendes:
Delphi-Quellcode:
procedure SaveListe( AListe : TListe; const AFilename : string );
var
  LStorage : TStorage; // kein konkreter Typ!!!
  LStorageClass : TStorageClass;
begin
  case IndexText( ExtractFileExt( AFilename ), ['.txt','.ini','.xml','.db'] ) of
    0 : // PlainText-Datei
      LStorageClass := TPlainTextStorage;
    1 : // Ini-Datei
      LStorageClass := TIniStorage;
    2, 3 : // MyBase-Datei
      LStorageClass := TMyBaseStorage;
  else
    raise Exception.CreateFmt( 'Unbekannte Dateiendung "%s"', [ExtractFileExt( AFilename )] );
  end;

  // Jetzt kommt das Speichern

  LStorage := LStorageClass.Create( AFileName );
  try
    LStorage.Save( AListe );
  finally
    LStorage.Free;
  end;
end;
Am Anfang wird es wohl durchaus reichen eine einfache Storage-Klasse zu entwerfen ... aber man sollte auch verstehen, warum eine Trennung der Klassen besser ist ;)

thejacensolo 14. Nov 2013 12:54

AW: Eine lineare Liste an Strings als Datei speichern
 
soll ich eine neue Klasse anstatt tliste erstellen? und was meinst du mit Container (ist dass so etwas wie speichern?). Die prozeduren Dosave und Doload, finde ich nicht in dem Quelltext, soll die in tliste drin sein? Ich deklariere immer als virtual, weil er sonst immer meckert ;).


Edit:
tschuldigung hab sie nicht gesehen, natürlich sind sie da

Sir Rufo 14. Nov 2013 13:28

AW: Eine lineare Liste an Strings als Datei speichern
 
Zitat:

Zitat von thejacensolo (Beitrag 1235850)
soll ich eine neue Klasse anstatt tliste erstellen? und was meinst du mit Container (ist dass so etwas wie speichern?).

Nein, deine
Delphi-Quellcode:
TListe
ist ja ein Container (zu deutsch Behälter) worin sich die Daten (hier Vokabeln) befinden.
Zitat:

Zitat von thejacensolo (Beitrag 1235850)
Die prozeduren Dosave und Doload, finde ich nicht in dem Quelltext, soll die in tliste drin sein?

Nein, du erstellst dir eine Klasse wie folgt:
Delphi-Quellcode:
unit mTStorage;

interface

uses
  mTListe, mTVokabel;

type
  TStorage = class
  private
    FFilename : string;
  protected
    procedure DoSave( AListe : TListe );
    procedure DoLoad( AListe : TListe );
  public
    constructor Create( const AFilename : string );

    property Filename : string read FFilename;

    procedure Save( AListe : TListe );
    procedure Load( AListe : TListe );
  end;

implementation

constructor TStorage.Create( const AFilename : string );
begin
  inherited Create;
  FFilename := AFilename;
end;

procedure TStorage.Save( AListe : TListe );
begin
  // Vorher evtl. eine Abfrage ob die Liste existiert?
  // if Assigned( AListe ) then
  DoSave( AListe );
end;

procedure TStorage.Load( AListe : TListe );
begin
  // Vorher evtl. eine Abfrage ob die Liste existiert?
  // if Assigned( AListe ) then
  DoLoad( AListe );
end;

procedure TStorage.DoSave( AListe : TListe );
begin
  // Hier kreativ werden
end;

procedure TStorage.DoLoad( AListe : TListe );
begin
  // Hier auch kreativ werden
end;

end.
Zitat:

Zitat von thejacensolo (Beitrag 1235850)
Ich deklariere immer als virtual, weil er sonst immer meckert ;).

Ok ... ist aber sehr seltsam ...

Popov 14. Nov 2013 14:09

AW: Eine lineare Liste an Strings als Datei speichern
 
@thejacensolo

Wahrscheinlich hast du es schon erwähnt, oder es steht im Quelltext, aber ich finde es nicht. Ich hab es zwar schon gefragt, aber keine Antwort bekommen. Wie und wo speicherst du deine Vokabeln?

Ich sehe da zwar eine TVokabel und eine Unit mTVokabel, weiß aber nicht absolut wie du das ablegst. Die Zeile
Delphi-Quellcode:
V := TVokabel.initVok(E,D);
sieht... nun ja, ich weiß nicht wie ich das deuten soll. Erstellst du das Objekt separat? Record ist es nicht, da E und D Strings sind. Sieht nach INI aus. Ini in einer Klasse?

Die Frage wie du deine Daten speichern sollst ist genauso zu beantworten wie die Frage was du in das Auto deines Vaters tanken sollst. Woher soll man das wissen, keiner kennt die Marke. Was du veröffentlicht hast ist die Klasse in der die Daten verarbeitet werden, aber den den wichtigeren Teil hast du weggelassen. Wo legst du die Daten ab. Denn so wie es aussieht ist dafür die mTVokabel Unit gedacht.

Es ist zwar nett von Sir Rufo Beispiele geliefert zu haben, aber er scheint sich auch alle Möglichkeiten offen zu halten
Delphi-Quellcode:
['.txt','.ini','.xml','.db']
.

Ich halte die Idee mit TStringList oder alternativ TIniFile am einfachsten, weil die schon die Verwaltung mit sich bringen, aber man kann auch alles alleine machen. Dann sollte man aber zweigen was man macht :-D

thejacensolo 14. Nov 2013 14:17

AW: Eine lineare Liste an Strings als Datei speichern
 
Hier die Unit mtvokabel:
Delphi-Quellcode:
UNIT mTVokabel;

interface

//--------------------  ggf Uses-Liste anpassen !  --------------------
uses Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls, ComCtrls, Menus;

type
  TVokabel = class

  public //Attribute
    Deutsch : string;
    Englisch : String;
    naechste : TVokabel;
    speicher : array of string;

     //Objektbeziehungen:

  public //Methoden
    constructor initVok (D: String; E: string); virtual;
    procedure SetzeEnglisch (pEnglisch: String); virtual;
    function GibEnglisch : String; virtual;

   end;

implementation

//+---------------------------------------------------------------------
//|         TVokabel: Methodendefinition
//+---------------------------------------------------------------------

//-------- initVok (public) --------------------------------------------
constructor TVokabel.initVok (D: String; E: string);
begin
  Englisch := E;
  Naechste := nil; // Nil ist der Nullwert, dh ist noch nicht belegt.
  Deutsch := D;
end;

//-------- SetzeEnglisch (public) --------------------------------------
procedure TVokabel.SetzeEnglisch (pEnglisch: String);
begin
  Englisch := pEnglisch
end;

//-------- GibEnglisch (public) ----------------------------------------
function TVokabel.GibEnglisch : String;
begin
  result := Englisch
end;

end.

und meine HAuptunit
Delphi-Quellcode:
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  ExtCtrls, ComCtrls, Menus, mtListe, mTvokabel;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button10: TButton;
    Button11: TButton;
    Button12: TButton;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    Button5: TButton;
    Button6: TButton;
    Button7: TButton;
    Button8: TButton;
    Button9: TButton;
    Edenglisch: TEdit;
    EDeutsch: TEdit;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    procedure Button10Click(Sender: TObject);
    procedure Button11Click(Sender: TObject);
    procedure Button12Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
    procedure Button6Click(Sender: TObject);
    procedure Button7Click(Sender: TObject);
    procedure Button8Click(Sender: TObject);
    procedure Button9Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { private declarations }
  public
    { public declarations }
  end;

var
t:integer; Liste:TListe; vokabel:TVokabel; Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button3Click(Sender: TObject);
begin
  Liste.hinzufuegen(Edeutsch.text, Edenglisch.text);
  showmessage('Vokabel gespeichert');
  Edeutsch.Text := '';
  Edenglisch.Text := '';
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
liste.loeschen(strtoint(Edit1.text));
showmessage('vokabel gelöscht');
end;
procedure TForm1.Button1Click(Sender: TObject);
begin

end;

procedure TForm1.Button10Click(Sender: TObject);
var n,t : integer;
begin
  n := liste.laenge;
  t := random(n);
  Edenglisch.text := Liste.zufallfragenE(t);
end;

procedure TForm1.Button11Click(Sender: TObject);
var n,t : integer;
begin
  n := liste.laenge;
  t := random(n);
  Edeutsch.text := Liste.zufallfragenD(t);
end;

procedure TForm1.Button12Click(Sender: TObject);
begin
  //liste.SaveToFile(Edit2.text + Edit3.text + '.txt');
end;

procedure TForm1.Button5Click(Sender: TObject);
var n: string;
begin
 n := inttostr(liste.laenge);
 if Edit1.Text = '' then
  begin
    showmessage('Keine Eingabe');
  end else;
  if Edit1.Text > n then
   begin
   showmessage('zu hohe zahl');
   end
 else begin;
    Edenglisch.Text := Liste.abfragen(strtoint(Edit1.Text));
  end;
end;

procedure TForm1.Button6Click(Sender: TObject);
begin
 if Edeutsch.text = '' then
  begin
  showmessage('Machen sie erst eine Eingabe');
  end
 else
  begin
  if EDeutsch.text = vokabel.Deutsch then
  begin
    showmessage('Die Vokabel war Richtig');
    Edenglisch.text := '';
    EDeutsch.Text := '';
  end else
  begin
    showmessage('Das war leider Falsch :-( versuche es nochmal');
    end;
  end;
end;

procedure TForm1.Button7Click(Sender: TObject);
begin
  //Erstes speichern
  liste := Tliste.initlist(Edenglisch.Text,EDeutsch.Text);
  //vokabel := TVokabel.initvok(Edenglisch.Text, EDeutsch.text);
  showmessage('Die Vokabel wurde gespeichert');

end;

procedure TForm1.Button8Click(Sender: TObject);
begin
 if Edeutsch.text = '' then
  begin
  showmessage('Machen sie erst eine Eingabe');
  end
 else
  begin
  if EDenglisch.text = vokabel.Englisch then
  begin
    showmessage('Die Vokabel war Richtig');
    Edenglisch.text := '';
    EDeutsch.Text := '';
  end else
  begin
    showmessage('Das war leider Falsch :-( versuche es nochmal');
    end;
  end;
end;

procedure TForm1.Button9Click(Sender: TObject);
var n: string;
begin
  n := inttostr(liste.laenge);
  if Edit1.Text > n then
   begin
   showmessage('zu hohe zahl');
   end
 else
    Edeutsch.Text := Liste.dabfragen(strtoint(Edit1.Text));
  end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  //t := 0;
  //liste := Tliste.initlist(Edenglisch.Text,EDeutsch.Text);
  Randomize;
end;

end.
Ich speichere alles in der Unit Tliste ab
(initlist, hinzufuegen)

Popov 14. Nov 2013 14:43

AW: Eine lineare Liste an Strings als Datei speichern
 
Ok, damit kann man schon was anfangen. Muss jetzt aber kurz weg, wenn ich wieder online bin, gucke ich mir das genauer an.

Das Problem scheint zu sein, dass du noch gar nicht die Vokabeln abspeicherst. Damit meine ich nicht Festplatte, sondern den Array.
Delphi-Quellcode:
speicher : array of string;
ist zwar da, scheint aber noch nicht genutzt zu werden.

Kriegen wir aber hin.

thejacensolo 14. Nov 2013 15:37

AW: Eine lineare Liste an Strings als Datei speichern
 
Ich habe array of string eingebaut, als meinen ersten Versuch. Aber als ich vokabel2 eingebaut habe die immer den wert vokabel einnimmt und als string zu speicher gehört, hat es nicht geklappt. Speicher wird sonst nicht benutzt.

Aber danke für die Hilfe ihr seid klasse ;-)

Sir Rufo 14. Nov 2013 16:16

AW: Eine lineare Liste an Strings als Datei speichern
 
@Popov

Die Klasse
Delphi-Quellcode:
TStorage
ist doch nur dafür da, das Geraffel, was du mit der
Delphi-Quellcode:
TStringList
oder
Delphi-Quellcode:
TIniFile
schreiben möchtest in eine Klasse gepackt wird und gut.

Der Code ist der gleiche ... nur wesentlich mehr OOP ;)

Popov 14. Nov 2013 17:00

AW: Eine lineare Liste an Strings als Datei speichern
 
@Sir Rufo

Ich sag doch nichts. Habe ich Kritik geübt? Würde ich niemals wagen ;) Mich hat zwar XML und DB etwas verblüfft (wenn schon, denn schon), aber warum nicht? Was du da als Beispiel abgeliefert hast sieht sehr gut aus, hat Hand und Fuß, ist professionell. Gutes Beispiel.

Ob thejacensolo nun mit TStringList oder TIniFile oder Record oder Datenbanken arbeitet, bleibt ihm überlassen. Ich hab seine Frage nur so verstanden, dass er einen Ansatz, eine Idee sucht.

Popov 14. Nov 2013 17:15

AW: Eine lineare Liste an Strings als Datei speichern
 
@thejacensolo

Was du bisher hast ist noch nicht viel. Bisher hast du nur
Delphi-Quellcode:
speicher : array of string;
ein Array, greifst aber noch nicht drauf zu. So wie man das verstehen könne ist, dass du die Vokabeln in dem Aray speichern möchtest. Noch machst du es noch nicht, wirst es vermutlich.

Trotzdem, bisher ist noch alles offen. Nun die Frage: willst du es tatsächlich mit dem Array machen? Nichts gegen Array, dann mußt du dich aber auch um alles kümmern, also die Verwaltung, das Speichern, das Laden, usw. Das ist eine Aufgabe für sich. Nicht sehr schwer, aber etwas Programmierarbeit.

Die andere Möglichkeit ist Vorhandenes zu nutzen. Ob das nun etwas mit TStringList oder TIniFile ist, diese Klassen bieten schon eine Verwaltung an. Du mußt dich nicht mehr um das Speichern kümmern, du speicherst deine Liste einfach mit einer Zeile Code. Bei Array wird es etwas mehr Code sein.

Also für was entscheidest du dich?


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:13 Uhr.
Seite 2 von 3     12 3      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz