我不确定这是否是已定义的行为。我有以下代码:
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;
Perldoc说substr
:
substr EXPR,OFFSET,LENGTH
如果OFFSET和LENGTH指定部分位于字符串之外的子字符串,则仅返回字符串中的部分。如果子字符串超出字符串的任何一端,则substr()返回未定义的值并产生警告。
length($string)
和length($string) + 1
都超出了字符串的(零索引)结尾,所以我不知道为什么substr
在一个案例中返回空字符串而undef
1}}在另一个。它是否与C用于字符串终止的NULL字符有关,并且在第一种情况下由substr
以某种方式返回,因此该字符串有一个“不可见”的最后一个字符,不计入{ {1}}?我错过了一些明显的东西吗?
答案 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
位于上例中的偏移量3
和len(str)
之间。
但是,如果我们尝试访问len(str)
以外的任何内容,包括len(str)
,我们会收到empty
字符串,如文档中所示, -
如果OFFSET和LENGTH指定一个部分在...之外的子字符串 string,只返回字符串中的部分。
,如果我们尝试访问除len(str)
之外的len(str)
以外的任何内容,我们将获得undef
值,如 docs : -
如果子字符串超出字符串的任何一端,则substr()返回 未定义的值并产生警告。