ppt

Werbung
Programmierkurs für absolute Anfänger
 weitere Arrayfunktionen, Hashes, Sortieren
Caren Brinckmann
Sommersemester 2005
http://www.coli.uni-saarland.de/~cabr/teaching.php
Funktion defined


Die Funktion defined testet, ob eine Variable einen anderen Wert
als undef enthält.
Ist der Wert undef, so wird falsch zurückgegeben, in allen
anderen Fällen wahr.
$nachname = <STDIN>; chomp $nachname;
if ($nachname eq "Barry") {
$vorname = "Bill";
} elsif ($nachname eq "Pinkal") {
$vorname = "Manfred";
}
# ...
if (! defined($vorname)) {
$vorname = "Herr/Frau";
}
$name = $vorname . " " . $nachname;
Programmierkurs für absolute Anfänger – Sitzung 10
1
defined  Arrayelemente


Durch automatische Arrayerweiterung erzeugte
Arrayelemente haben (sofern ihnen nicht explizit ein
Wert zugewiesen wurde) den Wert undef.
Dies lässt sich mit der Funktion defined abprüfen:
$steine[0] = "feuerstein";
$steine[1] = "schiefer";
$steine[5] = "basalt";
foreach $stein (@steine) {
unless (defined $stein) {
$stein = "kies";
}
}
print "@steine";
Programmierkurs für absolute Anfänger – Sitzung 10
2
Funktion exists


Die Funktion exists testet, ob einem Arrayelement mit einem
bestimmten Index jemals irgendein Wert zugewiesen wurde.
Wurde dem Element schon mal ein Wert zugewiesen (egal ob dies
der Wert undef oder ein anderer Wert ist), so wird wahr
zurückgegeben, sonst falsch.
$steine[0] = "feuerstein";
$steine[1] = undef;
$steine[4] = "basalt";
for ($i=0; $i<=10; $i++) {
if (exists $steine[$i]) {
print "Arrayelement mit Index $i existiert!\n";
}
}
Programmierkurs für absolute Anfänger – Sitzung 10
3
exists vs. defined
@array = (9, 0, undef, "", "hallo");
for ($index=0; $index<=@array; $index++) {
print "Element $index:\n";
if (exists $array[$index]) {
print "\texistiert.\n";
}
if (defined $array[$index]) {
print "\tist definiert.\n";
}
if ($array[$index]) {
print "\tist wahr.\n";
}
}
Programmierkurs für absolute Anfänger – Sitzung 10
4
Aufrufende Argumente in @ARGV


Einem Perl-Programm kann man beim Programmaufruf
Argumente übergeben, um das Verhalten des Programms
zu beeinflussen.
Beispiel: Ein Programm, dass aus einer Datei die Wörter
heraussucht, die aus einer bestimmten Anzahl von Silben
bestehen.
perl -w silbenzahl.pl 5 < silben.txt > fuenfsilb.txt
perl -w silbenzahl.pl 3 < silben.txt > dreisilb.txt


Beim Programmaufruf legt Perl die Liste der aufrufenden
Argumente in dem speziellen Array @ARGV ab.
Ansonsten verhält sich @ARGV wie ein normales Array:
Elemente können z.B. mit shift entfernt werden, oder man
kann mit einer foreach-Schleife über das Array iterieren.
Programmierkurs für absolute Anfänger – Sitzung 10
5
Funktion die


Schwerwiegende Fehler im Programmablauf kann man
mit der Funktion die abfangen.
die: gibt eine ihr übergebene Fehlermeldung aus und
beendet das Programm.
## Programmaufruf:
## perl -w silbenzahl.pl 5 < silben.txt > fuenfsilb.txt
if (defined $ARGV[0]) {
$silbenzahl = $ARGV[0];
} else {
die "Du hast vergessen, eine Silbenzahl
anzugeben!\nProgrammaufruf: perl -w silbenzahl.pl
5 < silben.txt\n";
}
Programmierkurs für absolute Anfänger – Sitzung 10
6
Hashes (1)




Hash: ungeordnete Ansammlung von Schlüssel/Wert-Paaren
Früher wurden Hashes auch "assoziative Arrays" genannt.
Jeder Schlüssel ist eine eindeutige Zeichenkette, d.h. er darf nur
einmal im Hash vorkommen.
Ein Wert kann eine Zahl, eine Zeichenkette oder undef sein. Gleiche
Werte dürfen beliebig häufig im Hash vorkommen.
Beispiel: Hash mit 5 Elementen
Schlüssel

Werte
35
"foo"
12.4
"bar"
undef
"2.5"
35
"Wilma"
"Betty" "Ciao!\n"
Programmierkurs für absolute Anfänger – Sitzung 10
7
Hashes (2)



Achtung: Die Reihenfolge der Schlüssel/Wert-Paare ist
ungeordnet, d.h. Perl legt die Schlüssel/Wert-Paare
intern so ab, dass ein schneller Zugriff möglich ist.
Daher ist es unmöglich vorherzusagen, welches das erste
und welches das letzte Schlüssel/Wert-Paar ist.
Anzahl der Schlüssel/Wert-Paare: beliebig!



kleinstes Hash: leer (gar keine Schlüssel/Wert-Paare)
größtes Hash: füllt den gesamten Hauptspeicher
Anwendungsfälle:


kleine Datenbank, z.B. Benutzerausweisnummer als Schlüssel,
Name als Wert
Vorkommenshäufigkeiten zählen
Programmierkurs für absolute Anfänger – Sitzung 10
8
Hashes (3)

Hashvariablen beginnen in Perl mit %

Als Wert wird einer Hashvariablen eine Liste zugewiesen,
die aus Schlüssel/Wert-Paaren besteht, d.h. das erste
Listenelement ist ein Schlüssel, das zweite sein Wert, das
dritte wiederum ein Schlüssel, das vierte sein Wert usw.
%meinhash = ("foo", 35, "bar", 12.4, "2.5",
undef, "Wilma", 35, "Betty", "Ciao!\n");

Ein leeres Hash enthält die leere Liste:
%leereshash = ();

Ein Hash kann komplett in eine andere Hashvariable
gespeichert werden:
%meinhash_kopie = %meinhash;
Programmierkurs für absolute Anfänger – Sitzung 10
9
Pfeil-Notation

Die Pfeilnotation erleichtert die Schreibweise bei der
Initialisierung eines Hash:
%nachname =
"Fred"
"Dino"
"Barney"
"Betty"
);
(
=>
=>
=>
=>
"Feuerstein",
undef,
"Geroellheimer",
"Geroellheimer",
Programmierkurs für absolute Anfänger – Sitzung 10
10
Beispiel: Schlüssel und Werte vertauschen




Da ein Hash auch nichts anderes ist als eine Liste, kann
die Funktion reverse auch auf ein Hash angewendet
werden.
Dadurch wird jeder Wert zu einem Schlüssel, und jeder
Schlüssel zu einem Wert.
%vorname = reverse %nachname;
Achtung: Jeder Schlüssel darf nur einmal vorkommen.
Wenn also %nachname 2 oder mehr gleiche Werte enthält,
gilt die Regel "der Letzte gewinnt", wobei aber Perl die
Reihenfolge festlegt.
Daher lässt sich bei mehrfach vorkommenden Werten
nicht vorhersagen, welches Schlüssel/Wert-Paar im
umgedrehten Hash enthalten sein wird.
Programmierkurs für absolute Anfänger – Sitzung 10
11
Zugriff auf Hashelemente (1)

Auf ein einzelnes Array-Element wird über den Index in eckigen
Klammern zugegriffen, z.B. $array[2]

Auf einen einzelnen Wert in einem Hash greift man über seinen
Schlüssel in geschweiften Klammern zu, z.B.:
print $nachname{"Fred"};

So kann einem Hash auch ein neues Schlüssel/Wert-Paar
hinzugefügt werden:
$nachname{"Wilma"} = "Feuerstein";

Ebenso kann der Wert eines existierenden Schlüssels überschrieben
werden:
$nachname{"Fred"} = "Astaire";

Achtung:
$nachname{"Fred"}  $nachname["Fred"]  $nachname
Programmierkurs für absolute Anfänger – Sitzung 10
12
Zugriff auf Hashelemente (2)

Versucht man, auf nicht-existierende Elemente zuzugreifen, so gibt Perl
undef zurück:
$name = $nachname{"Anna"};

Als Schlüssel können Zeichenkettenliterale, Variablen, die eine
Zeichenkette enthalten, oder beliebige Ausdrücke verwendet werden,
die eine Zeichenkette ergeben:
$foo = "Bar";
print $nachname{$foo . "ney"};

Einzelne Hashelemente werden in einer Zeichenkette in doppelten
Anführungszeichen interpoliert:
foreach $vor ("Barney", "Fred") {
print "Ich kenne $vor $nachname{$vor}\n";
}
Programmierkurs für absolute Anfänger – Sitzung 10
13
Hashfunktion: each

each: gibt pro Aufruf ein Schlüssel/Wert-Paar des Hash als Liste aus
zwei Elementen zurück.

Sind keine Elemente mehr übrig (d.h. wenn each schon alle
Schlüssel/Wert-Paare des Hash zurückgegeben hat), gibt each die
leere Liste zurück.
while (($vor, $nach) = each %nachname) {
print "Ich kenne $vor $nach.\n";
}

Achtung: Die Reihenfolge der von each zurückgegebenen
Schlüssel/Wert-Paare lässt sich nicht vorhersagen, da sie von der
von Perl intern festgelegten Reihenfolge abhängt.
Programmierkurs für absolute Anfänger – Sitzung 10
14
Hashfunktionen: keys und values (1)

keys: gibt eine Liste aller in einem Hash enthaltenen Schlüssel
zurück (bzw. die leere Liste, wenn das Hash leer ist).

values: gibt eine Liste aller in einem Hash enthaltenen Werte zurück
(bzw. die leere Liste, wenn das Hash leer ist).
%meinhash = ("a" => 1, "b" => 2, "c" => 1);
@schluessel = keys %meinhash;
@werte = values %meinhash;

Achtung: Enthält ein Hash mehrmals denselben Wert, so enthält die
von values erzeugte Liste auch mehrfach denselben Wert.

Die von keys und values erzeugten Listen enthalten also immer
genausoviele Elemente wie das Hash Schlüssel/Wert-Paare enthält.

Im skalaren Kontext wird die Anzahl der Schlüssel/Wert-Paare
zurückgegeben: $anzahl = keys %meinhash;
Programmierkurs für absolute Anfänger – Sitzung 10
15
Hashfunktionen: keys und values (2)

Achtung: Die Reihenfolge der von keys oder values
zurückgegebenen Listenelemente lässt sich nicht vorhersagen, da sie
von der von Perl intern festgelegten Reihenfolge der Schlüssel/WertPaare abhängt.

Ausgabe in sortierter (Schlüssel-)Reihenfolge mit sort:
%nachname = (
"Fred"
=>
"Feuerstein",
"Dino"
=>
undef,
"Barney" =>
"Geroellheimer",
"Betty"
=>
"Geroellheimer",
);
foreach $vor (sort keys %nachname) {
print "Ich kenne $vor $nachname{$vor}.\n";
}
Programmierkurs für absolute Anfänger – Sitzung 10
16
Funktionen: exists und defined


exists: gibt wahr zurück, wenn der angegebene
Schlüssel in dem Hash existiert, und falsch, wenn nicht.
if (exists $nachname{"Dino"}) {
print "Dino existiert!\n";
}
defined : gibt wahr zurück, wenn der angegebene
Schlüssel in dem Hash existiert und der entsprechende
Wert nicht undef ist, ansonsten ist der Rückgabewert
falsch.
if (defined $nachname{"Dino"}) {
print "Dino hat einen Nachnamen!\n";
}
Programmierkurs für absolute Anfänger – Sitzung 10
17
Hashfunktion: delete


delete: entfernt den angegebenen Schlüssel (und den
dazugehörigen Wert) aus einem Hash.
Der Rückgabewert von delete ist der entfernte Wert bzw.
undef, wenn das Schlüssel/Wert-Paar nicht existiert.
$vorname = "Betty";
$bettysnachname = delete $nachname{$vorname};
if (exists $nachname{$vorname}) {
print "Betty ist noch vorhanden!\n";
}
Programmierkurs für absolute Anfänger – Sitzung 10
18
Beispiel: Wortfrequenzen

Ein Perl-Programm, das ausgibt, wie häufig jedes Wort in einem
Text vorkommt.
%freq = ();
while ($zeile = <STDIN>) {
@woerter = split(/[\s.,:;?!"']+/,$zeile);
foreach $wort (@woerter) {
$freq{$wort}++;
}
}
foreach $wort (sort keys %freq) {
print "$wort: $freq{$wort}\n";
}
Programmierkurs für absolute Anfänger – Sitzung 10
19
Vergleichsoperatoren: <=> und cmp

Der binäre Vergleichsoperator <=> liefert als
Rückgabewert -1, 0 oder 1, abhängig davon, ob das
linke Argument numerisch kleiner, gleich oder größer ist
als das rechte Argument:
$rueckgabe = -10 <=> -100;
print $rueckgabe;

Der binäre Vergleichsoperator cmp liefert als
Rückgabewert -1, 0 oder 1, abhängig davon, ob das
linke Argument lexikographisch kleiner, gleich oder
größer ist als das rechte Argument:
$rueckgabe = "hallo" cmp "Helm";
print $rueckgabe;
Programmierkurs für absolute Anfänger – Sitzung 10
20
Fortgeschrittenes Sortieren (1)




Im Standardfall sortiert sort eine Liste lexikographisch, d.h. ASCIIbetisch: Zahlen vor Großbuchstaben vor Kleinbuchstaben.
@unsortarray = ("hallo", "Halt", "2raum");
@sortarray = sort @unsortarray;
print "@sortarray\n";
Wenn man z.B. eine Liste von Zahlen sortieren möchte, führt dieses
Standardverhalten zu einem unerwünschten Ergebnis:
@unsortnum = (2, 1, 10);
@sortnum = sort @unsortnum;
print "@sortnum\n";
Um das Standardverhalten zu ändern, kann man sort mit einer
expliziten Sortierroutine in geschweiften Klammern aufrufen, die -1, 0
oder 1 zurückgibt, z.B.:
@sortnum = sort {$a <=> $b} @unsortnum;
$a und $b sind zwei von Perl automatisch zur Verfügung gestellte
Variablen, die jeweils zwei zu vergleichenden Elementen der zu
sortierenden Liste entsprechen.
Programmierkurs für absolute Anfänger – Sitzung 10
21
Fortgeschrittenes Sortieren (2)

lexikographisch sortieren (mit expliziter Sortierroutine):
@sortarray = sort {$a cmp $b} @unsortarray;

in umgekehrter Reihenfolge lexikographisch sortieren:
@sortarray = sort {$b cmp $a} @unsortarray;

aufsteigend numerisch sortieren:
@sortnum = sort {$a <=> $b} @unsortnum;

absteigend numerisch sortieren:
@sortnum = sort {$b <=> $a} @unsortnum;

lexikographisch sortieren ohne Berücksichtigung von Groß- und
Kleinschreibung:
@sortarray = sort {"\L$a" cmp "\L$b"} @unsortarray;
Programmierkurs für absolute Anfänger – Sitzung 10
22
Fortgeschrittenes Sortieren (3)

Hash nach Werten absteigend numerisch sortieren:
%ergebnis = (
"Barney" => 195,
"Fred"
=> 205,
"Dino"
=> 30,
);
@rangfolge = sort
{$ergebnis{$b} <=> $ergebnis{$a}} keys %ergebnis;
print "@rangfolge\n";

Wörter absteigend sortiert nach ihrer Häufigkeit und aufsteigend
lexikographisch (ohne Groß-/Kleinschreibung) ausgeben:
foreach $wort (sort {$freq{$b} <=> $freq{$a}
|| "\L$a" cmp "\L$b"} keys %freq) {
print "$wort: $freq{$wort}\n";
}
Programmierkurs für absolute Anfänger – Sitzung 10
23
Herunterladen