Perl - 无法将字符串(...)用作数组引用

3
我正在使用codeeval.com上的挑战练习Perl,但是遇到了一个意外的错误。目标是逐行迭代文件,在每一行中,字符串和字符用逗号分隔,并找到该字符在字符串中最右边的出现位置。我得到了错误的答案,所以我修改了代码,仅打印变量的值,但我得到了以下错误:
“当“strict refs”被使用时,无法将字符串 (“Hello world”) 用作数组引用位于char_pos.pl第20行, line 1。”
我的代码如下。您可以在标题中看到文件的示例。您还可以看到原始输出代码,它错误地只显示了每个字符串中最右侧的字符。
#CodeEval challenge: https://www.codeeval.com/open_challenges/31/
#Call with $> char_pos.pl numbers
##Hello world, d
##Hola mundo, H
##Keyboard, b
##Connecticut, n

#!/usr/bin/perl
use strict;
use warnings;

my $path = $ARGV[0];

open FILE, $path or die $!;

my $len;

while(<FILE>)
{
    my @args = split(/,/,$_);
    $len = length($args[0]) - 1;
    print "$len\n";
    for(;$len >= 0; $len--)
    {
        last if $args[0][$len] == $args[1];
    }


    #if($len > -1)
    #{
    # print $len, "\n";   
    #}else
    #{
    # print "not found\n";   
    #}

}

编辑:根据下面的答案,我得到了可以运行的代码:

#!/usr/bin/perl
use strict;
use warnings;
use autodie;


open my $fh,"<",shift;

while(my $line = <$fh>)
{
    chomp $line;
    my @args = split(/,/,$line);
    my $index = rindex($args[0],$args[1]);

    print $index>-1 ? "$index\n" : "Not found\n";
}

close $fh;

5
如果你要比较字符串,请查看perldoc substr,而不是使用$args[0][$len],并使用eq - mpapec
使用 while (<>) { … } 代替显式打开文件等操作,这是更符合 Perl 的惯用法。在查看文档时(注意需要使用 perldoc -f substr 来按名称查找函数 substr),请同时查看 perldoc -f rindex。您可能需要使用 /, */ 进行分割,以允许在尾随字母之前加上空格。 - Jonathan Leffler
1
提示:您可能更喜欢使用 my ($word, $letter) = split(/,/,$_);@args 是一个相当糟糕的名称。 - ikegami
我倾向于避免在split中使用$_split(/,/);可以达到同样的效果。 - Sobrique
@ikegami - 我喜欢那种分割的方法。我会在以后记住的。谢谢! - Ben C.
3个回答

3
看起来你需要了解一些关于Perl函数的知译。Perl有许多用于字符串和标量的函数,不可能一下子就全部都掌握。
然而,Perl有一个很棒的函数叫做rindex,它恰好能够满足你的需求。你给它一个字符串,一个子字符串(在这种情况下,是单个字符),它会从字符串的右边开始查找该子字符串出现的第一个位置(index从左边开始执行相同的操作)。
既然你正在学习Perl,那么获取一些关于现代Perl和标准编码实践的书籍可能是个好主意。这样,你就可以了解到更新的编码技术和标准的编码实践。

以下是示例程序:

#!/usr/bin/perl

use strict;
use warnings;
use autodie;
use feature qw(say);

open my $fh, "<", shift;

while ( my $line = <$fh> ) {
    chomp $line;
    my ($string, $char) = split /,/, $line, 2;
    if ( length $char != 1 or not defined $string ) {
        say qq(Invalid line "$line".);
        next;
    }
    my $location = rindex $string, $char;
    if ( $location != -1 ) {
        say qq(The right most "$char" is at position $location in "$string".);
    }
    else {
        say qq(The character "$char" wasn't found in line "$line".)";
}
close $fh;

几个建议:

  • use autodie 允许您的程序在出现错误的 open 时自动退出。无需检查。
  • 现在认为三参数 open 语句是必须的。
  • 使用标量变量作为文件句柄。它们更容易传递到子例程中。
  • 循环使用词法范围变量。尽量避免使用 $_
  • 读取后始终执行 chomp

最重要的是,检查错误!我检查行的格式,确保只有一个逗号,并且我正在搜索的字符是字符。我还检查 rindex 的退出值,以确保它找到了该字符。如果 rindex 找不到该字符,则返回 -1

还要知道,一行中的第一个字符是 0 而不是 1。根据您期望的输出,您可能需要进行 调整


这太棒了。感谢您提供如此详尽的答案!我一定会查看那些资源。Perl不是我最喜欢的语言,但有清晰、详细的解释确实很有帮助。 - Ben C.

3
在perl中,字符串是基本类型,而不是可下标数组。要获取单个字符(它们也只是字符串)或从中获取子字符串,可以使用substr函数。
另外,请注意字符串比较使用eq进行;==用于数字比较。

0
while($i=<DATA>){
($string,$char)=split(",",$i);
push(@str,$string);}
@join=split("",$_), print "$join[-1]\n",foreach(@str);



__DATA__
Hello world, d
Hola mundo, H
Keyboard, b
Connecticut, n

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接