AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi [Records] Codeoptimierung bei Übergabetypen

[Records] Codeoptimierung bei Übergabetypen

Ein Thema von Igotcha · begonnen am 21. Sep 2004 · letzter Beitrag vom 23. Sep 2004
Antwort Antwort
Seite 2 von 3     12 3   
Benutzerbild von Luckie
Luckie
(Moderator)

Registriert seit: 29. Mai 2002
37.260 Beiträge
 
Delphi 2006 Professional
 
#11

Re: [Records] Codeoptimierung bei Übergabetypen

  Alt 22. Sep 2004, 11:12
adata ist vom Typ TData. TData ist ein Record mit den Feldern FGBez und FMonat. Die methode GetNodeData liefert einen Pointer zurück. Das mal dazu wie es aussieht.

Erstmal hast du vergessen ein Feld anzugeben in dem die Daten abgelegt werden sollen:
Code:
adata[b].FGBez[/b] := ...;
Und zweitens ist ein Record nicht zu einem Pointer kompatibel, wie du es geschrieben hast:
Code:
adata := MyPointer;
Das hingegen würde gehen:
Delphi-Quellcode:
type
  TData = record
    ...;
  end;
  PData = ^TDate;

var
  adata: PData;

...

  adata := PData(MyPointer);
Also überdenk noch mal, was du eigentlich machen willst.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Igotcha

Registriert seit: 22. Dez 2003
544 Beiträge
 
Delphi 2006 Professional
 
#12

Re: [Records] Codeoptimierung bei Übergabetypen

  Alt 22. Sep 2004, 11:47
Zitat:
Also überdenk noch mal, was du eigentlich machen willst.
Das weiss ich schon, deshalb fragte ich ja hier Wie gesagt, meine Anwendung läuft, ich möchte sie aber in der Codegröße in Bezug auf die Records schrumpfen (u.a. auch wegen der Pflege).

Zitat:
adata ist vom Typ TData. TData ist ein Record mit den Feldern FGBez und FMonat. Die methode GetNodeData liefert einen Pointer zurück. Das mal dazu wie es aussieht.

Erstmal hast du vergessen ein Feld anzugeben in dem die Daten abgelegt werden sollen:
Code:
adata[b].FGBez[/b] := ...;
Nicht notwendig, da der Kompiliervorgang schon vorher abbricht. Die Zeile hätte ich noch hinschreiben können, ist aber unnötig.

Zitat:
Das hingegen würde gehen:
Delphi-Quellcode:
type
  TData = record
    ...;
  end;
  PData = ^TDate;

var
  adata: PData;

...
adata := PData(MyPointer);
Wenn ich das recht überblicke, dann würde ich damit wieder genau am Anfang meines Problems stehen denn:

Delphi-Quellcode:
type
  TData = record
    ...;
  end;
  PData = ^TDate;

var
  Istdaten: PData;
  Plandaten: PData;
  Prognosedaten: PData;
Müsste in allen drei Fällen auf die gleichen Inhalte zeigen, wenn ich das richtig sehe. Und bei

Delphi-Quellcode:
type
  TData = record
    ...;
  end;
  PData1 = ^TDate;
  PData2 = ^TDate;
  PData3 = ^TDate;
var
  Istdaten: PData1;
  Plandaten: PData2;
  Prognosedaten: PData3;
bin ich wieder bei meiner Ausgangsfrage, denn ich müsste in meinen Routinen entweder PData1 oder PData2 oder PData3 benutzen und hätte dann wieder drei Varianten, um den Pointer auf den richtigen Record zu setzen:

Delphi-Quellcode:
var
  myData: IstDaten;
begin
myData:=atree.GetNodeData(myNode); oder

var
  myData: Plandaten;
begin
myData:=atree.GetNodeData(myNode); oder

var
  myData: Prognosedaten;
begin
myData:=atree.GetNodeData(myNode); oder
Ich möchte garantiert nicht unhöflich erscheinen, aber ist das eigentliche Problem eigentlich erkannt worden? Jeder VTV hat seinen eigenen Record, da er eigene Daten enthält. Ein VTV zeigt die IstDaten, der zweite die Plandaten, der dritte die Prognosedaten an. Die Records sind in der Struktur alle gleich - das haben wir ja auch hinbekommen. Der Zugriff auf die Daten (neu, lesen, schreiben) steuert der VTV, indem beim schreiben oder lesen an den VTV die Aufforderung gesendet wird "Gib mir bitte einen Zeiger auf den Recordeintrag entweder auf die Ist-, Plan- oder Prognosedaten. Erst wenn ich diesen Zeiger habe, komme ich an die Daten des Recordsatzes. Dies erledigt die VTV-Methode "GetNodeData". Dies hängt damit zusammen, dass der VTV über die Daten, die er verwaltet nichts weiss, sondern nur pro Node eine Verknüpfung (sprich also nur die Nummer auf einen Record-Satz, nicht aber die Art des Record-Typs) auf einen Recordeintrag in Form einer verketteten Liste hat.

Um nicht, wie es im Moment existiert, für jeden VTV eigene Routinen schreiben zu müssen, die sich nur darin unterscheiden, auf welche Daten er zugreift, habe ich nach einer Vereinfachung gesucht. Und zwar in der Form, dass ich für alle drei VTV pro Aufgabe nur eine Routine schreibe, der ich mitteile a) welcher VTV überhaupt angesprochen wird und b) auf welche Recorddaten sich die Manipulation bezieht.

Für das Beispiel einer Summenbildung wäre das z.B.:

Delphi-Quellcode:
procedure BildeSumme(TreeViewIstDaten, IstDatenrecord)
procedure BildeSumme(TreeViewPlanDaten, PlanDatenrecord)
procedure BildeSumme(TreeViewPrognoseDaten, PrognoseDatenrecord)
Ich muss aber (wie schon mehrfach gesagt), sobald ich die Daten bearbeiten möchte, angeben, welche Daten bearbeitet werden sollen. Und diese Daten kann ich mir nur mit der Methode "GetNodeData" holen - das Ergebnis ist ein Zeiger auf den entsprechenden Record-Eintrag, abhängig vom dem "Node", der ausgewählt wurde. Die Variable muss aber vom richtigen Record-Typ (ist, Plan, Prognose) sein.

Um mal bei meiner Ursprungsdeklaration zu bleiben, folgendes (unsinniges) Beispiel ist möglich:

Delphi-Quellcode:
var
  myIst: pIstdaten;
  myPlan: pPlandaten;
begin
  myIst:=TreeviewIst.GetNodeData(Node);
  myPlan:=TreeviewIst.GetnodeData(Node);
In diesem Fall hätte ich mit der selben Methode des VTVs für IstDaten einen Zeiger bekommen auf meine Plan- und meine IstDaten (sagen wir mal einen Zeiger auf jeweils den zweiten Record ). Dies kommt daher, da der VTV nichts über die Art der Daten, die er verwaltet weiss.

Und genau das, also welche Art des Records bearbeitet werden soll, möchte ich als Parameter übergeben. Dieser Übergabeparamteter muss aber ein Pointer auf den richtigen Record (Ist-, Plan- oder Prognosedaten-Record) sein:

Delphi-Quellcode:
BildeSumme(TIST, pIstDaten)
BildeSumme(TPLAN, pPlanDaten)
BildeSumme(TPROGNOSE, pPrognoseDaten)

und dann sollte so etwas in der Art in der Procedure stehen:

procedure BildeSumme(atree: TVirtualStringTree; adata: ???)
begin
    adata:=atree.GetNodeData(Node);
    adata.FBez:='Test';
    etc.
end;
Gruß Igotcha
  Mit Zitat antworten Zitat
scp

Registriert seit: 31. Okt 2003
1.120 Beiträge
 
Delphi 7 Personal
 
#13

Re: [Records] Codeoptimierung bei Übergabetypen

  Alt 22. Sep 2004, 12:40
Also nach wie vor sollte dies die richtige Lösung sein:
Delphi-Quellcode:
type
  TData = record
    ...;
  end;
  PData = ^TDate;

var
  Istdaten: PData;
  Plandaten: PData;
  Prognosedaten: PData;

procedure BildSumme(atree: TVirtualStringTree; var adata: PData)
begin
    adata:=atree.GetNodeData(Node);
    adata.FBez:='Test';
    etc.
end;

begin
  BildeSumme(TreeIST, IstDaten);
  BildeSumme(TreePLAN, PlanDaten);
  BildeSumme(TreePROGNOSE, PrognoseDaten);
end;
Was meinst du denn mit
Zitat von Igotcha:
Müsste in allen drei Fällen auf die gleichen Inhalte zeigen, wenn ich das richtig sehe.
? Wenn du drei Variablen deklariert hast kannst du diese auch auf drei verschiedene Inhalte zeigen lassen. Das hat nichts damit zu tun, ob die jetzt alle PData heissen oder eben PIstData PPlanData usw.
Und wenn du unterscheiden können willst, aus welchem der drei VTVs ein Record ursprünglich kam, dann brauchst du im record ja nur einen Eintrag hinzufügen, etwa so:
Delphi-Quellcode:
type
  TMyRecordOrigin = (roPlan, roIst, roProgrnose);

type
  TData = record
    ...;
    Origin : TMyRecordOrigin;
  end;
  Mit Zitat antworten Zitat
Igotcha

Registriert seit: 22. Dez 2003
544 Beiträge
 
Delphi 2006 Professional
 
#14

Re: [Records] Codeoptimierung bei Übergabetypen

  Alt 22. Sep 2004, 13:41
Danke danke danke, jetzt habe ich ein neues Problem

Es funktioniert wunderbar, nur kann ich mir jetzt überhaupt nicht mehr erklären wieso

Delphi-Quellcode:
type
  TData = record
  FBez: String;
  FMonat: array [0..1] of double;
  end;
  PData = ^TData;

...

var
  Istdaten: PData;
  Plandaten: PData;
  Prognosedaten: PData;
...

procedure TForm1.BildeSumme(atree: TVirtualStringTree; var adata: PData; aString: String);
var
  myNode: PVirtualNode;
begin
      aTree.Clear;
      aTree.NodeDataSize:=sizeof(TData); // Dies ist die einzigste "Beziehung", die zwischen einem VTV und "Art der Daten" überhaupt auftaucht - diese Anweisung muss auch nur einmal im Programm pro VTV auftauchen
      myNode:=atree.AddChild(nil);
      atree.BeginUpdate;
      adata:=atree.GetNodeData(myNode);
      adata.FBez:=aString; // dient nur zum Testen, ob tatsächlich die richtigen Records angesprochen werden
      adata.FMonat[0]:=1000;
      adata.FMonat[1]:=2000;
      atree.EndUpdate;
end;

procedure TForm1.est11Click(Sender: TObject);
begin
    // Genauso wollte ich es haben :-)
    BildeSumme(TIST, IstDaten,'Ist');
    BildeSumme(TPLAN, Plandaten,'Plan');
end;
Hier wird mir schon etwas mulmig. Warum greift er auf den richtigen Record-Typ zu?

Delphi-Quellcode:
procedure TForm1.TISTFocusChanged(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex);
var
  myNode: PData;
begin
  myNode:=TIST.GetNodeData(Node);
  ShowMessage(myNode.FBez); // Anzeige "Ist"
end;

procedure TForm1.TPLANFocusChanged(Sender: TBaseVirtualTree;
  Node: PVirtualNode; Column: TColumnIndex);
var
  myNode: PData;
begin
  myNode:=TPlan.GetNodeData(Node);
  ShowMessage(myNode.FBez); // Anzeige "Plan"
end;
Und hier wird mir ganz schwummerig Ich habe beiden Treeviews (TIST, TPLAN) die gleiche Ereignis-Routine zugewiesen (dient zur Anzeige der Inhalte):

Delphi-Quellcode:
procedure TForm1.TISTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var
   myData : PData;
begin
  myData:=Sender.GetNodeData(node);

  if TextType=ttNormal then
  begin
    case Column of
      0: CellText:=myData.FBez;
      1: CellText:=floattostr(myData.FMonat[0]);
      2: CellText:=floattostr(myData.FMonat[1]);
  end;
  end;
end;
Ich kann mir das nur so erkären, dass der VirtualTreeview (der ja wie gesagt selbst die Daten nicht hält) durch die Methode "GetNodeDataSize" nicht nur die Grösse des Records, sondern anscheinend auch ein Verweis auf den Record anlegt.

Vielen Dank und Gruß
Igotcha

... der jetzt wohl einige Tage seinen Code dahingehend anpassen wird...
  Mit Zitat antworten Zitat
scp

Registriert seit: 31. Okt 2003
1.120 Beiträge
 
Delphi 7 Personal
 
#15

Re: [Records] Codeoptimierung bei Übergabetypen

  Alt 22. Sep 2004, 13:52
Der VTV "kennt" den Inhalt der Daten nicht, er verwaltet sie aber. Deshalb musst du ja auch einmal die Grösse angeben ( SizeOf(TData) ). Der VTV reserviert dann den Speicher und gibt bei GetNodeData() dann den Pointer auf den Speicherbereich zurück.
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#16

Re: [Records] Codeoptimierung bei Übergabetypen

  Alt 22. Sep 2004, 14:55
Hi Igotcha,

dein Verständnisproblem ist einfach zu erklären.

Du denkst immer noch, dass deine Funktion PData-Typen mit spezifischen Werten gleichsetzt. das ist aber nicht so.

Ich geb dir mal ein einfaches Beispiel:

Du willst drei Autos mit unterschiedlichen Fahrern haben, wobei die Autos alle vom gleichen Typ sind.
Alles gleich, Farbe, Motor ... usw.

Dieser Autotyp heißt jetzt nicht BMW oder so, sondern PData.

Du vergibst drei Stück davon mit drei unterschiedlichen Kennzeichen.

Jetzt sagst du einem Freund er soll alle Autos vom Typ PData (BMW) anhalten und fragen wie die Fahrer heißen.

Somit hast du ihm nicht gesagt er soll das Auto mit dem Kennzeichen x anhalten und das Auto mit dem Kennzeichen y usw. sondern eben Typbezogen. Da er weiß wo die Fahrer sitzen kann er gar nichts falsch machen, da die Typen ja identisch sind. Nur die Inhalte an der richtigen Stelle sind unterschiedlich. Und nur darum geht es dir.

Somit sind deine 3 Autos zwar dreimal da, aber alle vom gleichen Typ.

Somit kannst du deine Funktion "abstrahieren" (wenn ich mal so sagen darf). Welcher Record übergeben wird ist wurst, hauptsache der Typ stimmt und somit der Zugriff auf die richtige Stelle.

Die Deklaration:

procedure BildSumme(atree: TVirtualStringTree; var adata: PData)


ist somit ausreichend. Hier kannst alle Variablen vom Typ PData übergeben und es kommt immer das richtige zurück.

Gruß oki
  Mit Zitat antworten Zitat
Igotcha

Registriert seit: 22. Dez 2003
544 Beiträge
 
Delphi 2006 Professional
 
#17

Re: [Records] Codeoptimierung bei Übergabetypen

  Alt 22. Sep 2004, 15:02
Zitat von oki:
...ist somit ausreichend. Hier kannst alle Variablen vom Typ PData übergeben und es kommt immer das richtige zurück.
Ja und genau diese "Genialität" an der Sache hat mich verwirrt
  Mit Zitat antworten Zitat
oki

Registriert seit: 30. Dez 2002
Ort: Brandshagen
1.819 Beiträge
 
Delphi 2007 Professional
 
#18

Re: [Records] Codeoptimierung bei Übergabetypen

  Alt 22. Sep 2004, 15:08
ja klar, denk an mein Bsp. mit den Autos. Wenn du es erweiterst und dann noch sagst das Auto ist vom Typ "englisch" (Lenker rechts), dann verstehst du auch das Thema mit den Typen. Gleiche Typen sind halt von Ihrem Aufbau identisch, ob nun String oder ein von dir erstellte spezieller Record den du type'st. Aufbau, Bezeichner, alles identisch. Nur was dann an Werten drin steht ist auf die entsprechende Variable dieses Typs bezogen.

Bei den Objekten, Klassen und ihren Instancen ist es genau so.

Gruß oki
  Mit Zitat antworten Zitat
scp

Registriert seit: 31. Okt 2003
1.120 Beiträge
 
Delphi 7 Personal
 
#19

Re: [Records] Codeoptimierung bei Übergabetypen

  Alt 22. Sep 2004, 15:19
Gutes Beispiel. Dazu könnte man dann sagen, das der VTV dir nur den "Parkplatz" für die Autos zur Verfügung stellt. Der VTV muss nicht den Typ kennen und auch nicht wer drin sitzt (Inhalt), sondern nur die Grösse. Er gibt dir denn mit GetNodedata() den Stellpatz (Pointer) zurück.
  Mit Zitat antworten Zitat
Benutzerbild von maximov
maximov

Registriert seit: 2. Okt 2003
Ort: Hamburg
548 Beiträge
 
Delphi 2005 Professional
 
#20

Re: [Records] Codeoptimierung bei Übergabetypen

  Alt 22. Sep 2004, 21:00
Auch wenn das jetzt destruktiv ist:

Ich würde uneingeschränkt empfehlen solche geschichten mit klassen zu lösen. Da fällt dieser ganze record wahnsinn schonmal weg und man erspart sich massig probleme und gewinnt an dynamität. Erst recht wenn man bedenkt, das objekt 'nur' bessere records mit einem pointer auf die VMT sind OOP rulez.

Ausnahmen bestätigen natürlich auch hier die regel, da es vor kommen kann, dass man alte daten in binär kompatiblen strukturen laden muss. Das sieht mir hier aber nicht so aus, denn sonst könntest du nicht mit dynamischen strings arbeiten.
mâxîmôv.

{KDT}
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 20:44 Uhr.
Powered by vBulletin® Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2019 by Daniel R. Wolf