2015-12-07 2 views
1

Perl новичка. Попробуйте несколько строк кода до вручную отмените массив по символу и распечатайте его. (да, я знаю, что это может быть сделано с помощью обратной функции).Использовать push и pop для вспять и распечатать массив в Perl?

Для начала, у меня есть фиктивный файл с именем dummy.txt

abcdefg1234567890 

PERL скрипт My здесь:

#! /usr/bin/perl 
use strict; 
use warnings; 
use Data::Dumper; 

my $file = 'dummy.txt'; 
my @reverse_array; 

open (FH, '<', $file) 
    or die ("Couldn't open $file : $!"); 

#split with empty string to get individual characters 
my @chars = split("", <FH>); 

print "$#chars\n"; #prints 16, meaning there are 17 elements in @chars 
print "@chars\n"; #prints a b c d e f g 1 2 3 4 5 6 7 8 9 0 

for(my $i=0; $i <= $#chars; $i++) #iterate number of elements' times 
{ 
    push @reverse_array, pop @chars; #pop the elements out of @chars into @reverse_array 
} 

print "$#reverse_array \n"; #prints 8, meaning there are 9 elements in @reverse_array 
print "@reverse_array \n"; #prints 0 9 8 7 6 5 4 3 2, not as expected, but this is indeed 17 elements including the white space 

close (FH) 
    or die ("Failed to close $file: $!"); 

Так поп хлопает из пробельные. Итак, split добавляет пробелы, когда пытаюсь разбить его пустой строкой? Я все еще думаю, как обойти это. Мне понравился бы ваш вход, и изменить его на мой код было бы лучше для меня. Спасибо.

-Джек

+0

Другой вопрос, который у меня есть, при печати, почему $ # reverse_array НЕ обрабатывает пробелы как элемент массива, а @reverse_array DO обрабатывает пробелы как элемент? –

+3

Подумайте, что происходит с '$ # chars', поскольку вы' pop' элементы с конца '@ chars'. – ThisSuitIsBlackNot

+0

Вы используете 'Data Data Dumper' в своем коде. Если вы сбрасывали содержимое массива с помощью 'print Dumper \ @ reverse_array', вы могли бы увидеть истинное содержимое – Borodin

ответ

4

Это всегда предпочтительнее, чтобы перебрать список в Perl, а не с помощью уродливого C-стиля для цикла

Вашего цикл

for (my $i=0; $i <= $#chars; $i++) { 
    push @reverse_array, pop @chars; 
} 

эквивалентно

my $i = 0; 
while ($i <= $#chars) { 
    push @reverse_array, pop @chars; 
    ++$i; 
} 

поэтому $#chars начинается с 16. Цикл выполняется один раз, а теперь $i составляет 1, а $#chars - 15 из-за pop. Этот процесс будет продолжаться только после восьмой итерации цикла - когда $i равно 8, а $#chars равно 7, и теперь тест не работает, поэтому петля выходит из строя

Это приводит к тому, что вы меняете только последние восемь элементов @chars, как вы уже видели

Если вместо того, чтобы писать

for my $i (0 .. $#chars) { 
    push @reverse_array, pop @chars;  
} 

, то это не только яснее и проще читать, но и делает то, что вы собираетесь

Пробелы исходят из поведения Perl, когда строит массивов. Если вы пишете "@array\n", то Perl строит строку, содержащую элементы @array, разделенные одним пробелом. (Это поведение по умолчанию. Вы можете изменить строку, используемую для разделения элементов, но я советую вам не пойти туда еще.)

Для печати только содержимое массива, то вы можете написать

print @chars, "\n" 

, и вы увидите, что вы ожидаете

+1

Альтернативно, хотя вид гольфа:' push @reverse_array, pop @chars while @chars; ' –

+0

' map 'может быть уместным, так как вы делаете трансформацию рода:' my @reverse_array = map {pop @chars} 0 .. $ # chars; ' –

+2

@HunterMcMillen: Вы оба упускаете точку. Способ написать это «my @reverse_array = reverse @ chars». Упражнение теоретическое – Borodin

2

Ваша проблема заключается в том, что вы используете $#chars в вашей конструкции петли, и он меняется, как вы идете.Вы должны сохранить его первым:

use strict; 
use warnings; 

my $str = 'abcdefghijklmnopqrstuvwxyz'; 

my @reversed; 
my @chars = split //, $str; 

my $elt_count = scalar @chars; 

for (1 .. $elt_count) { 
    push(@reversed, pop @chars); 
} 

print @reversed; 

Но вы могли бы справиться с ней немного легче с while цикла:

use strict; 
use warnings; 

my $str = 'abcdefghijklmnopqrstuvwxyz'; 

my @reversed; 
my @chars = split //, $str; 

while (@chars) { 
    push(@reversed, pop @chars); 
} 

print @reversed; 

которая опирается на тот факт, что вы опорожнение @chars, как вы идете, и спасается, когда ничего не осталось.

Вы должны также быть в курсе - есть разница между:

print "@reversed"; 

и

print @reversed; 

В первом случае, Perl вставляет пробелы, потому что вы превратили массив в строку. Вот почему вы получаете видимое поведение, которое у вас есть.

Смежные вопросы