![ein Kapitel weiter](../weiter.gif)
In Perl sind die Referenzen nicht mit denen in der Sprache C gleichzusetzen. In Perl können Referenzen nur auf definierten Variablen verweisen und nicht in irgendeinem Adressraum. Ein simples Beispiel des Einsatzes von Referenzen.......
$var=5;
$referenz=\$var;
Zuerst definieren wir eine Variable $var und geben ihr den Wert 5. Anschließend
übergeben wir der Variablen $referenz die Adresse der Variablen $var. Die können sie Anhand des Adressoperators '\' (Backslash) erkennen. Somit ist $referenz die Referenz auf der Variablen $var. Im nächsten Programm demostiere ich Ihnen diese Aussage...........
#!/usr/bin/perl -w
$var=5;
$referenz=\$var;
print $referenz , "\n"; #Referenz von $var Ausgabe:Adresse $var
print \$var, "\n"; # Ausgabe: Adresse von $var
In diesem Beispiel wird 2x die selbe Adresse von der Variablen $var ausgegeben.
Wie schon in der Programmiersprache C z.B. setzt sich eine Variable immer aus dem Namen, den Wert und der Adresse im Speicher zusammen. Durch das Backslash in der zweiten print-Anweisung sorgen wir dafür das die Adresse von $var ausgegeben wird.
Die Ausgabe von $referenz stellt dagegen die Adresse da auf die sie verwiesen wurde.
In diesem Fall $var. Wenn sie die Adresse des Referenzen $referenz selber erfahren wollen müssen sie nur den Adressoperator '\' davor setzen.................
print \$referenz , "\n";
Genauso wie eben funktioniert dies auch bei Arrays und Hashs.........
#!/usr/bin/perl -w
$var=5;
@array= (3,5,3,90,2,4);
%hash = ("Name" => "Udo", "Vorname" => "Lindenberg");
$referenz=\$var;
print "Adresse von der Variablen var auf die referenz verweist : ";
print $referenz .":". \$var, "\n"; #Referenz von $var Ausgabe:Adresse $var
$referenz=\@array;
print "Adresse vom Array array auf die referenz verweist : ";
print $referenz .":". \@array, "\n"; #Referenz von @array Ausgabe:Adresse @array
$referenz=\%hash;
print "Adresse vom Hash hash auf die referenz verweist : ";
print $referenz .":". \%hash, "\n"; #Referenz von %hash Ausgabe:Adresse %hash
An diesem Beispiel können sie erkennen wir Referenzieren immer gleich.
Nun wollen wir uns doch mal ansehen wir auf den Wert zugreifen auf dessen Adresse
unser Referenz verwiesen wurde.........
#!/usr/bin/perl -w
$var=5;
$referenz=\$var;
print "Die Adresse von referenz selber : " . \$referenz . "\n";
print "Die Adresse auf die referenz verweist : " . $referenz . "\n";
print "Der Wert der Adresse auf die referenz verweist : " . ${$referenz} . "\n\n";
print "Die Adresse von var : " . \$var . "\n";
print "Der Wert von var : " . $var . "\n";
In diesem Beispiel haben sie also gesehen wie sie auf den Wert von Referenzen zugreifen
können auf diese sie verweisen. Der Zugriff auf den Wert des Referenzen erfolgt also
einfach zwischen geschweifte Klammern. Man spricht beim Zugriff auf eine Referenz von
der Dereferenzierung. Nun sehen wir uns mal an was wir hier Derefenzieren
können..........
#!/usr/bin/perl -w
$var=5;
$referenz=\$var;
print "Der Wert auf den referenz verweist : " . ${$referenz} . "\n";
print "Der Wert von var : " . $var . "\n\n";
${$referenz}*=2; #Dereferenzierung
print "Der Wert auf den referenz verweist : " . ${$referenz} . "\n";
print "Der Wert von var : " . $var . "\n";
Hier Derefernzieren wir den Wert auf den $referenz zeigt. Was logischerweise auch
nach sich zieht das der Wert von $var sich ebenfalls verändert da ja $var
und ${$referenz} das selbe Objekt beinhalten.
Das ganze nun mit einem Array und einem Hash...........
#!/usr/bin/perl -w
@array = (33,66,99);
%hash = ("Name" => "Becker", "Vorname" => "Boris");
$ref1=\@array; #ref1 verweist array
$ref2=\%hash; #ref2 verweist hash
print "@{$ref1}" , "\n";
print %{$ref2} , "\n";
Wenn sie nun z.B in einem Array auf ein einzelnes Element zugreifen wollen so benötigen
sie nur den Index a la...........
@{$ref1}[1]
Somit würden sie im oberen Beispiel auf den Wert 99 zugreifen. Um bei einem Hash auf ein spezielles Element zuzugreifen gehen wir ähnlich vor und benutzen statt des Indexes
einfach den Schlüssel.........
%{$ref2}{'Name'}
In diesem Fall würden wir auf den Nachnamen Becker zugreifen. Nun zugegeben diese
beiden Schreibweisen....
@{$ref1}[1]
%{$ref2}{'Nachname'}
...sehen nicht gerade sehr Lese.-und Schreibfreundlich aus. Daher haben die Perl-Entwickler auch dafür gesorgt diese Schreibweise zu vereinfachen. Und aus.........
@{$ref1} .....wird......... @$ref1
@{$ref1}[1] ......wird......... $ref->[1]
%{$ref2} ......wird........ %$ref2
%{$ref2}{'Nachname'} ......wird....... $ref2->{'Nachname'}
Das ließt sich doch schon viel besser, oder? Das ganze wollen wir anhand unseres Programms anschauen...........
#!/usr/bin/perl -w
@array = (33,66,99);
%hash = ("Name" => "Becker", "Vorname" => "Boris");
$ref1=\@array; #ref1 verweist array
$ref2=\%hash; #ref2 verweist hash
print "@$ref1" , "\n";
print %$ref2 , "\n";
print $ref1->[2];#99
print $ref2->{'Name'};#Becker
Mit Referenzen haben wir also die Möglichkeiten komplexere Datenstrukturen zu
erstellen.......
Array von Arrays
Nehmen wir mal an wir haben mehrere Arrays mit Werten und wollen diese an einer Funktion übergeben............
@array1 = (22,55,11);
@array2 = (4,7,1);
@array3 = (99,2,7);
Nun hätten wir die Möglichkeit alle drei Arrays an die Funktion mittels.....
func(\@array1, \@array2, \@array3);
....übergeben. Es geht aber auch einfacher. Wir machen einfach daraus ein Array aus
Arrays........
@array1 = (22,55,11);
@array2 = (4,7,1);
@array3 = (99,2,7);
@allarray = (\@array1, \@array2, \@array3);
Hier nun das Beispiel..........
#!/usr/bin/perl -w
@array1 = (22,55,11);
@array2 = (4,7,1);
@array3 = (99,2,7);
@allarray = (\@array1, \@array2, \@array3);
gib_aus(\@allarray);
gib_aus
{
my $array_ref = $_[0];
foreach $elem (@$array_ref)#Anfangsadresse der einzelnen Array in $elem
{
#printf "x="; #Zur Kontrolle wird 3x ausgegen da 3 Arrays
foreach $wert (@$elem)
#Durchläuft die einzelnen Arrays jeweils 3x da 3 Werte pro Array
{
print $wert , "\t";
}
}
print "\n";
Nun zur Erklärung. In der Hauptfunktion übergeben wir mittels Referenzen die einzelnen
Arrays an ein Array. Anschließend geben wir an die Funktion gib_aus die
Anfangsadresse unserem Array in dem wir die Anfangsadressen der einzelnen Arrays
übergeben haben. Um nun da Referenzen ja auch einfache skalare sind übergeben wir in der Funktion gib_aus den Parameter $_[0] an my $array_ref.
Was nun kommt werden wir auch so bei den nächsten Beispielen verwenden. Die erste
foreach-Schleife durchläuft die einzelnen Arrays im Array. Beim ersten Durchlauf als
@array1. Somit steht jetzt in $elem die Anfangsadresse vom @array1. In der zweiten foreach-Schleife durchlaufen wir jetzt die einzelnen Werte von @array1 (22,55,11).
Anschließend ist die innere foreach-Schleife wieder fertig. Nun war die Äußere ja noch nicht fertig. Diese erhöht Ihren "Index" sozusagen auch um eins und dort haben wir nun @array2. Den weiteren Verlauf kennen wir ja nun.
Was sich hier so komplex anhört ist gar nicht so schlimm. Denn wenn wir eine Array von
Arrays durchlaufen wollen müssen wir ja zwei foreach-Schleifen verwenden damit wir
in das Innere Array kommen. Das ja wie folgt aussieht......
@allarray = ( [22,55,11] , [4,7,1], [99,2,7]);
Diese Möglichkeit von Referenzen auf Listen können wir übrigens auch verwenden.
Array von Hashes
Array von Hashes funktionieren im Übrigen genauso wie die eben schon erklärten Array
von Arrays. Daher will ich nicht genauer darauf eingehen sondern nur ein Programmbeispiel hinstellen..........
#!/usr/bin/perl -w
%hash1 = ("Marke" => "BMW",
"Baujahr" => 2000,
%hash2 = ("Marke" => "Opel",
"Baujahr" => 1999,
%hash3 = ("Marke" => "Audi",
"Baujahr" => 2001);
@array_hash = (\%hash1, \%hash2, \%hash3);
gib_aus(\@array_hash);
sub gib_aus
{
my $array_ref = $_[0];
foreach $elem (@$array_ref)
#Anfangsadresse der einzelnen Array in $elem
{
#printf "x="; #Zur Kontrolle wird 3x ausgegen da 3 Hash im Array
foreach $key (keys %$elem) #Gibt den Inhalt des Hash aus
{
print "$key : " , "$elem->{$key}" #$key=Marke und Baujahr
}
}
print "\n";
}
Hier also im Prinzip der selbe Vorgang wie schon bei Array von Arrays.
Was schon etwas Interessanter sein dürfte sind wohl Hashes mit Listen.........
%hash = ("Marke" => "BMW",
"PS" => [105, 120, 180]);
Um in einem einem solchen Fall auf die einzelnen Elemente der Liste im Hash zuzugreifen ist
folgende Schreibweise nötig.......
@$hash{$key};
Wollen wir das mal wieder in der Praxis anschauen........
#!/usr/bin/perl -w
%hash1 = ("Marke" => "BMW",
"PS" => [105, 120, 180]);
foreach $key (keys %hash1)
{
print "$key : ";
if(ref($hash1{$key})) #Referenz?
{
foreach $elem (@{$hash1{$key}})
{
print "$elem " ;
}
}
else
{
print "$hash1{$key} ";
}
print "\n";
}
Das meiste in diesem Programm dürfte Ihnen ja schon bekannt sein. Mit dem Schlüsselwort
ref überprüfen wir ob der Wert des Schlüssels eine Referenz ist. Wenn ja
durchlaufen wir die einzelnen Werte dieser Liste mit...
foreach $elem (@{$hash1{$key}})
Was sich hier als ziemlich kryptisch liest ist gar nicht so schlimm. In unserem Beispiel
lesen wir den ersten Wert des Arrays in $key ("PS") aus dem Hash
hash1 aus und übergeben diesen Wert der Variablen $elem um diesen gleich darauf auszugeben. Dann lesen wir den zweiten Wert des Arrays im Hash mit dem Schlüssel (PS) aus u.s.w.
Und als letztes hätten wir noch die Möglichkeit eines Hash von Hashes.
Dazu will ich jetzt aber nicht eingehen. Dies soll in einem späteren Kapitel behandelt
werden.
Nur ein Snippet wie man sich dies Vorstellen kann........
%hash1 = ("Marke" = "BMW",
"Baujahr" => 2000);
%hash2 = ("Marke" => "Audi",
"Baujahr" => 1999);
%hash_hash = ("h_key1" => \%hash1, "h_key2" => \%hash2);
Wie gesagt wir kommen später darauf zurück und gehen genauer darauf ein.
Nochmals kurz zusammengefasst, da diese ein Umfangreicheres Kapitel ist........
Folgende Bedeutung für folgende Dereferenzierungen............
- $$referenz = Skalar
- ${$referenz}[1] und $referenz->[1]= einzelnes Array-Element
- @$referenz und @{$referenz} = gesamtes Array
- %$hash und %{$hash} = gesamtes Hash
- ${$hash}{'key'} und $hash->{'key'}= einzelne Hash-Elemente
Referenz auf Subroutinen
Natürlich ist es auch möglich eine Referenz auf Subroutinen
festzulegen. Es muss dabei aber darauf geachtet werden
das hierzu das Präfix & nach dem Backslash erfolgt......
sub funkion{..}
$funcref = \&funktion;
Hiermit speichern wir die Adresse der Funktion funktion in $funcref.
Sie werden diese Methode noch öfters in sogenannte Dispatcher sehen.
Im Kapitel GUI's mit Perl und Tk zum Beispiel............
$m_file->command(-label => "Speichern",
-command => [\&save, "speichern"] );
Hier haben wir zum Beispiel Menü-Buttons. Dieser ist Beschriftet mit
"Speichern". Wenn sie diesen Button mit der linken Maustaste betätigen,
wird die Adresse der Subroutine \&save ausgeführt, was in unserem Fall
das Abspeichern von Daten bedeutet.
Referenz auf Filehandles
Es ist auch Möglich Referenzen auf Filehandles zu verwenden. Hier
#ist zu beachten, dass sie das Präfix * nach dem Backslash stehen
#haben. Wir wollen das ganze anhand eines einfachen Beispiels demonstrieren....
#!/usr/bin/perl -w
sub input{
my($stdin, $stdout, $prompt) = ($_[0],$_[1],$_[2]);
print $stdout, $prompt;
return scalar <$stdin>;
}
$scalar = input(\*STDIN, \*STDOUT, "Eingabe : ");
print "Sie gaben ein : $scalar\n";
Hier geben wir als Funktionsparameter die Standard-Filhandles STDIN und
STDOUT an die Funktion input. Als Rückgabewert bekommen wir den Skalaren
Wert von der Variable $stdin.
Rückgabe von lokale Referenzen aus Subroutinen
Was in C nicht möglich ist, funktioniert in Perl tadellos. Nur wozu
soll das gut sein?
Mit dieser Methode können sie Variablen Temporär Zwischenspeichern.
Beispiel............
#!/usr/bin/perl -w
sub input{
my @refarray;
my $scalar;
print "Bitte Eingabe machen : ";
chomp($scalar = <>);
@refarray=split(" ", $scalar);
return \@refarray;
}
$ref1=input;
$ref2=input;
print "@{$ref1}" , "\n"; #Überrascht?!
print "@{$ref2}" , "\n";
C-Programmierer dürften bei diesem Programm überrascht sein, das
hier keine Fehlermeldung ausgegeben wurde. Wir haben eine lokale
Variable einer Funktion an unsere Hauptfunktion zurückgegeben.
Dies ist in C unmöglich. Wir haben praktisch mit jedem Aufruf.....
$ref=input
...den Inhalt unserer Liste refarray in der Skalaren Variable $ref
gesichert. Mit diesen beiden Referenzen kann anschließend normal
weitergerabeitet werden.
Refernztyp idenfizieren mit ref
Wir haben die Funktion ref bereits Verwendet. Nun noch eine Erklärung dazu.
Mit der Funktion ref können sie überprüfen was für ein Referenztyp gerade
verwendet wird. Folgende Rückgabewerte sind dabei möglich........
SCALAR,ARRAY,HASH,REF,CODE,GLOB,LVALUE
Überprüfen können sie dies Idealerweise folgendermaßen...
foreach(@liste){
if(ref($_) eq 'SCALAR'){ #Scalar
}
elsif(ref($_) eq 'ARRAY'){ #Array
}
.........
.........
![ein Kapitel weiter](../weiter.gif)
© 2001,2002 Jürgen Wolf
|