いくつかのこと:
- プラグマ
use strict;
とを使用しますuse warnings;
。これらは多くのエラーをキャッチします。を使用する場合use strict;
は、変数を で宣言する必要がmy
あります ( を使用することもありますがour
、99% の場合は を使用しますmy
) 。
- ループでは、
for
デフォルトの変数を使用しています$_
。この変数は、さまざまな理由で悪です。(1つは、スコープがグローバルであるため、他の何かがこの変数を変更する可能性があり、わかりません。)を使用する必要がある場合を除き、変数を宣言します$_
。
- 標準では、と を
{
並べて配置します。もう 1 つは、for ループを回避することです (そして、これが単なるエイリアスであることを回避します) 。for
while
C style
foreach
for
- スペースを使用します。
$i <= $#a
よりもはるかに読みやすいです$i<=$a
。
あなたのプログラムの私の解釈は次のとおりです。
#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say); #A nicer 'print'
my @a = qw(12 13 14 15 16 17 18 19 20);
my @even;
my @odd;
for my $element (0..$#a) {
if ( $element % 2 ) {
push @odd, $a[$element];
}
else {
push @even, $a[$element];
}
}
say '@even = ' . join ': ', @even;
say '@odd = ' . join ': ', @odd;
出力:
@even = 12: 14: 16: 18: 20
@odd = 13: 15: 17: 19
for
私のループに注意してください。を使用し0..$#a
て、配列の各要素を調べます。is は、配列の最後の$#
インデックスを返します。これは、使用した よりも理解しやすいことに注意してfor($i=0;$i<=$#a;$i++)
ください。これが、C スタイルの for ループが推奨されない理由の 1 つです。
- モジュロ演算子を使用して
%
、偶数/奇数を解析します。Modulo は剰余除算のようなものです。数値が奇数の場合、モジュロ% 2
は 1 になります。それ以外の場合はゼロです。モジュロ演算は、サイクルで機能するものすべてに最適です。
しかし、プログラムに戻りましょう。これは、いくつかの微調整を加えた元のコードです。
- と を追加しまし
use strict;
たuse warnings;
。これらは、プログラミング エラーの約 99% をキャッチします。
- デバッグに関しては、より良い
use feature qw(say);
ので使用します。say
ステートメントを取得してコピーし、そのqq(...);
周りに言葉を投げかけて、それが何をしているかを確認できます。
say
コードのロジックを明らかにするために、一連のステートメントを追加しました。
何が起こるか見てみましょう。少し変更したプログラムは次のとおりです。
#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
my @b;
my @a = (1,2,3,4,5,6,7,8,9,10);
my $i;
for($i=0; $i<=$#a; $i++) {
say "Index = $i Element = $a[$i + 1]";
say qq(push(\@b, $a[$i+1]););
push(@b,$a[$i+1]);
}
print "@b";
出力は次のとおりです。
Index = 0 Element = 2
push(@b, 2);
Index = 1 Element = 3
push(@b, 3);
Index = 2 Element = 4
push(@b, 4);
Index = 3 Element = 5
push(@b, 5);
Index = 4 Element = 6
push(@b, 6);
Index = 5 Element = 7
push(@b, 7);
Index = 6 Element = 8
push(@b, 8);
Index = 7 Element = 9
push(@b, 9);
Index = 8 Element = 10
push(@b, 10);
Use of uninitialized value in concatenation (.) or string at ./test.pl line 11.
Index = 9 Element =
Use of uninitialized value within @a in concatenation (.) or string at ./test.pl line 12.
push(@b, );
Use of uninitialized value $b[9] in join or string at ./test.pl line 15.
各ステートメントがどのようpush
に実行されているかを見ることができます。それを見ると、すべての要素を押し込んでいます。実際、あなた$a[$i+1]
がプッシュしているものとして使用したからではありません。
を使用すると、存在しないものを配列use warnings
にプッシュしようとしていることがわかります。$a[10]
@b
for
ループを変更して、他のすべての要素に移動しましょう
#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
my @b;
my @a = qw(1 2 3 4 5 6 7 8 9 10);
my $i;
for ($i=0; $i <= $#a; $i += 2) {
push @b, $a[$i];
}
最初の要素は$a[0]
. ループ内の次の要素は、単にインクリメントするのではなく、インデックス$a[2]
に追加したためです。ここで、すべての偶数要素を調べて、すべての奇数要素をスキップします。2
1
そして出力:
1 3 5 7 9
12
($a[0] = 1 であることに注意してください。これが、すべて奇数であることに注意してください。これが、プログラムで開始した理由であり、偶数である $a[0] = 12 です)。
私の好みは、構造を使用しwhile
て回避するfor(...; ...; ...)
ことです。
#! /usr/bin/env perl
use strict;
use warnings;
use feature qw(say);
my @b;
my @a = qw(1 2 3 4 5 6 7 8 9 10);
my $i = 0;
while ( $i < $#a ) {
push @b, $a[$i];
$i += 2;
}