2016-05-13 2 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 
} 

E.g. Если я перехожу к doit под любым строковым средним значением - (с нулевым или без начального нуля), он должен быть преобразован в восьмеричное значение. В противном случае это просто число.

+2

Хотите знать, почему вы хотите такой интерфейс, где в кавычках и без аргументов ведет себя по-другому. Для меня это похоже на источник будущих ошибок ... – jm666

+0

@cajwine: это противоречит тому, что вы говорите в вопросе, где вы хотите, чтобы doit ('123') считался восьмеричным? – 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?

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

Update некоторые из этих функций выставляется в модуле ядра B, так что нет необходимости добавлять в XS зависимость:

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

'sub isNumber {no warnings" numeric "; length ($ _ [0] & "")} ' – ysth

+0

Ahh да !!! 'Use B', полученный' isString', является * точно * для того, что я смотрю. Также работает 'isNumber' @ysth, но' isString' почти в два раза быстрее. ВЕЛИКИЙ! Спасибо. ;) – cajwine

Смежные вопросы