为什么substr不会在字符串的末尾返回undef?

时间:2012-10-26 11:27:47

标签: perl substr

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

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 EXPR,OFFSET,LENGTH

     

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

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

2 个答案:

答案 0 :(得分:8)

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

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

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

其次substr length 参数作为返回字符数的上限,而不是要求。这就是文档所指的只返回字符串中的部分

将这些放在一起,像substr 'STRING', 6, 1这样的调用 - 在字符串的末尾要求最大一个字符 - 返回空字符串,而要求超越字符串的结尾(或在其开始之前)提供undef

答案 1 :(得分:5)

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

这为您提供了一个空字符串,因为substr认为offset之间的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)之间。

但是,如果我们尝试访问len(str)以外的任何内容,包括len(str),我们会收到empty字符串,如文档中所示, -

  

如果OFFSET和LENGTH指定一个部分在...之外的子字符串   string,只返回字符串中的部分。

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

  

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