Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Einführung in Pointer (https://www.delphipraxis.net/43704-einfuehrung-pointer.html)

El Cattivo 7. Apr 2005 13:49


Einführung in Pointer
 
Hallo,
ich habe zu meiner Frage schon das Forum durchsucht aber wie auch bei google ohne nennenswerten Erfolg. Deswegen hoffe ich, dass ihr mir helfen könnt. Es geht um Pointer und zwar ganz allgemein. Ich kann mit dem Begriff schon etwas anfangen und ich hab auch ne ungefähre Ahnung wozu Pointer nützlich sind. Aber ich bräuchte eine kleine Anleitung wie ich Pointer benutze. Einige Befehle kenne ich schon, ich weiß nur nicht wie ich die anwenden soll und ich bin mir auch nicht sicher ob die so richtig sind.
Wenn "wurzel" ein Zeiger ist dann gilt:
Delphi-Quellcode:
wurzel:=NIL;
Zeiger "erden" oder "ins Nichts Zeigen lassen"
Delphi-Quellcode:
new(wurzel);
Speicherplatz für "wurzel" reservieren.
Delphi-Quellcode:
wurzel:=123;
dem Ziel der Addresse "wurzel" wird ein Wert zugeweisen.
Delphi-Quellcode:
dispose(wurzel);
gibt den Speicherplatz wieder frei.
Wenn "wurzel" ein typisierter Zeiger ist, dann wird er folgendermaßen deklariert:
Delphi-Quellcode:
type PInt=^integer;
var wurzel: PInt;
der Abgespeicherte Wert lässt sich auch so darstellen (?)
Delphi-Quellcode:
wurzel^
Stimmt das soweit? Ich kann damit nicht sehr viel anfangen. Wie setze ich diese Befehle ein? Ich habe leider auch kaum Quelltexte gefunden und erst recht keine erläuterten. Ich wäre also sehr dankbar wenn mir jemand eine kleine Einführung in Sachen Pointer geben könnten. Vielleicht auch nen Link wo das anschaulich beschrieben wird.

ste_ett 7. Apr 2005 14:00

Re: Einführung in Pointer
 
Wenn der Zeiger "wurzel" auf etwas zeigt...
if (wurzel <> nil) then

Zeiger "ins Nichts Zeigen lassen"
wurzel := nil;

Speicherplatz für "wurzel" reservieren.
GetMem(wurzel);

dem Ziel der Addresse "wurzel" wird ein Wert zugeweisen.
wurzel := ^MeinObjekt;

gibt den Speicherplatz wieder frei.
FreeMem(wurzel);

Wenn "wurzel" ein typisierter Zeiger ist, dann wird er folgendermaßen deklariert:
type PInt = ^Integer;
var wurzel: PInt;

der Abgespeicherte Wert lässt sich auch so darstellen
wurzel^

himitsu 7. Apr 2005 14:06

Re: Einführung in Pointer
 
Schau mal beim Luckie nach.


www.Luckie-Online.de


dort gibt es viele Programme (natürlich mit Quellcode)

Und viele Tuturials mit und sogar einige speziel über Pointer.

SirThornberry 7. Apr 2005 14:26

Re: Einführung in Pointer
 
@ste_ett: Anstelle von GetMem und FreeMem ist New und Dispose zu bevorzugen (steht auch in der Delphihilfe wenn du diese mal zu GetMem aufrufst)

himitsu 7. Apr 2005 14:33

Re: Einführung in Pointer
 
hmmm?

"GetMem und FreeMem"

Ja, da steht was in der OH, aber ich verwende auch noch diese ... hab irgendwie nicht rausbekommen, wie man bei New die Speichergröße angibt, welche man haben möchte.
Außerdem arbeitet Delphi selber auch damit und nicht mit new/dispose ... jedenfalls kommt getmem/freemem ziehmlich oft iim Source der Delphi-Komponenten vor :shock:

ste_ett 7. Apr 2005 14:38

Re: Einführung in Pointer
 
Zitat:

Zitat von himitsu
hmmm?

"GetMem und FreeMem"

Ja, da steht was in der OH, aber ich verwende auch noch diese ... hab irgendwie nicht rausbekommen, wie man bei New die Speichergröße angibt, welche man haben möchte.
Außerdem arbeitet Delphi selber auch damit und nicht mit new/dispose ... jedenfalls kommt getmem/freemem ziehmlich oft iim Source der Delphi-Komponenten vor :shock:

Die Größe für den Speicherbereich richtet sich automatisch nach der benötigten Größe des Objektes, das du bei "New(Objekt);" angibst.

El Cattivo 7. Apr 2005 14:45

Re: Einführung in Pointer
 
Ok, die Befehle sind mir dann also klar. Aber wenn ich damit etwas sinnvolles machen will, zum Beispiel eine Kette, dann hab ich schon wieder Schwierigkeiten. Dann sieht das zum Beispiel so aus:
Delphi-Quellcode:
type Zeiger=^Element
Element:record
rechst:zeiger;
inhalt:integer;
end;
var wurzel, lauf: zeiger;
begin
wurzel:=NIL;
new(lauf);
lauf^.rechts:=NIL;
//"lauf^.rechts" ist also ein Zeiger, der vom Ziel von Zeiger "lauf" ausgeht und erstmal ins Leere zeigt?//
lauf^.inhalt:=1;
//ist "lauf^.inhalt" das selbe wie "lauf^"?//
Bis hierhin hätte man also einen Zeiger "lauf" mit "lauf^"=1, einen Zeiger "wurzel", der ins Leere zeigt und einen Zeiger "lauf^.rechts", der von "lauf^" aus ins Leere zeigt.
Nun gehts weiter:
Delphi-Quellcode:
wurzel:=lauf^;
new(lauf);
lauf^.rechts:=wurzel;
lauf^.inhalt:=2;
wurzel:=lauf;
der Zeiger "wurzel" zeigt jetzt auf einen Speicherplatz in dem der selbe Wert wie "lauf^" (1) gespeichert ist. der Zeiger "lauf" bekommt einen neuen Speicherplatz reserviert. der Zeiger "lauf^.rechts", der vom Ziel von "lauf" ausgeht zeigt jetzt auf den selben Speicherplatz wie "wurzel". "lauf^.inhalt" wird überschrieben. Der Inhalt ist nun ein anderer, "lauf" stellt aber immer noch die selbe Addresse dar.
Wenn das so alles richtig war, dann hätte ich noch ne Frage. Wollte man die Kette um eine 3 erweitern, müsste man dann mit einem "lauf^.rechts^.rechts"-Zeiger arbeiten? gibt es so einen Zeiger überhaupt?

Danke für den link, ich denke der hilft mir auch weiter.

Ich denke für mich ist das noch nicht so relevant ob ich new und dispose oder Getmem und freemem benutze. So komplex sind meine Programme nicht gerade *g*...

himitsu 7. Apr 2005 14:52

Re: Einführung in Pointer
 
@El Cattivo

OK, das mag ja nicht schlecht sein, aber was macht dann New bei dem Typen Pointer und PChar, die haben ja keine feste Größe und für sowas brauchte ich diese Funktionen ja :gruebel:

SirThornberry 7. Apr 2005 14:56

Re: Einführung in Pointer
 
für PChars gibt es "StrAlloc"

El Cattivo 7. Apr 2005 15:41

Re: Einführung in Pointer
 
Also das mit dem new hab ich so verstanden.
Wenn p nen Pointer ist und n ne gespeicherte variable, dann weist man mit p:=@n p die Addresse von n zu. Wenn p noch auf keinen Wert zeigt, man aber bereits auf den Raum zugreifen will, auf den der Pointer zeigt, dann schreibt man new(p). Ich schätze mal, wenn p:=NIL wäre, dann könnte man nicht p^.rechts schreiben.
Aber eigentlich wollte ich hier die Fragen stellen :lol:, ich weiß ja nichtmal was ein PChar ist und mit " für PChars gibt es "StrAlloc"" kann ich erst recht nichts anfangen... :shock:
Ich wollte eigentlich nur wissen wie man Pointer anwendet, dass man ne Kette erstellt, in die man Elemente einfügen und auslesen kann und die man sortieren kann.
Die Kette unten hat aber erst zwei Eltemente (1 und 2) und ich hab keine Ahnung wie man die erweitet und ich habe nur ne leichte Ahnung wie man die sortieren könnte...

Khabarakh 7. Apr 2005 15:48

Re: Einführung in Pointer
 
Zitat:

Zitat von OH
Ein PChar ist ein Zeiger auf einen nullterminierten String mit Zeichen des Typs Char. Jeder der drei Zeichentypen besitzt einen integrierten Zeigertyp:

PChar ist ein Zeiger auf einen nullterminierten String mit 8-Bit-Zeichen.
PAnsiChar ist ein Zeiger auf einen nullterminierten String mit 8-Bit-Zeichen.
PWideChar ist ein Zeiger auf einen nullterminierten String mit 16-Bit-Zeichen.

PChars bilden mit kurzen Strings den ursprünglichen String-Typ von Object Pascal. Sie wurden als Kompatibilitätstyp zur Sprache C und zur Windows-API eingeführt.

Das erklärt den PChar doch ziemlich gut.

El Cattivo 7. Apr 2005 16:13

Re: Einführung in Pointer
 
Ja, ok... Aber darum gings mit jetzt eigentlich nicht haupsächlich.

SirThornberry 7. Apr 2005 16:14

Re: Einführung in Pointer
 
was genau hast du denn jetzt noch nicht verstanden? also welchen Operator(@ ^ ...) oder welche funktion (new, dispose...)

Pseudemys Nelsoni 7. Apr 2005 16:17

Re: Einführung in Pointer
 
Ich glaube er versteht nicht, wo und wann man pointer (verkettete listen hier ausgenommen) benutzen sollte bzw wann das von Vorteil ist. Ich verstehs naemlich auch nicht, ich bin immer ohne ausgekommen.

atreju2oo0 7. Apr 2005 16:32

Re: Einführung in Pointer
 
Mal als Beispiel:

Du willst Kundendaten speichern, und weißt nicht genau wieviele das werden.
Ein super Fall um Listen zu erklären ;)

Als erstes mal muss man den Typ deklarieren:

Delphi-Quellcode:
PMyDaten=^TMyDaten;
TMyDaten=record
  name:string;
  alter:integer;
  .
  .
  .
  next:PMyDaten;
 end;
Als nächstes braucht man den Anker/Wurzel.
Dieser wird beim Start des Progs einmal erstellt und danach NIE mehr angerühert, ausser beim beenden!

Delphi-Quellcode:
var MyDaten:PMyDaten;


new(MyDaten);
MyDaten.next:=nil;
Damit haste alles schonmal gut vorbereitet um die Liste nun zu füllen...
Wir stellen uns einfach mal vor wir haben ein Formular, wo die Daten in edits und so richtig eingegeben
wurden. Dann ist unten noch nen Knopf "Daten hinzufügen"

Delphi-Quellcode:
procedure Datenhinzufügen;
var help:PMyDaten // den Pointer nehmen wir um uns durch die Liste zu hangeln
begin
help:=MyDaten; // jetzt zeigen help und mydaten auf den selben Speicherbereich.
while help.next<>nil do //um zum letzten Element der Liste zu kommen gehen wir solange eins weiter bis das nachfolgende NIL ist.
  help:=help.next

// Jetzt haben wir mit help also einen Pointer der auf den Speicherpplatz des letzten Elements der Liste zeigt.
// Jetzt können wir das neue Element anhängen

new(help.next) // New stellt Speicherbereich für ein neues Element her und help.next zeigt automatisch auf dieses.
// Jetzt müssen wir noch auf das neue Element draufzeigen, da wir ja noch beim vorletzten hängen
help:=help.next;
// Na jetzt kommt nur noch Schreibarbeit: Werte eintragen und next auf nil setzten

help.Name:=Ich;
help....
help.next:=nil;

end;

// Das wars dann auch schon!

SirThornberry 7. Apr 2005 16:39

Re: Einführung in Pointer
 
Liste der Anhänge anzeigen (Anzahl: 1)
Beispiel für Pointer.
Du hast eine Musiksoftware und möchtest natürlich zu jedem Lied das ID3-Tag anzeigen.
Jetzt wäre es speicherverschwendung wenn du 10 Listen hast in denen jeweils ein paar Lieder gleich sind das du in all diesen Listen das ID3Tag speicherst. Lösung ist das man eine Große Liste im Speicher hat wo alle Informationen zu der Datei gespeichert werden und die Playlisten sind dann nur noch Listen mit Pointer welche auf die Informationen zeigen (Bild zu diesem beispiel im Anhang, die Zahlen 1 bis 14 stellen dabei die Pointer(adressen) dar)

El Cattivo 7. Apr 2005 17:28

Re: Einführung in Pointer
 
Ok, danke! Ich habt mir sehr geholfen. Mein Denkfehler war glaub ich, dass ich dachte jeder gespeicherte Wert bräuchte einen eigenen Pointer um die einzelenen Werte aufrufen zu können. Aber man lässt dann wohl in dem Bsp. von atreju2oo0 die zwei Zeiger durchhangeln und an der Stelle stoppen wo der Wert auf den gezeigt wird ein bestimmter ist. Ich dachte durch den Befehl "help:=help.next;" würde die ehemals in help gespeicherte Information zur Speicherleiche werden. Das erstellen einer solchen Kette könnte man ja so darstellen:
http://mitglied.lycos.de/ovittacel/l...sachen/bla.JPG
Hier beim zweiten Element sind noch für alle Elemente Adressen vorhanden. Aber MyDaten zeigt doch immer auf das erste Element und help und help^.next gehen immer weiter. Wie kann man dann (wenn man jetzt nur die Namen der Kunden speichert) bei dem fünfen, oder sechsten Element angekommen, wieder auf den ersten help^.name zugreifen? einfach durch
Delphi-Quellcode:
help:=MyDaten;
while help.next<>help^.name do
help:=help.next
Ist dann das erste help das gleiche wie beim erstellen der Kette? Wenn das so wäre, dann hätte ichs endlich verstanden :-D
Und das Pointer Speicherplatz spaaren hab ich jetzt auch begriffen :wink: .

DGL-luke 8. Apr 2005 15:38

Re: Einführung in Pointer
 
*räusper*

da ich auf luckies seite nichts zu pointern gefunden habe, frag ich hier:

Delphi-Quellcode:
//globale vars
var currentbox:^TListBox;

procedure TForm1.LBbeforeMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
currentbox:=@sender;

end;

procedure TForm1.deleteClick(Sender: TObject);
begin
currentbox^.DeleteSelected;
end;
wieso wirft mir das ne AV??

Pseudemys Nelsoni 8. Apr 2005 15:57

Re: Einführung in Pointer
 
Weil du "currentbox" keinen Speicher zugewiesen hast (New())

DGL-luke 8. Apr 2005 16:20

Re: Einführung in Pointer
 
oh * mein * gott * so * ein * dummer * anfängerfehler *

(sich bei jedem stern das geräusch vorstellen, das ein auf eine hölzerne tischplatte aufprallender kopf erzeugt)

EDIT: es geht immer noch nicht.... ich rufe new(currentbox) im formcreate und im mousemove( wo der pointer ne adresse bekommt, siehe oben) auf. :pale:

EDIT2: prinzipiell müsste das aber funktinieren, oder? ich missverstehe da nicht die funktion von pointern?!

Pseudemys Nelsoni 8. Apr 2005 16:34

Re: Einführung in Pointer
 
Zeig mal den code her, bei mir gibts kein Fehler. Btw das "@" kannst du weglassen, klassen werden immer als referenz übergeben

bttb930 8. Apr 2005 16:35

Re: Einführung in Pointer
 
Mal eine Frage:

Seid ihr Geschichtsforscher?

Oder programmiert ihr mit Turbo Pascal 5.0?

Zeiger braucht man heutzutage in Delphi so gut wie gar nicht mehr. Records auch nicht. Das wurde alles extrem vereinfacht und hier scheint es niemand mitbekommen zu haben.

Benutzt einfach Klassen und macht euch über Pointer keine Gedanken.

Natürlich ist es hilfreich zu wissen, wie das funktioniert, aber wie gesagt: Borland hat da in den letzten Generationen viel vereinfacht. Ihr benutzt ja auch schon die IDE und nicht den vi, oder? Und die Icons unter Windows und nicht die Kommandozeile, oder? Will heissen: Manchmal sind Kommandozeile, vi und Pointer sehr mächtig, aber in der Regel kommt man auch ohne aus. Und fährt besser damit (die Programme werden lesbarer und die eigene Fehlerquote verringert sich).

bttb930 8. Apr 2005 16:40

Re: Einführung in Pointer
 
Und gleich im Anschluß eine Antwort hierauf:

Zitat:

Zitat von DGL-luke
Delphi-Quellcode:
//globale vars
var currentbox:^TListBox;

procedure TForm1.LBbeforeMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
currentbox:=@sender;

end;

procedure TForm1.deleteClick(Sender: TObject);
begin
currentbox^.DeleteSelected;
end;
wieso wirft mir das ne AV??

Ist doch klar: TListBox ist eine Klasse, also abgeleitet von TObject und damit von Borland soweit vereinfacht, dass Sender schon selbst ein Zeiger auf die Listbox ist. CurrentBox := @Sender setzt dann CurrentBox auf die Adresse des Zeigers, der auf die Listbox zeigt. Damit ist CurrentBox^.DeleteSelected Schwachsinn, denn eigentlich müsste es heissen (CurrentBox^)^.DeleteSelected.

Wie gesagt: Borland hat das alles vereinfacht (schon vor Jahren) und seitdem geht's so:

Delphi-Quellcode:
//globale vars
var currentbox: TListBox;

procedure TForm1.LBbeforeMouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  currentbox := sender;
end;

procedure TForm1.deleteClick(Sender: TObject);
begin
  currentbox.DeleteSelected;
end;

Pseudemys Nelsoni 8. Apr 2005 16:48

Re: Einführung in Pointer
 
Das weiss er selbst. Er möchte es aber mit Pointern versuchen um Selbige zu kapieren. Zum üben ist das ganz gut. Ich denke kaum das er das in _diesem_ Fall wirklich so am Ende macht.

DGL-luke 8. Apr 2005 17:03

Re: Einführung in Pointer
 
doch ich hatte genau das so vor.
ich habe nämlich drei listboxen, ein popup und ein deletclick. -> nur eine zeile code für drei sachen. ist doch schön, oder?(eingentlich sinds ja vier zeilen.... :D)

und warum macht borland solche verienfachungen? damit ein armer noob in AVs ertrinkt....

EDIT: wieso erzählt ihr mir hier jetzt schwachsinn?

die version von bttb930 geht nämlich kein stück..... hab jetzt nämlich seinen code, und currentbox und sender sind absoult inkmpatibel. dacht ich mirs doch....([Fehler] Unit1.pas(59): E2010 Inkompatible Typen: 'TListBox' und 'TObject')

...
werd ichs wohl doch selber rausfinden müssen. also das enttäuscht mich jetzt wirklich....

bttb930 8. Apr 2005 17:13

Re: Einführung in Pointer
 
naja, getestet hab ich den code nicht, aber dann schreib einfach

Delphi-Quellcode:
if Sender is TListBox then
  CurrentBox := Sender as TListBox;

DGL-luke 8. Apr 2005 17:16

Re: Einführung in Pointer
 
Liste der Anhänge anzeigen (Anzahl: 1)
dir ist aber schon klar, dass ich nen pointer habe, also mit den "echten" listboxen auf meinem formular arbeiten will udn nicht mit der kopie davon, die dann in meinem currentbox gespeichert ist?

ich poste mal das projekt hier(nur source; sollte aber mit D2005 sofort kompilieren; selbsterklärend; kann man mit D2005 abwärtskompatibel projekte speichern?)

bttb930 8. Apr 2005 17:17

Re: Einführung in Pointer
 
Ja, Du hast dann einen Pointer und keine Kopie.

Übrigens ist dies ein gutes Beispiel dafür, dass durch die Änderung von Borland Fehler schon beim Compilieren gefunden werden. Denn den Zeiger hättest Du einfach zuweisen können, ohne Typprüfung, d.h. Du hättest auch den Zeiger der eigentlich auf eine TListBox zeigen soll auf einen TButton zeigen lassen können - und dann krachts. So wie ich's gemacht hab geht das aber nicht - da meckert der Compiler spätestens bei der Zuweisung.

Wichtig ist natürlich das "if Sender is TListBox" vor dem "... := Sender as TListBox", denn ohne diese Prüfung kracht's doch wenn Sender mal keine TListBox ist.

DGL-luke 8. Apr 2005 17:25

Re: Einführung in Pointer
 
Zitat:

Wichtig ist natürlich das "if Sender is TListBox" vor dem "... := Sender as TListBox", denn ohne diese Prüfung kracht's doch wenn Sender mal keine TListBox ist.
das is mir klar, soweit bin ich auch schon.

könntest du dann bitte den source oben zum laufen bringen?

wäre dir sehr dankbar.

ps: im moment ist es nur so implementiert, dass es nur für eine listbox funktioniert. ich bin kein noob, und kriege das dann schon hin, auf auf die anderen listboxen das onclick zu setzen....

EDIT: es funktioniert wirklich...... omg sry dass ich so misstrauisch war. aber das ist doch nicht normal dass eine ganz normale globale variable einfach so zum pointer wird....

bttb930 8. Apr 2005 17:52

Re: Einführung in Pointer
 
Zitat:

Zitat von DGL-luke
aber das ist doch nicht normal dass eine ganz normale globale variable einfach so zum pointer wird....

was ist schon normal?

El Cattivo 9. Apr 2005 13:12

Re: Einführung in Pointer
 
Zitat:

Zitat von bttb930
Mal eine Frage:

Seid ihr Geschichtsforscher?

Oder programmiert ihr mit Turbo Pascal 5.0?

Zeiger braucht man heutzutage in Delphi so gut wie gar nicht mehr. Records auch nicht. Das wurde alles extrem vereinfacht und hier scheint es niemand mitbekommen zu haben.

Benutzt einfach Klassen und macht euch über Pointer keine Gedanken.

[...]

Erzähl das meinem Info-Lehrer... :roll:
Aber wenn ich nochmal auf das Beispiel von atreju2oo0 zurückkommen darf... wäre das dann "fifo" (first in first out)? Ist der Quelltext mit "lifo" (last in first out) nicht kürzer? Das Problem ist, ich weiß selbst nicht genau wie man fifo und lifo unterscheidet. Ich weiß nur, beim auslesen ließt man bei lifo rückwärts aus und bei fifo vorwärts, weil man beim einlesen bei fifo hinten dran hängt und bei lifo eben vorne.

El Cattivo 10. Apr 2005 15:25

Re: Einführung in Pointer
 
...ok
Ich hab noch eine letzte Frage. Ich habe eine Kette von Zahlen erstellt. Die sieht so aus:
das sind globale deklarationen:
Delphi-Quellcode:
type
  Zeiger=^Element;
     Element= record
               rechts: Zeiger;
               inhalt: integer;
               end;
var
  Form1: TForm1;
  a: integer;
  wurzel,lauf,help: zeiger;
Nun kommt das Program an sich:
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
begin
a:=1;
wurzel:=NIL;
end;

procedure TForm1.Button1Click(Sender: TObject);
var b: integer;
begin
b:=strtoint(edit1.text);
if a=1
   then
     begin
       new(lauf);
       lauf^.rechts:=NIL;
       lauf^.inhalt:=b;
       wurzel:=lauf;
       a:=2;
     end
   else
     begin
       while lauf^.rechts<>NIL do
         lauf:=lauf^.rechts;
       new(lauf^.rechts);
       lauf:=lauf^.rechts;
       lauf^.inhalt:=b;
       lauf^.rechts:=NIL;
     end;
edit1.text:='';

end;
Und die Ausgabe in ein label:
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
begin
lauf:=wurzel;
label1.Caption:=inttostr(lauf^.inhalt) + ',';
while lauf^.rechts<>NIL do
  begin
    lauf:=lauf^.rechts;
    label1.Caption:=label1.caption + inttostr(lauf^.inhalt) + ',';
  end;
end;
Für das sortieren habe ich folgenden Ansatz:
Delphi-Quellcode:
procedure TForm1.Button3Click(Sender: TObject);
begin
lauf:=wurzel;
help:=lauf^.rechts;
while lauf.rechts.rechts<>NIL do
  if lauf^.rechts^.inhalt<help^.rechts^.inhalt
    then
      begin
        lauf^.rechts:=help^.rechts;
        lauf^.rechts^.rechts^.rechts:=help;
        lauf^.rechts^.rechts:=lauf^.rechts^.rechts^.rechts;
        lauf^.rechts^.rechts^.rechts:=help^.rechts^.rechts;
      end
    else
      begin
        lauf:=help;
        help:=lauf^.rechts;
      end;
label2.Caption:=label1.caption + inttostr(lauf^.inhalt) + ',';
end;
Achso ja. Und meine Frage ist, wie ich diese Pointerkette sortiert bekomme. Wohlgemerkt ohne die gespeicherten Elemente zu ändern sondern nur durch "Verbiegen" der Pointer..?

El Cattivo 24. Apr 2005 14:24

Re: Einführung in Pointer
 
...Oder vielleicht kann mir wenigstens jemand sagen wie man ein Glied einer Pointerkette löscht... :duck:
Ich kann Pointer ja auch nicht mehr sehen. Ich habe auch nen Ansatz, der funktioniert aber nicht.
Delphi-Quellcode:
r:=strtoint(edit5.text);
lauf:=wurzel;
for n:=1 to r-1 do
  lauf:=lauf.rechts;
help:=lauf.rechts;
dispose(lauf);
lauf:=help;

Motzi 24. Apr 2005 14:31

Re: Einführung in Pointer
 
Wenn ich den Thread schon früher gesehen hätte, hätte ich schon früher auf mein Tutorial verweisen - naja, dann hol ich das halt mal nach.. ;)
Auf www.manuel-poeter.de findest du ein sehr umfangreiches Pointer-Tutorial von mir. Für diejenigen die schon glauben es zu kennen - die alte Version wurde komplett überarbeitet und das alte (schlechte) Beispiel-Projket wurde durch ein neues ersetzt! :)
Ich denke da findest du auch fast alle Fragen eine Antwort..! :)

El Cattivo 24. Apr 2005 19:28

Re: Einführung in Pointer
 
Vielen Dank! Das Tutorial ist mir wirklich eine große Hilfe! :thumb: Super!

Boombuler 25. Apr 2005 08:36

Re: Einführung in Pointer
 
Ich sag nur

Pointerfun with BINKY

http://www.cs.stanford.edu/cslibrary...nPascalBig.avi <-- Large Version (34 MB)
http://www.cs.stanford.edu/cslibrary...rFunPascal.avi <-- Small Version (14 MB)

Viel Spass damit
Greetz
Boombuler

Tormentor32 18. Jan 2007 08:03

Re: Einführung in Pointer
 
Muss das Thema nochmal aufkochen :wink:

warum gibt folgendes eine AV?
Delphi-Quellcode:
type
  PBitmap = ^TBitmap;
var
  Bitmap: PBitmap;
{...}
  new(PBitmap);
  Bitmap := @image1.picture.bitmap;
  Bitmap^.Canvas.Brush.Color := clred;
  Bitmap^.Canvas.Rectangle(0,0,10,10); // Hier krachts!
Gruß Richard

Muetze1 18. Jan 2007 08:56

Re: Einführung in Pointer
 
TBitmap ist intern ein Zeiger auf das Objekt. Durch deinen PBitmap Typ hast du dann einen Zeiger auf den Zeiger auf das Objekt.

Aber wie gesagt (wenn du den Thread gelesen hättest), wird auf Seite 2 schon erklärt, dass Instanzen intern Zeiger sind und du somit keinen solchen Zeigertyp brauchst. Eine Variable vom Typ TBitmap ist ein Zeiger.

Beispiel:
Delphi-Quellcode:
ShowMessage(IntToStr(SizeOf(TBitmap)) + ' bytes gross');
Schmeiss alles mit deinem PBitmap raus und nutze statt dessen einfach nur TBitmap.

Dein Code wie es reichen würde:
Delphi-Quellcode:
var
  Bitmap: TBitmap;
{...}
  Bitmap := image1.picture.bitmap;
  Bitmap.Canvas.Brush.Color := clred;
  Bitmap.Canvas.Rectangle(0,0,10,10); // Hier krachts!
Dein Code korrigiert:
Delphi-Quellcode:
type
  PBitmap = ^TBitmap;
var
  Bitmap: PBitmap;
{...}
  new(PBitmap);
  Bitmap^ := image1.picture.bitmap;
  Bitmap^.Canvas.Brush.Color := clred;
  Bitmap^.Canvas.Rectangle(0,0,10,10); // Hier krachts!
Dein Problem im Code ist folgender: Du reservierst Speicher für den Typen PBitmap. Danach zeigt PBitmap auf den reservierten Speicherbereich. Danach setzt du den Zeiger aber um und lässt ihn auf die Property von TPicture zeigen. Somit nutzt den alloziierten Speicher nicht und zum anderen zeigst du auf eine Property und kein richtiges Objekt. Bei der Dereferenzierung versucht er dann die Property als TBitmap zu benutzen. Dadurch wird der Getter der Property nicht ausgelöst und es gibt an der Stelle kein TBitmap -> AV

Tormentor32 18. Jan 2007 09:15

Re: Einführung in Pointer
 
Okay danke! Ich hatte den obrigen Thread gelesen, hatte es aber nicht richtig verstanden... Jedenfalls funktioniert es jetzt!

Aber das ist nicht bei einem Record so oder?
Wenn ich ein
Delphi-Quellcode:
TMyArray = Array[0..19,0..19] of TMyRecord
habe, dann kann ich mit meinem Zeiger auf ein Record den Aufruf
Delphi-Quellcode:
MyZeiger := @MyArray[x,y]
machen und dann über
Delphi-Quellcode:
MyZeiger^.ValueX
darauf zugreifen und die entsprechenden Werte modifizieren oder?

Edit: Juhu 100 Beiträge

Muetze1 18. Jan 2007 09:29

Re: Einführung in Pointer
 
Ja, kannst du. In dem Falle erstellst du direkt einen Zeiger auf das Element x des Arrays - das funktioniert entsprechend.

Aber: Ein Hinweis gleich dazu: Ein dynamisches Arrays ist intern ein Zeiger auf die Elemente des Arrays. Also auch hier aufpassen - ABER: ein Zeiger auf ein Element (wie dein Beispiel eben mit einem statischen Array) des Arrays funktioniert entsprechend dem statischen Array.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:21 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