2016-05-13 6 views
2

次の問題を解決するには?perlの文字列と数値の引数を区別する

use 5.014; 
use warnings; 
use Test::Simple tests => 4; 

ok(doit(0123) == 83, "arg as octal number"); 
ok(doit(83)  == 83, "arg as decimal number"); 
ok(doit('0123') == 83, "arg as string with leading zero"); 
ok(doit('123') == 83, "arg as string without leading zero"); 

sub doit { 
    my $x = shift; 
    return $x;          # how to replace this line 
    #return got_the_arg_as_string ? oct($x) : $x; # with something like this 
} 

など。私がdoitサブ文字列に渡す場合、引用符で囲まれた値 - (先頭に0を付けてもしなくても)8進値に変換する必要があります。それ以外の場合は、単なる数字です。

+2

が疑問に思います異なる動作をします。私にとってこれは未来のバグの源のように見えます... – jm666

+0

@cajwine:これはdoit( '123')が8進数であると考えられるかどうかという質問であなたが言うことと矛盾しますか? – ysth

答えて

6

Perlのスカラーの内部表現は、整数または文字列の場合と同じであり、いつでも他のスカラー型にその表現を強制する準備ができています。 C/XSコードでスカラーの内部型を取得することは可能です。 JSON::XSモジュールは、たとえば、値を数値として出力するか文字列として出力するかを決定するためにこれを行います。

はここにあなたの問題のためのコンセプトの証明です:

use Inline 'C'; 
sub foo { 
    my ($x) = @_; 
    print $x, " => isString: ", isString($x), "\n"; 
} 
foo(0123); 
foo('0123'); 

__END__ 
int isString(SV* sv) 
{ 
    return SvPOK(sv) ? 1 : 0; 
} 

プログラムの出力:

83 => isString: 0 
=> isString: 1 

関連記事:

Difference between $var = 500 and $var = '500'

When does the difference between a string and a number matter in Perl 5?

この機能の一部がコア Bモジュールにさらされ

Why does the JSON module quote some numbers but not others?

更新、XSの依存関係として追加するので、必要はありません:あなたは、このようなインターフェイス、引用されたと引用符で囲まれていない引数をする理由

use B; 
sub isString { 
    my $scalar = shift; 
    return 0 != (B::svref_2object(\$scalar)->FLAGS & B::SVf_POK) 
} 
+2

'sub isNumber {警告なし"数値 ";長さ($ _ [0]& "")} ' – ysth

+0

ああはい!!!派生した 'use B'は'私が探しているもののためのisString'です。 @ysthの 'isNumber'も機能しますが、' isString'はほぼ2倍の速さです。すばらしいです!ありがとうございました。 ;) – cajwine

関連する問題