Programmierkurs: Delphi: Pascal: Sets

Sets Bearbeiten

Bei einem Set handelt es sich um einen Datentyp, der eine Menge von Werten eines Basistyps speichert. Ein Set speichert dabei zu jedem möglichen Wert des Basistyps, ob dieser enthalten ist. Der Basistyp muss ein Typ sein, der höchstens 256 verschiedene Werte annehmen kann, also etwa Byte, Char oder ein selbst definierter Aufzählungstyp. Möglich sind natürlich auch Teilbereichstypen dieser Typen. Ein Set benötigt für jeden möglichen Wert des Basistyps ein Bit, hat also eine Größe von (Zahl der möglichen Werte des Basistyp / 8) Byte, maximal also 32 Byte.

Mengen sind z.B. nützlich, um Programmeinstellungen oder auch bestimmte kumulative Eigenschaften von Objekten zu speichern. Anders als beim Array spielt die Reihenfolge der Elemente keine Rolle, und jedes Element kann auch nur einmal enthalten sein.

Ein Mengentyp wird durch die Angabe von set of deklariert:

type
  Typbezeichner = set of <Aufzählungstyp>;


Um einer Mengenvariablen Werte zuzuweisen, setzt man diese in eckige Klammern [] und trennt die einzelnen Werte mit einem Komma. Für eine leere Menge geben Sie nur die eckigen Klammern an. Mit dem Operator in fragt man ab, ob ein Element in einer Menge enthalten ist.

Zur Verdeutlichung ein Beispiel zur Ziehung der Lottozahlen:

type
  TLottozahlen = 1..49;

var
  Lottozahlen: set of TLottozahlen = [];  // leere Menge
  i: Byte;
  z: TLottozahlen;

begin
  { Zufallszahlen initialisieren }
  Randomize;
 
  { Ziehung 1 bis 6 }
  for i := 1 to 6 do
  begin
    { Eine Zufallszahl ziehen und prüfen, ob diese bereits vorhanden ist }
    repeat
      z := Random(49) + 1;
    until not (z in Lottozahlen);
    { Zahl der Ziehung hinzufügen }
    Lottozahlen := Lottozahlen + [z];
  end;

  { alle Lottozahlen sortiert ausgeben }
  for z in Lottozahlen do
    Writeln(z);
end.


Die Gesamtmenge aller gültigen Lottozahlen reicht von 1 bis 49. Hierzu deklarieren wir uns einen entsprechenden Typ. Da wir aus dieser Gesamtmenge 6 Zahlen zufällig auswählen, benötigen wir noch eine Zählschleife, die den Vorgang nach der 6. Ziehung beendet. Da wir ja keine echten Kugeln herausnehmen können, kann es passieren, dass eine Zahl mehrfach gezogen wird. Um dies zu vermeiden, prüfen wir, ob die Zahl eventuell bereits vorhanden ist und ziehen in diesem Fall eine neue. Eine Menge speichert zwar (im Gegensatz zu einem Array) jeden Wert nur einmal, allerdings würde die for...to Schleife beendet werden, bevor 6 unterschiedliche Zahlen gezogen wurden.
Anschließend fügen wir die gezogene Zahl unserer Teilmenge hinzu. Da wir auch wissen wollen, ob wir richtig getippt haben, geben wir dann alle Lottozahlen auf dem Bildschirm aus. Da es sich bei den Lottozahlen um einen Aufzählungstyp handelt, sind diese automatisch von der kleinsten zur größten sortiert. Die Zusatzzahl dürften wir nicht in unsere Menge aufnehmen, sondern müssten diese gesondert speichern, da aus einer sortierten Liste nicht mehr die zuletzt gezogene Zahl zu erkennen wäre.

Für die Ziehung wäre auch der folgende Code möglich. Dieser zählt eine Zahl nur dann als gezogen, wenn es sich dabei um eine neue handelt:

i := 0;
repeat
  z := Random(49) + 1;
  if not (z in Lottozahlen) then
  begin
    Inc(i);
    Lottozahlen := Lottozahlen + [z];
  end;
until i = 6;


Mehr über die Verwendung von Schleifen erfahren Sie später.

Genauso, wie Sie über den Plus-Operator + Elemente in eine Menge aufnehmen können, entfernt der Minus-Operator - diese. Dabei können Sie jeweils auch mehrere Elemente gleichzeitig angeben. Normalerweise sollte man jedoch statt des Plus- und des Minusoperators die Funktionen include und exclude verwenden, weil diese effizienteren Code erzeugen. Mehrere direkt aufeinanderfolgende Elemente können mit dem Aufzählungszeichen .. angegeben werden:

Lottozahlen := [2, 3, 5];
Lottozahlen := Lottozahlen + [7, 11, 13];  // ergibt [2, 3, 5, 7, 11, 13]
Lottozahlen := Lottozahlen - [3, 7];       // ergibt [2, 5, 11, 13]
Lottozahlen := [1..4, 8, 16];              // ergibt [1, 2, 3, 4, 8, 16]


Mehrfaches Entfernen desselben Elementes ist dabei genauso ohne Fehlermeldung möglich wie mehrfaches Hinzufügen.

Verwechseln Sie Sets bitte nicht mit Arrays. Beide benutzen die eckigen Klammern, jedoch zu einem anderen Zweck. Man kann zum Beispiel bei einem Set nicht das dritte Element erfragen, indem man folgenden Code zu kompilieren versucht:

 z := Lottozahlen[3];


  Pascal: Aufzählungen Inhaltsverzeichnis Pascal: Arrays