9

我不确定这是否是定义的行为。我有以下代码:

use strict;
use warnings;
use Data::Dumper;

my $string = 'aaaaaa0aaaa';
my $char = substr($string, length($string), 1);
my $char2 = substr($string, length($string)+1, 1);

print Dumper($char);
print Dumper($char2);

除了收到关于字符串结尾的警告之外substr(),我对输出感到困惑:

$VAR1 = '';
$VAR1 = undef;

Perldocsubstr

substr 表达式,偏移量,长度

如果 OFFSET 和 LENGTH 指定了部分在字符串之外的子字符串,则只返回字符串内的部分。如果子字符串超出字符串的任一端,则 substr() 返回未定义的值并产生警告。

两者length($string)length($string) + 1都超出了字符串的(零索引)结尾,所以我不知道为什么substr在一种情况下返回空字符串,在另一种情况下返回空字符串undef。它是否与 C 用于字符串终止的 NULL 字符有关,并且substr在第一种情况下以某种方式返回,因此该字符串有一个“不可见”的最后一个字符不计入length?我在这里遗漏了一些明显的东西吗?

4

2 回答 2

8

这里有几个问题。首先,您应该考虑substr 偏移量来指示字符之间的位置,因此:

 S T R I N G
0 1 2 3 4 5 6

所以你可以看到偏移量 6 - 字符串的长度 - 位于字符串的末尾,而不是超出它。

其次,长度参数substr作为返回字符数的上限,而不是要求。这就是文档的含义,仅返回字符串中的部分

将这些放在一起,类似的调用substr 'STRING', 6, 1- 要求在字符串末尾最多一个字符- 返回空字符串,同时要求超出字符串结尾(或在其开始之前)的任何内容给出.undef

于 2012-10-26T12:47:19.403 回答
5
substr($string, length($string), 1)

这给了您一个空字符串,因为substr考虑了offsetbetween 0 to len(str),并且超出该范围的任何内容都是undef.

所以,substr("aa", 2, 1);-> 会给你最后一个空字符串a
substr("aa", 3, 1);-> 会给你undef(子字符串完全超出范围)

相似地: -

  • substr("aa", 2, 2);-> 会在最后一个之后给你空字符串 a(部分超出范围的子字符串)

现在,对于第二个: -

substr($string, length($string) + 1, 1)

这已经超过了最后一个允许的时间offset。所以它返回undef值。

认为: -

$str = "abcd";

然后,索引将如下所示: -

  a   b   c   d             undef
0   1   2   3  len(str)  len(str) + 1

更新: -

因此,正如@Borodin 在他的帖子中解释的那样,该字符d位于偏移量之间 -3len(str)上面的示例中。

但是,如果我们尝试访问除 include 之外的任何len(str)内容len(str),我们将得到一个empty字符串,如文档中所示 -

如果 OFFSET 和 LENGTH 指定了部分在字符串之外的子字符串,则只返回字符串内的部分。

此外,如果我们尝试访问除len(str)之外的任何内容len(str),我们将获得undef价值,如docs中所示:-

如果子字符串超出字符串的任一端,则 substr() 返回未定义的值并产生警告。

于 2012-10-26T11:52:07.183 回答