AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

array of X - Suche nach Element

Offene Frage von "peter001"
Ein Thema von peter001 · begonnen am 26. Nov 2009 · letzter Beitrag vom 26. Nov 2009
Antwort Antwort
peter001

Registriert seit: 2. Nov 2008
17 Beiträge
 
#1

array of X - Suche nach Element

  Alt 26. Nov 2009, 19:56
Hallo!

Eigentlich ein Anfängerproblem, aber ich habe scheinbar irgend einen Denkfehler.

Ich habe mir eine Art cache gebaut, Cache ist ein Objekt mit Methoden "isCached(name) -> boolean", "addToCache(CacheEntry)" und "getCached(pos) -> CacheEntry".

Als Attribut hat diese Klasse ein Array of TCacheEntry, welches im Constructor auf die Länge 0 gesetzt wird (dynamisches array).

Hier mal der Code:

Delphi-Quellcode:
unit QCache;

interface

uses
  ..., QCacheEntry;

type
  TQueryCache = class(TObject)
    entries: array of TQueryCacheEntry;

    constructor Create;
    destructor Destroy;

    function isCached(name: string; var pos:integer): boolean;
    function getCached(pos: integer): TQueryCacheEntry;
    procedure addEntryToCache(Charinfo: TQueryCacheEntry);
    function getNumEntries: integer;
  end;

var
  QueryCache: TQueryCache;

implementation

constructor TQueryCache.Create;
begin
  SetLength(entries,0);
end;

destructor TQueryCache.Destroy;
begin
  //
end;

function TQueryCache.getNumEntries: integer;
begin
  Result := Length(entries);
end;

function TQueryCache.getCached(pos: integer): TQueryCacheEntry;
begin
  if entries[pos] <> nil then
  Result := entries[pos];
end;

function TQueryCache.isCached(name:string; var pos:integer):boolean;
var
  i: integer;
begin
  Result := false;
  pos := 0;
  try
    if Length(entries) > 0 then
    begin
      for i := 0 to Length(entries)-1 do
      begin
        if entries[i].option1 = name then
        begin
          Result := true;
          pos := i;
        end;
      end;
    end;
  except
    Result := false;
  end;
end;

procedure TQueryCache.addEntryToCache(Charinfo: TQueryCacheEntry);
begin
  SetLength(entries,Length(entries)+1);
  entries[Length(entries)-1] := Charinfo;
  Charinfo.Free;
end;

end.
und hier die TQueryCacheEntry:
Delphi-Quellcode:
unit QCacheEntry;

interface

type
  TQueryCacheEntry = class(TObject)
    option1: string;
    option2: string;
    option3: string;
    option4: string;
    option5: string;
    option6: string;

constructor Create;
end;

implementation

constructor TQueryCacheEntry.Create;
begin
  inherited Create;
  option1:= '';
  option2:= '';
  option3:= '';
  option4:= '';
  option5:= '';
  option6:= '';
end;

end.

Problem ist nun dieser Abschnitt, wo ich eine Funktion aufrufe:

Delphi-Quellcode:
procedure TForm1.testName(name:string);
var
  ...
  qpos: integer;
  Charinfo: TQueryCacheEntry;
begin
  qpos := 0;

  if Cache.isCached(name, qpos) = true then // <- Fehler kommt in dieser Zeile
  begin
    ListBox1.Items.Add('Found Object in cache: ' + name + ' in Position: ' + IntToStr(qpos) + ' and total cache size: ' + IntToStr(Cache.getNumEntries));
    Charinfo := Cache.getCached(qpos);
  end else
  ...
Ich bekomme also einen Namen und prüfe, ob dieser Name irgendwo im Cache auftaucht.
Als Fehler bekomme ich die Meldung "...exe raised an exception. Error in Reading of Adress ..." Also für mich sehr nichtssagend.
Stehen bleibt er bei der oben markierten Zeile.
Problem scheint also diese Methode "isCached" zu sein, die das dynamische Array mit den Cache Einträgen durchläuft, nach einer Übereinstimmung sucht und dessen Position zurückgibt.

Delphi-Quellcode:
function TQueryCache.isCached(name:string; var pos:integer):boolean;
var
  i: integer;
begin
  Result := false;
  pos := 0;
  try
    if Length(entries) > 0 then
    begin
      for i := 0 to Length(entries)-1 do
      begin
        if entries[i].option1 = name then
        begin
          Result := true;
          pos := i;
        end;
      end;
    end;
  except
    Result := false;
  end;
end;
Was ist da verkehrt?

Ich danke für jede Antwort, falls ihr mehr Infos braucht, sagt bescheid.
  Mit Zitat antworten Zitat
Apollonius

Registriert seit: 16. Apr 2007
2.325 Beiträge
 
Turbo Delphi für Win32
 
#2

Re: array of X - Suche nach Element

  Alt 26. Nov 2009, 20:03
In addEntryToCache gibst du das übergebene Objekt frei. Danach steht im Array nur noch Müll.
Wer erweist der Welt einen Dienst und findet ein gutes Synonym für "Pointer"?
"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.768 Beiträge
 
Delphi 10.4 Sydney
 
#3

Re: array of X - Suche nach Element

  Alt 26. Nov 2009, 20:10
Delphi-Quellcode:
procedure TQueryCache.addEntryToCache(Charinfo: TQueryCacheEntry);
begin
  SetLength(entries,Length(entries)+1);
  entries[Length(entries)-1] := Charinfo;
  Charinfo.Free;
end;
Hallo,

wie Apollonius scho beschrieben hat gibts du die Instanz wieder frei.
Da Du nur die Addresse der Instanz Deinem Array übergeben hast ist
auch das Element im Array nicht mehr existent.

Vielleicht ist es besser in der addEntryToCache Methode
alle Daten von CharInfo zu kopieren.
Also ein neues Element im Array erzeugen und dann den Inhalt von
CharInfo in das neue Element kopieren.

Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
peter001

Registriert seit: 2. Nov 2008
17 Beiträge
 
#4

Re: array of X - Suche nach Element

  Alt 26. Nov 2009, 20:21
Super danke euch!

Genau sowas in der Art hatte ich mir gedacht
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.080 Beiträge
 
Delphi 12 Athens
 
#5

Re: array of X - Suche nach Element

  Alt 26. Nov 2009, 20:24
warum das globale var QueryCache: TQueryCache; ?

die Konstruktoren kannst du dir sparen
- dynamische Array und String sind per Standard eh leer

leere Destruktoren/Funktionen sind ebenfalls sinnlos

getCached liefert einen undefinierten Wert, wenn nichts im Cache ist

if Length(entries) > 0 then in isCached bringt auch nichts, denn dieses ist praktisch in der Forschleife schon vorhanden.

Try-Except ... eine dort auftretende Exception sollte man nicht einfach unter den Tisch kehren, denn dieses würde auf eine defekte Datenstruktur hinweisen und sowas dürfte eh nie auftreten

Vergleiche mit =true macht man nicht
(es sei denn man muß GENAU auf True(1) vergleichen)

Delphi-Quellcode:
unit QCache;

interface

uses
  ..., QCacheEntry;

type
  TQueryCache = class(TObject)
  private
    entries: array of TQueryCacheEntry;
  public
    function isCached(name: string; var pos:integer): boolean;
    function getCached(pos: integer): TQueryCacheEntry;
    procedure addEntryToCache(Charinfo: TQueryCacheEntry);
    function getNumEntries: integer;
  end;

implementation

function TQueryCache.getNumEntries: integer;
begin
  Result := Length(entries);
end;

function TQueryCache.getCached(pos: integer): TQueryCacheEntry;
begin
  //if Assigned(entries[pos]) then
  // Result := entries[pos]
  //else
  // Result := nil;

  // gekürzt kommt das bei raus und nebenbei wird nun nur noch einmal gesucht :)
  Result := entries[pos];
end;

function TQueryCache.isCached(name:string; var pos:integer):boolean;
var
  i: integer;
begin
  Result := false;
  for i := 0 to Length(entries)-1 do
    if entries[i].option1 = name then
    begin
      Result := true;
      pos := i;
      break; // wenn gefunden, dann braucht man nicht weitersuchen
    end;
end;

procedure TQueryCache.addEntryToCache(Charinfo: TQueryCacheEntry);
begin
  SetLength(entries,Length(entries)+1);
  entries[High(entries)] := Charinfo;
end;

end.
Delphi-Quellcode:
unit QCacheEntry;

interface

type
  TQueryCacheEntry = class(TObject)
    option1: string;
    option2: string;
    option3: string;
    option4: string;
    option5: string;
    option6: string;
  end;

implementation

end.
Delphi-Quellcode:
procedure TForm1.testName(name:string);
var
  ...
  qpos: integer;
  Charinfo: TQueryCacheEntry;
begin
  qpos := 0;

  if Cache.isCached(name, qpos) then
  begin
    ListBox1.Items.Add('Found Object in cache: ' + name + ' in Position: ' + IntToStr(qpos) + ' and total cache size: ' + IntToStr(Cache.getNumEntries));
    Charinfo := Cache.getCached(qpos);
  end else
  ...
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Christian Seehase
(Co-Admin)

Registriert seit: 29. Mai 2002
Ort: Hamburg
11.116 Beiträge
 
Delphi 11 Alexandria
 
#6

Re: array of X - Suche nach Element

  Alt 26. Nov 2009, 22:11
Moin Peter,

Zitat von himitsu:
Vergleiche mit =true macht man nicht
(es sei denn man muß GENAU auf True(1) vergleichen)
was analog auch für das Prüfen auf false gilt.
Dann sollte man nur auf "if not Boolscher-Ausdruck then" prüfen.


Du könntest übrigens auf Deine eigene Listenimplementierung verzichten, wenn Du Deine Liste nicht von TObject sondern von TObjectList (zu finden in der Unit contnrs) ableitest.
Da die Cache-Entries Objekte sind, bietet sich das, meiner Ansicht nach, an.
Das dürfte Deine Liste vereinfachen.
Tschüss Chris
Die drei Feinde des Programmierers: Sonne, Frischluft und dieses unerträgliche Gebrüll der Vögel.
Der Klügere gibt solange nach bis er der Dumme ist
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:39 Uhr.
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