Perl-Programmierung: Operatoren

Aus Wikibooks


Vorbemerkung[Bearbeiten]

Perl verwendet Operatoren, welche denen von C oder ähnlichen Sprachen stark gleichen. Der '='-Operator wurde ja bereits erwähnt. Er nimmt in Perl eine Sonderstellung ein, da es der einzige Operator ist, der für selbst definierte Objekte nicht umdefiniert werden kann.

Ein wichtiger Aspekt im Zusammenhang mit Operatoren ist ihre Assoziativität. Das heißt ob der Operator sich auf ein Sprachelement links oder rechts von ihm bezieht.

Außerdem ist es wichtig zu wissen, dass für die Operatoren eine bestimmte Reihenfolge festgelegt ist, die darüber entscheidet, wie ein aus mehren Operatoren zusammengesetzter Ausdruck ausgewertet wird.

Das Umdefinieren eines Operators, das später beschrieben wird, kann nur seine Funktionsweise ändern; die Assoziativität und Auswertungsreihenfolge sind nicht änderbar.

Zuweisende und verknüpfende Operatoren[Bearbeiten]

Mathematische Operatoren[Bearbeiten]

Zuerst die Operatoren die wahrscheinlich am meisten gebraucht werden, die mathematischen.

Grundrechenarten[Bearbeiten]

Am häufigsten werden wohl die meisten Programmierer die 4 Grundrechenarten gebrauchen.

$a = 4 + 2;   # Addiere 4 und 2.
$b = 4 - 9;   # Subtrahiere 9 von 4.
$c = 5 * 11;  # Multipliziere 11 mit 5.
$d = 12 / 4;  # Dividiere 12 durch 4. $d enthält nun also 3.

Es fehlt uns also an nichts, alle anderen mathematischen Funktionen könnten wir nun herleiten, aber Perl bietet noch mehr.

Für jede Grundrechenart gibt es nach dem Vorbild von C/C++ auch einen Zuweisungsoperator:

#!/usr/bin/perl

use strict;
use warnings;

my $a = 1;    # Deklaration und Initialisierung
$a += 9;      # Addiere 9 zu $a.
$a -= 6;      # Ziehe 6 von $a ab
$a *= 3;      # Multipliziere $a mit 3
$a /= 2;      # Teile $a durch 2
print "$a\n";
Andere Rechenarten[Bearbeiten]

Perl stellt auch höhere mathematische Operatoren zur Verfügung.

# Potenzieren
my $a = 2 ** 10;      # 2 Hoch 10, sprich 2*2*2*2*2*2*2*2*2*2 = 1024.

# Ermittlung von Ganzzahldivisions-Resten
my $b = 13 % 7;       # 13 Modulo 7 = 6.

# Quadratwurzel
my $c = 49 ** 0.5;    # 7 * 7 = 49
my $d = sqrt(36);     # 6 * 6 = 36

# dritte Wurzel
my $e = 27 ** (1/3);  # 3 * 3 * 3 = 27

Der Operator '**' dient zum Potenzieren; er sollte nicht mit dem bitweisen Operator '^' verwechselt werden, der in einigen Programmiersprachen zum Potenzieren dient.

Wurzelziehen muß im allgemeinen als Potenzieren mit dem Kehrwert des Wurzelexponenten betrachtet werden. Für die Quadratwurzel steht aber zusätzlich die Funktion sqrt($parameter) zur Verfügung.

Für die Ganzzahldivision steht weder ein Operator, noch eine Funktion zur Verfügung, aber mit Hilfe des Modulo-Operators % (s.o.) läßt sich eine entsprechende eigene Funktion leicht erstellen.

#!/usr/bin/perl

use strict;
use warnings;

print div(13, 7) ."\n";

sub div {
  return ($_[0] - $_[0] % $_[1]) / $_[1] ;
}

Zuerst wird mit dem Modulo Operator der Rest der Division der beiden Argumente ermittelt.

Hinweis: Da das Erstellen von eigenen Funktionen noch nicht erläutert wurde, hier kurz und knapp einige Hinweise:

  • sub ist das Schlüsselwort zur Erstellung einer eigenen Funktion.
  • return erzeugt den Ausgabewert einer Funktion.
  • $_[0] und $_[1] sind die Handler für den 1. und den 2. Funktionsparameter. Perl fängt aber bei 0 an zu zählen.


Eine allgemeine Funktion für den Logarithmus zu einer beliebigen Basis steht nicht zur Verfügung. Aber die Funktion log kann den natürlichen Logarithmus berechnen. Die Mathematiker unter den Lesern wissen natürlich, daß dessen Basis die Eulersche Zahl e ist, außerdem, daß man damit auf einfache Weise eine Funktion zur Ermittlung der Logarithmen anderer Basen erstellen kann.

#!/usr/bin/perl

use warnings;
use strict;

print logarithmus(1000, 10) . "\n";

sub logarithmus {
  return log($_[0])/log($_[1]);
}
Inkrementieren und Dekrementieren[Bearbeiten]

Zum simplen Erhöhen oder Verringern einer Variable scheint eine normale Zuweisung oft zu lang oder (in Sonderfällen) zu unübersichtlich.

$a = $a + 1;
$b = $b - 1;

Zur Verkürzung gibt es, ähnlich in C, die Operatoren ++ und -- um diese Statements zu verkürzen.

$a++;         # Rückgabe von $a, dann Inkrementieren von $a.
++$a;         # Inkrementieren von $a, dann Rückgabe von $a.
 
$b--;         # Rückgabe von $b, dann Dekrementieren von $b.
--$b;         # Dekrementieren von $b, dann Rückgabe von $b.

Zu beachten ist hier unbedingt die Position des '++'- bzw. '--'–Operators. So hat zum Beispiel das folgendes Statement nicht die Wirkung auf $b die der Ungeübte auf den ersten Blick vermutet.

$a = 9;
$b = $a++;

In diesem Beispiel besitzt die Variable $b am Ende den Wert 9, da $a zuerst zurückgegeben und dann erhöht wurde. Die gewünschte Wirkung lässt sich mit dieser Konstruktion erreichen.

$a = 9;
$b = ++$a;

Nun wird $a zuerst erhöht und dann an $b zurückgegeben. Nun hat $b den Wert 10.

Stringverknüpfungs–Operatoren[Bearbeiten]

Des Weiteren gibt es spezielle Operatoren um Strings zusammenzufügen, welche von der Programmiersprache PHP übernommen wurden. Durch die Typenlosigkeit Perls ist es notwendig mitzuteilen, ob man zwei Variablen, die möglicherweise Ziffern beinhalten, wie Zahlen oder wie Zeichenketten behandeln soll.

$b = 'Wiki';
$c = 'books';
$d = 42;
$a = $b . $c . $d;   # Verkette $b, $c und $d.
print $a;            # Gibt "Wikibooks42" aus.
print "$b$c$d";      # gibt ebenfalls "Wikibooks42" aus

Der Wiederholungsoperator ( "x" ) vervielfältigt den linken String um den angegebenen rechten Wert.

$b = 'o';
$b = $b x 10;               # Füge $b zehnmal zusammen.
print 'Wikib' . $b . 'ks';  # Gibt "Wikibooooooooooks" aus.

Bitweise Operatoren[Bearbeiten]

Als nächstes die Operatoren, mit denen wir Zahlen bitweise vergleichen können.

Bitweises AND[Bearbeiten]

Der Operator "&" für das bitweise AND vergleicht jeweils 2 Bits miteinander; nur wenn beide 1 sind, ist das Ergebnis auch 1. Am besten demonstrieren wir das ganze einmal an einem Beispielprogramm:

#!/usr/bin/perl
# bitweisesAND.pl
# Demonstration bitweises AND.
  
my ($foo, $bar, $baz);
 
$foo = 1; # In Bits: 0000 0001
$bar = 3; # In Bits: 0000 0011
 
$baz = $foo & $bar; 
# Der bitweise And-Operator.
# Wir vergleichen jedes Bit:
# 0000 0001
# 0000 0011
#----------
# 0000 0001
 
print '$foo: '.$foo."\n";
print '$bar: '.$bar."\n";
print '$baz: '.$baz."\n";

Und die Ausgabe:

$foo: 1
$bar: 3
$baz: 1
Bitweises OR[Bearbeiten]

Der OR–Operator '|' dient wie auch & dem bitweisem Vergleich zweier Zahlen. Wie der Name schon vermuten lässt wird das Ergebnisbit nur auf 1 gesetzt wenn wenigstens eines der beiden Bits 1 ist.

Hier das Beispielprogramm:

#!/usr/bin/perl -w
# bitweisesOR.pl
# Demonstration bitweises OR.
 
my ( $foo, $bar, $baz );
 
$foo = 5;  # In Bits: 0000 0101
$bar = 15; # In Bits: 0000 1111
 
$baz = $foo | $bar; 
# Der bitweise Or-Operator.
# Wir vergleichen jedes Bit:
# 0000 0101
# 0000 1111
#----------
# 0000 1111
 
print '$foo: '.$foo."\n";
print '$bar: '.$bar."\n";
print '$baz: '.$baz."\n";

Und hier wiedermal die Ausgabe:

$foo: 5
$bar: 15
$baz: 15
Bitweises XOR[Bearbeiten]

Der XOR–Operator ^ dient wie seine Geschwister dem bitweisem Vergleichen von Zahlen; er verhält sich ähnlich dem OR–Operator, jedoch wird beim Ergebnis ein Bit nur auf 1 gesetzt, wenn genau eines der beiden Bits 1 ist. Das nennt man exklusives Oder.

Und hier wieder mal das Beispielprogramm:

#!/usr/bin/perl -w
# bitweisesXOR.pl
# Demonstration bitweises XOR.
 
my ( $foo, $bar, $baz );
 
$foo = 3;  # In Bits: 0000 0011
$bar = 61; # In Bits: 0011 1101
 
$baz = $foo ^ $bar; 
# Der bitweise XOR-Operator.
# Wir vergleichen jedes Bit:
# 0000 0011
# 0011 1101
#----------
# 0011 1110
 
print '$foo: '.$foo."\n";
print '$bar: '.$bar."\n";
print '$baz: '.$baz."\n";

Und die Ausgabe des XOR-Programmes:

$foo: 3
$bar: 61
$baz: 62
praktische Anwendung[Bearbeiten]

Nun wollen wir das ganze doch einmal an einem praktischen Anwendungsbeispiel demonstrieren. Wir tauschen zwei Variablen aus:

#!/usr/bin/perl -w
# PraktischeOperatoren.pl
# Praktische Anwendung eines bitweisen XOR.
 
my ( $foo, $bar );
 
$foo = 3; # Bitweise: 0000 0011
$bar = 4; # Bitweise: 0000 0100
 
$foo = $foo ^ $bar;
     # $foo: 0000 0111
 
$bar = $foo ^ $bar;
     # $bar: 0000 0011
 
$foo = $foo ^ $bar;
     # $foo: 0000 0100
 
print '$foo: '.$foo."\n";
print '$bar: '.$bar."\n";

Und nun die Ausgabe:

$foo: 4
$bar: 3

Wie man sieht, haben wir die beiden Variablen ohne den Einsatz einer Hilfsvariable ausgetauscht. Diese Technik ist sehr elegant, birgt aber auch Risiken, so zum Beispiel bei negativen Zahlen, bzw Zahlen nahe am Ganzzahlvariablenmaximum.

Logische Operatoren[Bearbeiten]

Logische Operatoren dienen dazu, Aussagen miteinander zu vergleichen. Soll zum Beispiel überprüft werden, ob eine Zahl $a im Bereich von 2 bis 5 liegt, so muss man zwei Vergleiche durchführen: ist $a größer oder gleich 2, und ist es kleiner oder gleich 5?

Binäre Operatoren[Bearbeiten]

Das oben genannte Beispiel schreibt sich in Perl so:

 if (2 <= $a and $a <= 5) { ... }

der and-Operator (den man auch als '&&' schreiben kann), liefert nur dann ein wahres Ergebnis zurück, wenn beide verknüpfte Ausdrücke wahr sind.

Analog dazu gibt es den or–Operator (der auch als '||' geschrieben werden kann), der ein wahres Ergebnis zurückgibt, wenn mindestens einer Operanden, also der Ausdrücke links und rechts des Operators, wahr ist.

Beispiel:

 if ($a >= 2 or $a <= -2) { ... }

wird dann wahr, wenn $a größer gleich 2 ist oder kleiner gleich -2.

Obwohl man die Operatoren and und or in den meisten Fällen mit && und || ersetzen kann, muss man beachten, dass and und or einen wesentlich niedrigeren Vorrang haben. Dazu ein Beispiel:

$a = 0;
$b = 2;
$c = 0;
$abc = $a || $b || $c;  # $abc bekommt den Wert 2 zugewiesen.

ersetzt man in diesem Beispiel die || durch ein or passiert jedoch folgendes:

$a = 0;
$b = 2;
$c = 0;
$abc = $a or $b or $c;  # $abc wird 0 zugewiesen, weil der Zuweisungsoperator höheren Vorrang hat.
                        # Ist die Zuweisung fehlgeschlagen, wird die or-Operation durchgeführt.

Der Ternäre Operator[Bearbeiten]

Oft muss man zwischen zwei Alternativen unterscheiden. Dabei kann der ternäre Operator ? helfen.

#!/usr/bin/perl
use strict;
use warnings;

my $tor_status = 1;
print 'Das Tor ist ', $tor_status ? 'offen' : 'geschlossen', ".\n";

Stringvergleichende Operatoren[Bearbeiten]

Aufgrund der Typenlosigkeit von Perl ist es nicht möglich bei einem Vergleich genau zu sagen was verglichen werden soll. Ein Beispiel: In $a enthält die Zeichenkette '1abc' und $b enthält den Integer 5. Bei dem Vergleich

  if ( $a == $b )

Würde $a (die Zeichenkette) zum Vergleich nach Integer gecastet (konvertiert) werden. Das hat keine direkten Auswirkungen auf $a, aber während des Vergleiches wird $a von 1abc zu 1. Das kann zu unerwünschten Nebenwirkungen führen. Um dieses Problem zu beheben gibt es einige Operatoren zum Vergleich von Zeichenketten. Diese sind:

  • eq ( equal / gleich)
  • ne ( not equal / ungleich )
  • cmp ( compare / vergleiche )
  • lt ( lower than / kleiner als )
  • le ( lower than or equal / kleiner oder gleich )
  • ge ( greater than or equal / größer oder gleich )
  • gt ( greater than / größer als )

Diese Operatoren sollen hier kurz erläutert werden.

  • Der eq–Vergleich zweier Zeichenketten ergibt wahr wenn die beiden Zeichenketten exakt gleich sind.
  • Der ne–Vergleich zweier Zeichenketten ergibt wahr wenn die beiden Zeichenketten nicht gleich sind.

Diese beiden Operatoren sind vergleichbar mit == und !=.

Beispiele:

  'asdf' eq 'asd'      # ergibt falsch
  'asdf' eq 'asdf'     # ergibt wahr
  'asdf' lt 'asdg'     # ergibt wahr
  'asdf' gt 'asdg'     # ergibt falsch

Spezielle Operatoren[Bearbeiten]

Kombinierte Operatoren[Bearbeiten]

Perl erkennt die von C geläufigen Zuweisungsoperatoren und besitzt noch einige mehr. Folgende Zuweisungsoperatoren gibt es:

=    *=   &&=  |=   .=   x=
**=  &=   -=   >>=  %=
+=   <<=  /=   ||=  ^=

Beispiele:

$a += 2;    # $a wird um 2 vergrössert.
$a -= $b;   # $a wird um $b verkleinert
$a .= $b;   # $a und $b werden in $a zusammengefügt(verkettet).
$a &= $b;   # siehe bitweise Operatoren
$a |= $b;   #
$a ^= 2;    #

Der Bereichsoperator[Bearbeiten]

Der Bereichsoperator erstellt eine Liste mit Werten im Bereich zwischen dem linken Operanden und dem rechten Operanden. Wobei sowohl .. als auch ... verwendet werden können (diese sind gleichwertig). Er verhält sich ziemlich intelligent und ist durchaus in der Lage Listen, welche aus Buchstaben bestehen, zu erstellen. Die Listen können zum Beispiel in Schleifen durchlaufen werden, aber auch mit simplen Befehlen.

#!/usr/bin/perl
use strict;
use warnings;
print (10 .. 21);
print "\n"; # Zeilenumbruch ausgeben.
 
# Das ganze geht genausogut mit Schleifen.
for ( 'A' .. 'F' ) { print }

Programmausgabe:

101112131415161718192021
ABCDEF

Der defined-or Operator[Bearbeiten]

Neu in Perl 5.10 ist der defined-or operator // bzw. //=. Er überprüft nicht den Wahrheitsgehalt seines Argumentes, sondern die Definiertheit.