在Perl中确定范围

时间:2016-10-15 18:48:45

标签: perl scoping

作为一名生物学专业的学生,​​我正在尝试扩展我的编程知识,并且遇到了Perl的问题。

我正在尝试创建一个生成随机DNA字符串的程序,并对生成的数据执行分析工作。

在程序的第一部分中,我能够打印出存储在数组中的字符串,但第二部分我无法检索除数组中的一个元素之外的所有字符串。

这可能是Perl范围规则的一部分吗?

#!usr/bin/perl

# generate a random DNA strings and print it to file specified by the user.

$largearray[0] = 0;

print "How many nucleotides for the string?\n";
$n      = <>;
$mylong = $n;

print "how many strings?\n";
$numstrings = <>;

# @largearray =();
$j = 0;

while ( $j < $numstrings ) {

    $numstring = '';    # start with the empty string;
    $dnastring = '';
    $i         = 0;

    while ( $i < $n ) {

        $numstring = int( rand( 4 ) ) . $numstring;    # generate a new random integer
                                                       # between 0 and 3, and concatenate
                                                       # it with the existing $numstring,
                                                       # assigning the result to $numstring.
        $i++;                                          # increase the value of $i by one.
    }

    $dnastring = $numstring;
    $dnastring =~ tr/0123/actg/;                       # translate the numbers to DNA characters.
                                                       #print $dnastring;
                                                       #print "\n";

    $largearray[j] = $dnastring;                       #append generated string to end of array

    #print $largearray[j];
    #print $j;
    #IN HERE THERE ARE GOOD ARRAY VALUES
    #print "\n";

    $j++;
}

# ii will be used to continuously take the next couple of strings from largearray
# for LCS matching.

$mytotal = 0;
$ii      = 0;

while ( $ii < $numstrings ) {

    $line = $largearray[ii];
    print $largearray[ii];    #CANNOT RETRIEVE ARRAY VALUES
    print "\n";

    $ii++;
    @string1 = split( //, $line );

    $line = $largearray[ii];

    #print $largearray[ii];
    #print "\n";
    $ii++;
    chomp $line;
    @string2 = split( //, $line );

    $n = @string1;    #assigning a list to a scalar just assigns the
                      #number of elements in the list to the scalar.
    $m = @string2;

    $v  = 1;
    $Cm = 0;
    $Im = 0;

    $V[0][0] = 0;     # Assign the 0,0 entry of the V matrix

    for ( $i = 1; $i <= $n; $i++ ) {    # Assign the column 0  values and print
                                        # String 1  See section 5.2 of Johnson
                                        # for loops
        $V[$i][0] = -$Im * $i;

    }

    for ( $j = 1; $j <= $m; $j++ ) {    # Assign the row 0 values and print String 2
        $V[0][$j] = -$Im * $j;

    }

    for ( $i = 1; $i <= $n; $i++ ) {    # follow the recurrences to fill in the V matrix.
        for ( $j = 1; $j <= $m; $j++ ) {

            #   print OUT "$string1[$i-1], $string2[$j-1]\n"; # This is here  for debugging purposes.

            if ( $string1[ $i - 1 ] eq $string2[ $j - 1 ] ) {
                $t = 1 * $v;
            }
            else {
                $t = -1 * $Cm;
            }

            $max = $V[ $i - 1 ][ $j - 1 ] + $t;

            #  print OUT "For $i, $j, t is $t \n"; # Another debugging line.
            if ( $max < $V[$i][ $j - 1 ] - 1 * $Im ) {
                $max = $V[$i][ $j - 1 ] - 1 * $Im;
            }

            if ( $V[ $i - 1 ][$j] - 1 * $Im > $max ) {
                $max = $V[ $i - 1 ][$j] - 1 * $Im;
            }

            $V[$i][$j] = $max;
        }
    }    #outer for loop

    print $V[$n][$m];
    $mytotal += $V[$n][$m];    # append current result to the grand total
    print "\n";

}    # end while loop

print "the average LCS value for length ", $mylong, " strings is: ";
print $mytotal/ $numstrings;

2 个答案:

答案 0 :(得分:9)

这不是一个范围问题。您没有声明任何变量,这会隐式地使它们全局化并且可以在代码中的任何位置访问

我重新格式化了您的Perl程序,以便我可以阅读它,然后将其添加到程序的顶部

use strict;
use warnings 'all';

在您编写的每个Perl程序中必需

然后我添加了

no strict 'vars';

这是非常糟糕的主意,让您在不声明任何变量的情况下逃脱

结果就是这个

Argument "ii" isn't numeric in array element at E:\Perl\source\dna.pl line 60.
Argument "ii" isn't numeric in array element at E:\Perl\source\dna.pl line 61.
Argument "ii" isn't numeric in array element at E:\Perl\source\dna.pl line 67.
Argument "j" isn't numeric in array element at E:\Perl\source\dna.pl line 42.
Bareword "ii" not allowed while "strict subs" in use at E:\Perl\source\dna.pl line 60.
Bareword "ii" not allowed while "strict subs" in use at E:\Perl\source\dna.pl line 61.
Bareword "ii" not allowed while "strict subs" in use at E:\Perl\source\dna.pl line 67.
Bareword "j" not allowed while "strict subs" in use at E:\Perl\source\dna.pl line 42.
Execution of E:\Perl\source\dna.pl aborted due to compilation errors.

第42行(我的重新格式化版本)是

$largearray[j] = $dnastring

和第60,61和67行是

$line = $largearray[ii];
print $largearray[ii];    #CANNOT RETRIEVE ARRAY VALUES

$line = $largearray[ii];

您使用jii作为数组索引。那些是Perl子程序调用,而不是变量。添加use strict会阻止编译,除非您还声明了sub iisub j

如果您只是将jii更改为$j$ii可能会侥幸成功,但您肯定会得到进一步的问题

请对您自己的代码进行相同的更改,使用my声明所需的每个变量尽可能接近它们使用的第一个位置

您还应该改进变量命名。 @largearray之类的内容毫无意义:@表示它是一个数组,无论它是否大都是相对的,对理解你的代码几乎没用。如果您对其目的没有更好的描述,那么@table@data可能会更好一些

同样,请避免使用大写字母和大多数单字母名称。 @V$Cm$Im毫无意义,如果这些名称更好,您需要更少的评论

如果您已正确缩进块并保持其足够短以便可以在屏幕上看到开头和结尾,那么您肯定不需要# end while loop# outer for loop之类的注释与此同时,你可以用更好的方式获得更少的评论,因为它们严重混乱了代码结构

最后,值得注意的是,C风格的for循环很少是Perl的最佳选择。您的

for ( $i = 1; $i <= $n; $i++ ) { ... }

更清晰

for my $i ( 1 .. $n ) { ... }

并在此时声明控制变量,因此无需为每个新循环创建$ii等新名称

答案 1 :(得分:5)

我认为您的代码中有拼写错误:

ii =&gt;必须是$ii

不要忘记把它放在代码的开头:

use strict;
use warnings;

为了避免这种(以及其他)的错误