2016-10-15 83 views
-1

作爲一名生物學學生,我試圖擴展自己的編程知識,並遇到了一個Perl問題。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; 
+0

包裝邏輯功能。明碼是你知道的一塊***。評論可以幫助,但請閱讀功能。而且,命名規則也很糟糕。你應該使用s_n_a_k_e或cAmEl的情況。 – gaussblurinc

+0

你沒有範圍你的變量。 –

+1

任何未聲明的變量都是全球性的,包括任何拼寫錯誤。這是一個不幸的Perl默認。打開'use strict'和'use warnings',然後通過確定所有這些變量範圍的過程。這很難,但如果你現在不這樣做,它只會變得更糟。 – Schwern

回答

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新名稱爲每個新的循環

+0

謝謝您提供的所有提示。這是我第一次嘗試用Perl編寫任何東西。 – armorlord

+1

@armorlord:不客氣。但是我認爲你在Perl上的第一次嘗試已經過度了。你試圖實現的最長的公共子序列算法本身非常笨拙,而在沒有對該語言的全面瞭解的情況下打擊這種算法是一個很大的問題。你應該通過優秀的[learn.perl.org](http://learn.perl.org),它也有其他有用資源的鏈接。核心Perl文檔在同一個網站上[perdoc.perl.org](http://perldoc.perl.org)在線,並且是非常寶貴的。 – Borodin

5

我認爲你必須在你的代碼一個錯字:

ii =>必須$ii

不要忘了把這個在你的代碼的開頭:

use strict; 
use warnings; 

爲了避免這種(和其他)類型的錯誤