ODER in Perl in Wirklichkeit ENTWEDER-ODER?
Yadgar
- perl
High!
Ich arbeite mich gerade durch ein Perl-Lehrbuch (konkret: Randal L. SCHWARTZ, Tom CHRISTIANSEN: Einführung in Perl, O'Reilly 1998) und stelle in einem Übungslisting fest, das Ergebnis einer ODER-Verknüpfung offensichtlich FALSE ist, wenn beide Teile TRUE sind!
Es geht um die Subroutine wort_richtig, die prüft, ob es für den eingegebenen Benutzernamen in dem am Beginn des Programms definierten Hash ein passendes Passwort gibt, falls nicht, soll "groucho" als Passwort akzeptiert werden. Interessanterweise führt die Eingabe "groucho", wenn es für den Benutzeramen ein reguläres Passwort gibt, zu einer Falsch-Meldung, was bei logisch ODER, wie ich es aus anderen Programmiersprachen kenne, nicht passieren dürfte!
Hier der Code:
sub wort_richtig
{
my ($einname, $einrateversuch) = @_;
$einname =~ s/\W.*//; # alles hinter dem ersten Wort löschen
$einname =~ tr/A-Z/a-z/; # alles in Kleinbuchstaben umwandeln
if ($einname eq "yadgar")
{
return 1;
}
elsif (($worte{$einname} || "groucho") eq $einrateversuch)
{
return 1;
}
else
{
return 0;
}
}
Bis bald im Khyberspace!
Yadgar
Hallo Yadgar,
elsif (($worte{$einname} || "groucho") eq $einrateversuch)
ich habe zwar keine Ahnung von Perl, hier aber scheinst du zuerst $worte{$einname} mit "groucho" zu verodern und das Ergebnis davon mit $einrateversuch zu vergleichen. Willst du das wirklich?
Gruß, Jürgen
Hallo Yadgar,
elsif (($worte{$einname} || "groucho") eq $einrateversuch)
ich habe zwar keine Ahnung von Perl, hier aber scheinst du zuerst $worte{$einname} mit "groucho" zu verodern und das Ergebnis davon mit $einrateversuch zu vergleichen. Willst du das wirklich?
Das würde an dem Problem nichts ändern - auch wenn erst auf die Wahrheit der beiden Passwörter geprüft wird, sollte doch TRUE || TRUE wiederum TRUE und nicht FALSE ergeben!
Bis bald im Khyberspace!
Yadgar
Das würde an dem Problem nichts ändern - auch wenn erst auf die Wahrheit der beiden Passwörter geprüft wird, sollte doch TRUE || TRUE wiederum TRUE und nicht FALSE ergeben!
Tut es doch.
Struppi.
Ich arbeite mich gerade durch ein Perl-Lehrbuch (konkret: Randal L. SCHWARTZ, Tom CHRISTIANSEN: Einführung in Perl, O'Reilly 1998) und stelle in einem Übungslisting fest, das Ergebnis einer ODER-Verknüpfung offensichtlich FALSE ist, wenn beide Teile TRUE sind!
Um welches geht's konkret?
Es geht um die Subroutine wort_richtig, die prüft, ob es für den eingegebenen Benutzernamen in dem am Beginn des Programms definierten Hash ein passendes Passwort gibt, falls nicht, soll "groucho" als Passwort akzeptiert werden. Interessanterweise führt die Eingabe "groucho", wenn es für den Benutzeramen ein reguläres Passwort gibt, zu einer Falsch-Meldung, was bei logisch ODER, wie ich es aus anderen Programmiersprachen kenne, nicht passieren dürfte!
Du musst es nur richtig schreiben. Du hast:
($worte{$einname} || "groucho") eq $einrateversuch
Die linke Seite wird wie folgt ausgewertet: Ist $worte{$einname} wahr? Wenn nein, nimm 'groucho'. Wenn ja, sei 'groucho' Banane. Daher wird der Vergleich eines Users mit existierendem Passwort *nie* gegen 'groucho' evaluieren. Das, was Du willst, ließe sich so ausdrücken:
elsif($einrateversuch eq $worte{$einname} or $einrateversuch eq 'groucho') {
return 1;
}
Siechfred
High!
elsif($einrateversuch eq $worte{$einname} or $einrateversuch eq 'groucho') {
return 1;
}
Das habe ich dann zwischenzeitlich auch so umgestellt und jetzt funktioniert es - danke für den Tipp!
Bis bald im Khyberspace!
Yadgar
High!
Hugh Yadgar
Damit dus auch richtig verstehst...
Habe das Buch selbst konnte dieses Listing aber nicht finden, allerdings das Kapitel "Kontrollstrukturen mit teilweise auswertenden Operatoren" S. 162
1. Bei && || und ?: wird die rechte Seite nicht ausgewertet wenn die linke reicht. (deswegen wird auch von Kurzschlussoperatoren gesprochen).
2. Rückgabewert der Operationen ist (im Gegensatz zu anderen Sprachen) kein Boolescher Wert sondern der letzte ausgertete Ausdruck!!!
z.B. liefert
print ( ($n!=0) && (5/$n) );
Für $n ungleich 0 den Divisionswert aus der rechten Seite
Für $n=0 gibts aber keine Fehlermeldung, weil die Rechte Seite nicht erreicht wird.
elsif (($worte{$einname} || "groucho") eq $einrateversuch)
Nur wenn $worte{$einname} nicht undef oder 0 (!!!) ist, ist "groucho" Rückgabewert der Klammer, und der wird dann mit $einrateversuch verglichen.
Tschau
Kurt
Stimmt alles, aber hier fehlt noch was:
elsif (($worte{$einname} || "groucho") eq $einrateversuch)
Nur wenn $worte{$einname} nicht undef oder 0 (!!!) ist,
oder kein Leerstring.
Struppi.
Hi
Nur wenn $worte{$einname} nicht undef oder 0 (!!!) ist,
oder kein Leerstring.
Danke, also generell undefiniert oder unbelegt oder 0.
(leere Hashes oder Arrays sind nämlich auch "falsch")
Umsteiger müssen sich klar machen das Perl keinen Booleschen Datentyp mit den Werten "true" oder "false" hat. Bedingungen sind bei den obigen Fällen falsch und ansonsten wahr.
Was bei einem geklammerten logischen Ausdruck rauskommt, hängt von den Rückgabewert der Einzelterme und ihrer Position ab und ist kein "true" oder "false".
In Javascript ist es übrigens ähnlich...
alert(0 || "trulla") ergibt "trulla" (rechte Seite musste ausgewertet werden)
alert(1 || "trulla") ergibt 1 (rechte Seite konnte übersprungen werden)
Tschau
Kurt
oder der String "0" ... ich glaubs selbst nicht aber ...
$var="0";
print "Skandal" unless ($var);
SKANDAL!
Kurt
Naja
SKANDAL!
ist wohl zu hart aber ich hatte immer die Hoffnung dass man Javascript als eingeschränktes Perl begreifen könne, aber sowas ...
Kurt