【问题标题】:Differentiate string and number argument in perl区分perl中的字符串和数字参数
【发布时间】:2016-05-14 14:50:02
【问题描述】:

如何解决以下问题?

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 子 - 平均引用值 - (带或不带前导零),它应该转换为八进制值。否则,它只是一个数字。

【问题讨论】:

  • 想知道为什么需要这样的接口,其中带引号和不带引号的参数的行为不同。对我来说,这看起来像是未来错误的来源......
  • @cajwine:这与你在你希望 doit('123') 也被视为八进制的问题中所说的相矛盾??

标签: perl


【解决方案1】:

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
0123 => 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?

更新其中一些功能在核心B 模块中公开,因此无需添加为XS 依赖项:

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

【讨论】:

  • sub isNumber { no warnings "numeric"; length($_[0] & "") }
  • 啊是的!!! use B 派生的isString 正是符合我的要求。 @ysth 的 isNumber 也可以工作,但 isString 的速度几乎快了一倍。伟大的!谢谢你。 ;)
  • @ysth 您能否解释一下,理想情况下,请提供一个将这种方法描述为替代方法的答案。我理解按位 AND 但我仍然不确定它为什么有效。谢谢!
猜你喜欢
  • 2021-10-07
  • 1970-01-01
  • 1970-01-01
  • 2012-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多