Sehr Umfangreiche Webseite zum Programmieren in C Perl CGI, Skripting, Konvertieren, int ceil sprintf hex oct floor Runden AbschneidenPerl Kurs Skripting Funktionen Unterprogramme Subroutinen Parameter Argumente eval wantarray Memoizing Funktionen Unterprogramme Subroutinen Parameter Argumente eval wantarray Memoizing Perl Kurs Kapitel 10

10.1. Unterprogramme (Funktionen)           zurück Ein Kapitel tiefer zum Inhaltsverzeichnis

Was sind Unterprogramme und wozu benötigen Sie diese? Unterprogramme sind wie schon in vielen anderen Programmiersprachen, nichts anderes als ein mit Namen und mit dem vorangestellten Schlüsselwort sub, versehener Anweisungsblock. Also einfach Funktionen.

sub ICH_BIN_EINE_FUNKTION
 {
   #Anweisung(en) was die Funktion machen soll
 }

Hierzu ein kurzes Beispiel ...

#!/usr/bin/perl -w

sub function            #Beginn der Funktion function
 {
 print "Ausgabe in der Funkion \"function\"\n";  #Was die Funktion macht
 }  #Ende der Funktion function

print "Wir rufen nun die Funktion \"function\" auf\n";
function();           #Wir rufen die Funktion function auf
print "Jetzt nach dem Funktionsaufruf\n";

Mit dem Schlüsselwort sub weis unser Perl-Interpreter, hier ist also eine Funktion. sub heißt soviel wie subfunction (Unterfunktion), was für den Perl-Interpreter nichts anderes heißt, dass er diese Funktion nur ausführt, wenn Sie auch aufgerufen wird. Und wie wir eine Funktion aufrufen haben Sie eben gesehen ...

function();

In Perl gibt es außer dieser Methode Funktionen aufzurufen, noch folgende Schreibweisen ...

&function;
&function();
function;

Alle Möglichkeiten liefern das selbe Ergebnis. In diesem Fall macht die Funktion eine Textausgabe mittels print auf dem Bildschirm.

Wozu sollen Funktionen jetzt gut sein? Ich zähle folgende hervorhebende Punkte dazu auf ...

Dies sind nur einige Punkte welchen Vorteil Unterprogramme haben. Weitere werden Sie im Laufe dieser Kapitel von selbst bemerken.

Sie haben übrigens schon seit dem "Hallo Welt" - Perl-Programm, Funktionen verwendet. Beispielsweise print ist auch nichts anderes als eine Funktion.

10.2. Parameter, Argumente und Standardvariable @_           zurück Ein Kapitel tiefer Ein Kapitel höher zum Inhaltsverzeichnis

Wenn Sie sich die Schreibweise von Funktionen wie z.B. print ansehen, können Sie erkennen, dass die meisten Funktionen mit einem Parameter eingesetzt werden. Beispiel ...

print "Ich bin der Parameter von print\n";

Wollen wir uns doch mal ansehen, wie wir dies in Perl bewerkstelligen können ...

#!/usr/bin/perl -w

sub lese_einen_wert       #Beginn der Funktion lese_einen_wert
 {
   print "Sie haben folgendes eingegeben : " . $var . "\n";
 }  #Ende

$var=0;

print "Bitte machen Sie eine Eingabe : ";
chomp ($var=<STDIN>);

lese_einen_wert();     #Funktionsaufruf

Ein weiteres Beispiel mit einem Array ...

#!/usr/bin/perl -w

sub gib_sortiert_aus       #Beginn
 {
  foreach (sort{$a <=> $b} @werte)
    {
      print $_ , "\t";
    }
  print "\n";
 }  #Ende

@werte = (2,9,12,43,2,3,1);

gib_sortiert_aus();

Das sieht doch schon gut aus oder? Aber was machen Sie jetzt, wenn Sie das folgende Array ...

@mehr_werte=(4,66,33,64,34,6,3,65);

... auch noch sortiert ausgeben wollen? Programmiererfahrene wissen es natürlich. Wir rufen die Funktion mit einem Argument auf ...

gib_sortiert_aus(@werte);
gib_sortiert_aus(@mehr_texte);

Nun benötigen Sie nur noch das Wissen, wie Sie mit der Funktion dieses Argument empfangen und bearbeiten können. Hierzu gibt es wieder eine weitere Standardvariable, nämlich @_. Wenn also eine Funktion aufgerufen wird, übernimmt Perl diese Argumente in die Standardvariable @_ und steht dann somit der Funktion zur Verfügung. Dazu folgt wieder ein Skript ...

#!/usr/bin/perl -w

sub gib_sortiert_aus          #Beginn
 {
  foreach (sort{$a <=> $b} @_)
   {
      print $_ , "\t";
   }
  print "\n";
 }  #Ende

@werte = (2,9,12,43,2,3,1);
@mehr_werte=(4,66,33,64,34,6,3,65);

gib_sortiert_aus(@werte);
gib_sortiert_aus(@mehr_werte);

Was wurde hier geändert? Richtig die Standardvariable @_. In dieser stehen jetzt bei jedem Funktionsaufruf die einzelnen Argumente, mit entsprechenden Parametern. Dazu ein weiteres Beispiel ...

#!/usr/bin/perl -w

sub verdopple  #Beginn
 {
   @temp= map {$_* 2} @_ ;
   print "@temp\n";
 } #Ende

@temp=0;
@werte = (2,9,12,43,2,3,1);
@mehr_werte=(4,66,33,64,34,6,3,65);
$skalare=100;

verdopple(@werte);
verdopple(@mehr_werte);
verdopple($skalare);     #So gehts auch

Bei diesem Beispiel verdoppeln wir unseren Wert, der einzelnen Argumente, die wir als Parameter an der Funktion übergeben haben.

10.3. Mehrere Parameter und Argumente           zurück Ein Kapitel tiefer zum Inhaltsverzeichnis

Eben haben Sie gesehen, wie es möglich ist mit Hilfe der Standardvariablen @_, Parameter, die Sie an eine Funktion übergeben, weiterverarbeiten können. Was ist aber, wenn Sie folgendes von unserer Funktion berechnen lassen wollen ...

multipliziere($werta, $wertb);

Dafür gibt es in Perl eine weitere Standardvariable für Funktionen. Nämlich ...

$_[INDEX_NUMMER];

Der erste Parameter sieht somit so aus ...

$_[0];

Der zweite ... $_[1], der dritte ... $_[2] usw. Folglich können Sie diese Standardvariablen in der Funktionen wie folgt einsetzten ...

#!/usr/bin/perl -w

sub mehr_parameter
 {
  print "1.Parameter : " . $_[0] . "\n";
  print "2.Parameter : " . $_[1] . "\n";
  print "3.Parameter : " . $_[2]. "\n";
 }

$var=666;
$name=0;

print "Bitte geben Sie Ihren Namen ein : ";
chomp ($name = <STDIN>);

mehr_parameter($var, $name, 999);
print "\n";
mehr_parameter($name, "Hallo", "Welt");

Bei Array, Hashes und Listen wird dies nun wieder nicht funktionieren. Das Programm wird zwar ablaufen, aber durch die Parameterübergabe $_[0] werden die einzelnen Argumente eines Arrays gebrochen. Somit würde immer nur das erste Element eine Arrays ausgegeben werden. Hier ein Beispiel dazu ...

#!/usr/bin/perl -w

sub lese_array
 {
  @tmp = $_[0];
  print "@tmp\n";
 }

@tmp=0;
@array = ("Feuer", "Eis", "Flamme", "Ball");

lese_array(@array);

Hier wird nur das Wort Feuer ausgegeben. Sie können gerne folgendes in der Funktion hinzufügen ...

print $_[1] , "\n";

Somit wird Feuer und Eis ausgegeben. Was können Sie also tun, damit Arrays, Hashes oder Listen nicht gebrochen werde?

In diesem Fall könnten Sie die Standardvariable @_ verwenden, aber sobald Sie mehrer Parameter übergeben und vor allem Unterschiedliche funktioniert dies auch wieder nicht mehr damit ...

#!/usr/bin/perl -w

sub lese_verschiedenes
 {
  @tmp = @_ ;
  print "@tmp\n";
 }

@tmp=0;
@array = ("Feuer", "Eis", "Flamme", "Ball");
$var=99;
%hash = ("Name" => "user",
         "Vorname" => "superuser");

lese_verschiedenes(@array, $var, %hash);

In diesem Beispiel werden alle drei Parameter in die Standardvariable @_ gelegt und sind somit nicht mehr voneinander zu unterscheiden.

Wir benötigen also etwas, womit Sie die Adressen der Variablen an der Funktion übergeben können. Ein Schelm wer da jetzt an Zeigern denkt ;) Und doch haben Sie Recht, sollten Sie an diese Gedacht haben. In Perl gibt es auch so etwas in der Art, wie die Zeiger. Aber keine Angst, in Perl ist es nicht möglich auf irgendeine Adresse zu zeigen und damit ein Chaos zu verursachen wie etwa in C. Referenzen in Perl werden nur verwendet um auf Variablen zu verweisen.

Referenzen in Perl werden einfach dem Array oder dem Hash mit dem Präfix '\' (Backslash) vorangestellt, wie folgendes Skript demonstrieren soll ...

#!/usr/bin/perl -w

sub lese_array
 {
  $tmp = $_[0];
  print "@{$tmp}" , "\n";
 }

$tmp=0;
@array = ("Feuer", "Eis", "Flamme", "Ball");

lese_array(\@array);

Machen Sie sich jetzt noch keinen Gedanken zu dem Syntax. Zu den Referenzen kommt noch ein extra Kapitel. Wichtig ist hier nur, dass Sie wissen, wie man Arrays, Listen und Hashes an eine Funktion (Unterprogramm) übergeben kann. Hier nun ein Beispiel wie schon im Beispiel oben, wo mehrere Fälle aufeinandertreffen ...

#!/usr/bin/perl -w

sub lese_verschiedenes
 {
  $tmp = $_[0] ;
  print "@{$tmp}\n";
  $tmp = $_[1];
  print $tmp , "\n";
  $tmp = $_[2];
  print %{$tmp} , "\n";
 }

$tmp=0;
@array = ("Feuer", "Eis", "Flamme", "Ball");
$var=99;
%hash = ("Name" => "user",
         "Vorname" => "superuser");

lese_verschiedenes(\@array, $var, \%hash);

Was bisher an den Funktionen ein wenig störend war, ist das immer Globale Variablen eingesetzt wurden. Das sind Variablen die für das gesamte Programm sichtbar sind. Wie im folgendem Beispiel ...

#!/usr/bin/perl -w

sub global
 {
   print $var , "\n";
 }

$var=99;

print $var , "\n";
global();

Hier wird zweimal 99 ausgeben. Nun was ist aber wenn sich in der Funktion die Zahl verändert, obwohl Sie den Wert noch für weiteren Berechnungen benötigt hätten? Beispielweise ...

#!/usr/bin/perl -w

sub global
 {
   $var*=2;
   print $var , "\n";
 }

$var=99;

print $var , "\n";
global();
printf "Hier präsentieren wir den Wert 99 : " . $var . "\n";

Das war wohl nichts mit dem Wert 99. Damit eine Variable nur für Ihre Funktion gültig ist, benötigen Sie das Schlüsselwort my, welches der Variable vorangestellt wird. Hier nun unser Beispiel mit my ...

#!/usr/bin/perl -w

sub global
 {
  my $var= $_[0];     #lokale Variable
  $var*=2;
  print $var , "\n";
 }

$var=99;

print $var , "\n";
global($var);
printf "Hier präsentieren wir den Wert 99 : " . $var . "\n";

Natürlich könnten Sie auch in der Hauptfunktion das Wort my vor $var stellen und in der Funktion global entfernen. Es würde genauso funktionieren. Sie haben in diesem Beispiel die Variable $var als Parameter an unsere Funktion global übergeben. Denn durch die Definition my $var haben wir zwar zwei identisch lautende Variablen, aber belegen diese beiden einen völlig anderen Adressplatz im Speicher.

Eine weitere Möglichkeit eine Variable lokal zu definieren wäre mit dem Schlüsselwort local. Mit diesem Schlüsselwort ist es möglich, dass eine Variable in der Funktion als lokal definiert wird aber für andere Unterfunktionen, damit sind weitere Funktionen gemeint, global bzw. sichtbar bleiben. Einfaches Beispiel ...

#!/usr/bin/perl -w

sub func1
 {
  local $var= $_[0];      #$var ist local aber für func2 sichtbar
  $var*=2;
  print $var , "\n";
  func2();
 }

sub func2
 {
  $var*=2;        #ist local $var von func1
  print $var , "\n";
 }

$var=99;

print $var , "\n";
func1($var);
printf "Hier präsentieren wir den Wert 99 : " . $var . "\n";

Hier wurde durch das Schlüsselwort local die Variable $var als lokal definiert. Diese ist somit durch das Schlüsselwort local in der Funktion func2 sowie für weitere Unterfunktionen sichtbar. Nur nicht für die Hauptfunktion. Was uns die Ausgabe auch bestätigen wird.

Die Parameterübergabe in @_ kann auch durch Iteratives zerstörendes Auslesen der Parameterliste mittels shift geschehen ...

#!/usr/bin/perl -w

sub func{
   my $var1=shift;
   my $var2=shift;
   my $var3=shift;
   my $var4=shift;

    return $var1+$var2+$var3+$var4;
}

@array = (10,30,13,11);

$ergebnis=func(@array);
print $ergebnis , "\n";

Mit dieser Methode wird jeder Wert im Array pro shift-Aufruf an eine Variable übergeben. Der Inhalt von @_ wird dabei aber Zerstört.

Um in Perl eine statische Variable wie in C zu realisieren, können Sie sich mit einem BEGIN-Block behelfen ...

#!/usr/bin/perl -w

BEGIN{
   my $stat=0; #Statische Variable
    sub func{
       print $stat++ ,"\n";
     }
}

 foreach(0..10){
  func(); #Funktionsaufruf
}

Die Funktion selbst befindet sich dabei im BEGIN-Block. Statische Variablen sind Variablen, die Ihren Wert nach Beenden der Funktion behalten und auf die man beim nächsten Funktionsaufruf  wieder zugreifen kann. Besser noch als in C können auf diese Variable gleich mehrere Funktionen auf einmal zugreifen ...

#!/usr/bin/perl -w

BEGIN{
  my $stat=0; #Statische Variable
    sub func{
       print $stat++ ,"\n";
    }
    sub func2{
      print $stat * $stat ,"\n";
    }
}

foreach(0..10){
    func(); func2();  #Funktionsaufruf