7 Stimmen

Den Datentyp einer skalaren Variablen in Perl ermitteln

Ich habe eine Funktion, die eine Eingabe vom Benutzer annimmt. Die Eingabe kann ein Integer, ein Float oder ein String sein. Ich habe drei überladene Funktionen, die auf der Grundlage des Datentyps der eingegebenen Daten aufgerufen werden sollen. Wenn der Benutzer zum Beispiel eine ganze Zahl (z.B. 100) eingibt, sollte die Funktion mit dem Parameter integer aufgerufen werden. Wenn der Benutzer eine Zeichenkette eingibt (z. B. "100"), sollte die Funktion mit dem String-Parameter aufgerufen werden.

Ich muss also den Datentyp der eingegebenen Daten herausfinden. Mit regulären Ausdrücken kann ich zwischen einem Integer und einem Float unterscheiden (da ich nur den Typ herausfinden muss, würde ich die Bibliothek von cpan.org nicht vorziehen), aber ich kann nicht herausfinden, wie ich einen Integer von einem String unterscheiden kann. Behandelt Perl "100" und 100 als das gleiche? Gibt es eine Möglichkeit, dieses Problem zu umgehen?

11voto

Brian Gerard Punkte 885

Von perldoc perldata :

Skalare sind nicht unbedingt das eine oder das andere. Es gibt keine Möglichkeit, eine Skalarvariable als Typ "String", Typ "Zahl", Typ "Referenz" oder etwas anderes zu deklarieren. Wegen der automatischen Konvertierung von Skalaren müssen sich Operationen, die Skalare zurückgeben, nicht darum kümmern (und können sich eigentlich auch nicht darum kümmern), ob ihr Aufrufer nach einer Zeichenkette, einer Zahl oder einer Referenz sucht. Perl ist eine kontextuell polymorphe Sprache, deren Skalare Zeichenketten, Zahlen oder Referenzen (die Objekte einschließen) sein können. Obwohl Zeichenketten und Zahlen für fast alle Zwecke als so ziemlich das Gleiche angesehen werden, sind Referenzen stark typisierte, uncastbare Zeiger mit eingebauter Referenzzählung und Destruktoraufruf.

Für ganzzahlige Skalare müssen Sie also im Voraus entscheiden, wie Sie sie verarbeiten wollen. Perl konvertiert fröhlich von einer Zahl in einen String oder umgekehrt, je nach Kontext.

10voto

Eric Strom Punkte 39363

Perl macht keinen sinnvollen Unterschied zwischen Zahlen und String-Repräsentationen dieser Zahlen. Ihr Skript sollte das auch nicht. Sie könnten etwas Code schreiben, um zwischen Dingen zu unterscheiden, die wie Ganzzahlen und Fließkommazahlen aussehen, aber die einzige Möglichkeit zu wissen, ob es sich um eine Zeichenkette handelt, ist, wenn der Skalar nicht wie eine Ganzzahl oder eine Fließkommazahl aussieht.

Hier ist eine einfache Routine, die Folgendes zurückgibt int , rat , oder str für sein Argument. Beachten Sie, dass 100 y '100' sind beide int sondern etwas wie 'asdf' wird str .

use Scalar::Util 'looks_like_number';
sub guess_type {
    looks_like_number($_[0]) ? $_[0] =~ /\D/ ? 'rat' : 'int' : 'str'
}

say guess_type 1;      # int
say guess_type "1";    # int
say guess_type 1.1;    # rat
say guess_type 'asdf'; # str

Da Sie daran arbeiten, Perl-Variablen auf C-Funktionen abzubilden, könnten Sie etwas wie folgt schreiben:

sub myfunction {
    if (looks_like_number($_[0]) {
        if ($_[0] =~ /\D/) {C_float($_[0])}
        else               {  C_int($_[0])}
    }
    else {C_string($_[0])}
 }

Das sollte "das Richtige tun", wenn ein Perl-Skalar gegeben wird. Sie können auch eine Prüfung hinzufügen, um zu sehen, ob das Argument ein Verweis ist, und dann behandeln diesen Fall anders.

2voto

pavel Punkte 3480
#!perl6

use v6;

multi guess ( Int $a ) { say "got integer: $a" }
multi guess ( Str $a ) { say "got string: $a" }  
multi guess ( Rat $a ) { say "got float: $a" }

guess(3);
guess("3");
guess(3.0);

Schummeln, ich weiß...

Paul

1voto

yarian Punkte 5734

Haben Sie in Erwägung gezogen, der Funktion eine Hash-Referenz zu übergeben, wobei die Schlüssel angeben, welchen Datentyp die Eingabe hat?

my $str_input = { string => "100" };
my $int_input = { integer => 100 };
my $float_input = { float => 100.0 };

Sie können überprüfen, welchen Typ Sie erhalten haben, indem Sie prüfen, welche Taste der Eingang hat: my $datatype = shift (keys %{$input}) und nehmen Sie es von dort aus. (Beachten Sie die implizite Dereferenzierung, die mit $input )

switch ($datatype) {
   case string:
       C_string($input->{$datatype});
   case integer:
       C_integer($input->{$datatype});
   case float:
       C_float($input->{$datatype});
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X