Delphi -- Zeigervariablen???

Diskutiere Delphi -- Zeigervariablen??? im Developer Network Forum im Bereich Hardware & Software Forum; Hi Kann mir jemand den Sinn und Zweck von Zeigervariablen erklären? Im Grunde ist eine "normale" Variable wie z.B. "var test: integer" doch auch...
  • Delphi -- Zeigervariablen??? Beitrag #1
D

Deep Space

Bekanntes Mitglied
Dabei seit
01.08.1999
Beiträge
2.004
Reaktionspunkte
0
Hi

Kann mir jemand den Sinn und Zweck von Zeigervariablen erklären?
Im Grunde ist eine "normale" Variable wie z.B. "var test: integer" doch auch nur ein Zeiger, nämlich auf den Speicherbereich, in welchem sich die Informationen befinden. Dann wäre ja die Zeigervariable ein Zeiger auf eine Variable die selbst schon ein Zeiger ist.

Wozu braucht man das?

D.S.
 
  • Delphi -- Zeigervariablen??? Beitrag #2
C

cion

Bekanntes Mitglied
Dabei seit
13.07.2000
Beiträge
257
Reaktionspunkte
0
Ja Zeiger braucht man schon an einigen Stellen. Ein gutes Beispiel wären Listen oder Bäumen. Eine Liste zum Beispiel würde im Pseudocode ungefähr so aussehen:

type
pEintrag = ^TEintrag;
TEintrag = record
inhalt: integer;
next: pEintrag;
end;

liste = pEintrag;

Das mag vielleicht jetzt erstmal verwirrend aussehen aber damit kannst du ne Menge anfangen. Das Schlüsselelement ist dabei "next". Das zeigt nämlich wieder auf die eigene Struktur. Somit würde eine nicht festgelegte lange Liste entstehen, man kann das ganze immer mit Next ansprechen, zum Beispiel liste.next.next.next. Somit kann man immer wieder Einträge an die Liste hinzufügen, aber auch mal schnell löschen oder ändern...

cion
 
  • Delphi -- Zeigervariablen??? Beitrag #3
D

Deep Space

Bekanntes Mitglied
Dabei seit
01.08.1999
Beiträge
2.004
Reaktionspunkte
0
ist in der Tat ziemlich verwirrend.
so wie ich das verstehe, dann müsste ja dieser Code zu einer "Endlosliste" führen, da in dem Record wieder ein neues vorhanden ist, und in diesem wieder eins usw.

Abgesehen davon ist der Code doch unlogisch und dürfte so in Delphi garnicht funktionieren (ich hab es aber noch nicht ausprobiert), da in der Zeile unter "type" auf den Datentyp "TEintrag" zugegriffen wird, obwohl er zu dem Zeitpunkt noch nicht deklariert wurde, sondern erst in der Zeile darunter.

könntest du das nochmal näher erläutern, und vielleicht ein Beispiel geben?

D.S.
 
  • Delphi -- Zeigervariablen??? Beitrag #4
O

O Love

Bekanntes Mitglied
Dabei seit
08.04.1999
Beiträge
2.286
Reaktionspunkte
0
Nein, nein, das funktioniert schon. Warum, kann ich nur vermuten, aber es scheint eine implizite Forward-Deklaration zu sein. Sprich, der Compilter weiß, daß da noch was kommen wird.

Ansonsten ist obiges Beispiel nur die Deklaration, der Aufbau eines Listenelementes. Im Programm muß ich dann Speicher ausfassen und am Schluß wieder freigeben.

Man muß dazu etwas weiter ausholen. Wenn Du statisch ein Array deklarierst, reservierst Du einen festen Speicherbereich. Brauchst Du im Programm mehr Speicher, stehst Du auf dem Schlauch. Brauchst Du weniger, hast Du verschenkt, wenn das Array viel zu groß ist.

Jetzt kommen die Listen ins Spiel, hier arbeite ich dynamisch. Wenn ich ein neues Element brauche, fordere ich Speicher für genau ein Element vom Typ TEintrag (T wie Type) an. Damit dieses nicht sinnlos in der Gegend rumsteht, hänge ich das an die Liste dran. Ich habe also irgendwo einen Anfang der Liste und kann mich dann über den next-Zeiger durchhangeln.

Wenn es nur einen Zeiger in einer Richtung gibt, spreche ich von einer "einfach verketteten Liste", gibt es auch einen Zeiger in der Rückrichtung, heißt das "doppelt verkettete Liste". So komme ich nämlich auch rückwärts durch die Liste.

Will ich ein Element löschen, trenne ich die Liste wie eine Kette an einer Stelle auf, lösche das einzelne Element (Speicher freigeben) und hänge die Enden der Kette wieder zusammen. In einem Array müßte ich die nachfolgenden Elemente nach vorne schieben.

O Love

------------------
"I will not abide disobedience!"
 
  • Delphi -- Zeigervariablen??? Beitrag #5
O

O Love

Bekanntes Mitglied
Dabei seit
08.04.1999
Beiträge
2.286
Reaktionspunkte
0
So, nachdem mein Kopf etwas klarer ist :D , hier nun die Beispiele.

Typ-Deklaration einer doppelt verketteten Liste

Code:
type
  PElement	= ^TElement;
  TElement	= record
    Contents	: Integer;
    Prev	: PElement; // Zeiger auf Vorgänger
    Next	: PElement; // Zeiger auf Nachfolger
  end;

Hilfsvariablen

Code:
var
  FirstElement, LastElement : PElement;

Anlegen eines neuen Elementes

Code:
function CreateNewElement: PElement;
begin
  // Zuerst Speicher für ein Element ausfassen
  GetMem (Result, SizeOf (TElement));
  Result.Prev := nil;
  Result.Next := nil;
 
  // Haben wir schon andere Elemente?
  if (LastElement = nil) then begin
    // Nein, unser neues Element wird erstes und letztes zugleich
    FirstElement := Result;
    LastElement := Result;
  end else begin
    // Ja, unser Vorgänger wird das alte letzte Element
    Result.Prev := LastElement;
    // Der Nachfolger des alten letzten Elementes sind wir
    LastElement.Next := Result;
    // Und wir sind das neue letzte Element
    LastElement := Result;
  end;
end;

Löschen eines bestimmten Elements

Code:
procedure DeleteElement (CurElement: PElement);
begin
  // Wurde überhaupt ein Element übergeben?
  if (CurElement = nil) then
    Exit;
 
  // Spezialfall erstes Element
  if (CurElement = FirstElement) then begin
    // Das neue erste Element wird der Nachfolger des alten
    FirstElement := FirstElement.Next;
    // Kommen noch weitere Elemente?
    if (FirstElement <> nil) then
      // Ja, dann hat unser neues erstes Element keinen Vorgänger
      FirstElement.Prev := nil
    else begin
      // Nein, dann gibt es kein letztes Element mehr
      LastElement := nil;
      // Speicher freigeben
      FreeMem (CurElement);
      Exit;
    end;
  end;
 
  // Spezialfall letztes Element
  if (CurElement = LastElement) then begin
    // Das neue letzte Element wird der Vorgänger des alten
    LastElement := LastElement.Prev;
    // Gibt es noch weitere Elemente?
    if (LastElement <> nil) then begin
      // Ja, aber das neue letzte Element hat keinen Nachfolger
      LastElement.Next := nil;
      // Speicher freigeben
      FreeMem (CurElement);
      Exit;
    end;
  end;
 
  // Normaler Fall "in der Mitte"
  // Unser Vorgänger (CE.Prev) bekommt als Nachfolger unseren Nachfolger
  CurElement.Prev.Next := CurElement.Next;
  // Unser Nachfolger (CE.Next) bekommt als Vorgänger unseren Vorgänger
  CurElement.Next.Prev := CurElement.Prev;
  // Speicher freigeben
  FreeMem (CurElement);
end;

Fazit

Natürlich ist es zum Verständnis von Programmieren wichtig, daß man solche Sachen weiß, aber in Zeiten der objektorientieren Programmierung wird man bei dynamischen Listen unterstützt. Es gibt dann sogenannte Collections, die intern natürlich auf obige Weise programmiert sind. Nach außen präsentiert sich das aber einfacher: Man fügt nur noch Elemente in die Collection ein, manipuliert die Collection und löscht Elemente aus der Collection heraus. Damit wird es dem Programmierer leicht gemacht.

O Love

------------------
"I will not abide disobedience!"

[Dieser Beitrag wurde von O Love am 12. Oktober 2000 editiert.]
 
  • Delphi -- Zeigervariablen??? Beitrag #6
C

cion

Bekanntes Mitglied
Dabei seit
13.07.2000
Beiträge
257
Reaktionspunkte
0
Nochmal wegen der Variable die eigentlich noch gar nicht deklariert ist. Das geht schon und liegt an dem ^.
Das ist ja das Zeichen für einer Zeiger. In dem Fall zeigt das ganze auf die Deklaration, also das könnte man wie einen Link verstehen. Wenn der Compilier an die Stelle kommt und den Zeiger sieht dann springt er zu der Zeigeradresse und da steht dann die Deklaration (der Recordtyp).

cion

[Dieser Beitrag wurde von cion am 12. Oktober 2000 editiert.]
 
  • Delphi -- Zeigervariablen??? Beitrag #7
S

Svenche

Bekanntes Mitglied
Dabei seit
30.04.1999
Beiträge
471
Reaktionspunkte
0
Ort
Erfurt, Deutschland
Ähm, ist es dann was schlimmes, wenn man statt Zeigern einfach dynamische Arrays nutzt? Denn ich persönlich ziehe die vor.
 
  • Delphi -- Zeigervariablen??? Beitrag #8
O

O Love

Bekanntes Mitglied
Dabei seit
08.04.1999
Beiträge
2.286
Reaktionspunkte
0
1. In welcher Programmiersprache gibt es dynamische Arrays?

2. Welche Daten speicherst Du als Element? In der Liste kann sonstwas stehen. Da, wo oben ein simpler Integer als Inhalt eingetragen ist, kann wieder ein dynamisches Objekt stehen.

Stelle Dir folgende Situation vor: Du hast einen grafischen Editor. Dieser verwaltet seine Seiten in einer Liste. Und jede dieser Seiten hat wiederum Objekte, die auch in einer Liste gespeichert werden.

O Love

------------------
"I will not abide disobedience!"
 
  • Delphi -- Zeigervariablen??? Beitrag #9
C

cion

Bekanntes Mitglied
Dabei seit
13.07.2000
Beiträge
257
Reaktionspunkte
0
@O Love
In Delphi gibts dynamische Arrays

@Svenche
Also praktisch wäre das auch ok. Aber unpraktisch wirds wenn du z.B. ein Element aus deinem dynamischen Array entfernen willst. Da müßtest du alle folgenden Elemente um eins nach vorne wieder rücken, was bei rießen Daten (vielleicht ein Telefonbuch) viel zu lange Dauern würde. Mit einer Liste nimmst du das Element einfach raus und verbindest den Vorgänger über einen Zeiger mit dem Nachfolger (als würdest du eine Brücke herstellen).

cion
 
  • Delphi -- Zeigervariablen??? Beitrag #10
D

Deep Space

Bekanntes Mitglied
Dabei seit
01.08.1999
Beiträge
2.004
Reaktionspunkte
0
<BLOCKQUOTE><font size="1" face="Verdana, Arial">Zitat:</font><HR>Original erstellt von O Love:
1. In welcher Programmiersprache gibt es dynamische Arrays?
[/quote]

Also in Delphi lässt sich doch ein dynamisches Array folgender Maßen realisieren:

var DynArray: Array of Integer
...
SetLength(DynArray, 20)//array erhält 20 Elemente (Index 0..19)

DynArray := Copy(DynArray, 0, 10)//array enthält nur noch Elemente 0..9

D.S.
 
  • Delphi -- Zeigervariablen??? Beitrag #11
D

Deep Space

Bekanntes Mitglied
Dabei seit
01.08.1999
Beiträge
2.004
Reaktionspunkte
0
Vielen Dank!

Ich denke damit werde ich mich erstmal eine Weile auseinandersetzen müssen, um es vollständig zu verstehen :)

D.S.
 
  • Delphi -- Zeigervariablen??? Beitrag #12
S

Svenche

Bekanntes Mitglied
Dabei seit
30.04.1999
Beiträge
471
Reaktionspunkte
0
Ort
Erfurt, Deutschland
Na, ich mach mir das etwas einfacher. :) Wenn ich ein Element lösche, dann setze ich einfach das aktuell letzte an seine Position und geh da in der Länge um eines runter. So bewege ich genau ein Element. Und das ist zu verkraften. :) Selbst noch auf einem P90.
 
  • Delphi -- Zeigervariablen??? Beitrag #13
O

O Love

Bekanntes Mitglied
Dabei seit
08.04.1999
Beiträge
2.286
Reaktionspunkte
0
Ah ja, klar, mit SetLength kann man das machen. Habe ich nur nie auf diese Weise benutzt. Obwohl, wenn man es so sieht, ist ja ein String auch ein dynamisches Array. Danke für den Hinweis.

2 Svenche:

Natürlich kannst Du das letzte Element in die Lücke schreiben. Nur ist die Frage, ob Du das auch darfst. Wenn Du mein obiges Beispiel nimmst, dann kannst Du nicht einfach die letzte Seite im Editor nach vorne nehmen, wenn Du mittendrin was löschst.

O Love



------------------
"I will not abide disobedience!"
 
Thema:

Delphi -- Zeigervariablen???

ANGEBOTE & SPONSOREN

https://www.mofapower.de/

Statistik des Forums

Themen
213.181
Beiträge
1.579.177
Mitglieder
55.880
Neuestes Mitglied
Hahn
Oben