2015-04-16 2 views
0

Я беру учебник Perl и несколько озадачен о том, как перебрать массив при вызове библиотекиПеребор массива в Perl

Библиотека должна содержать функцию, которая принимает в массив чисел (произвольных размер). Затем функция вычисляет среднее число чисел, общее количество всех добавленных чисел и новый массив чисел, который состоит из исходных номеров ввода, каждый из которых разделен на 2. Затем он будет возвращать новый список со всеми эта информация.

Файл сценария должен получить список номеров от пользователя через STDIN, вызвать библиотечную функцию и распечатать возвращенные номера.

До сих пор у меня есть это в основном скрипте:

#!/usr/local/bin/perl 

    require 'test4lib.pl'; 

    my @numbers; 

    while (<>) { 
     s/\s+\z//; 
     last if $_ eq ""; 
     push @numbers, $_; 
    } 
    print "My Numbers are: @numbers\n"; 
    number_crunch(@numbers); 

    print "Total is: $total\n"; 
    print "Average is: $Average\n"; 
    print "Divided by 2 is: @divided_by\n"; 

и это в библиотечной функции:

sub number_crunch { 
    foreach $number(@_) { 
     $total = $sum+=$_ for (@_); 
     $count = $numelements=(@_); 

     $Average = ($total/$count); 
     print "Total is: $total\n"; 
     $Average = ($total/$count); 
     print "Average is: $Average\n"; 

     @divided_by =(); 
     foreach (@_) { 
     $new_number = $_/2; 
     push @divided_by, $new_number; 
     } 
    } 
    } 
    1; 

Вопрос заключается в том, что функция в библиотеке только захватывая первый номер из массива, и я не уверен, как проходить через массив. Любая помощь оценивается.

Бекки

+2

добро пожаловать в stackoverflow. Стандартным советом для perl является использование строгого; предупреждения использования; ' – KeepCalmAndCarryOn

+1

В этом есть много ошибок. Вы перебираете все пройденные числа, передавая текущий в '$ number', но никогда не используете эту переменную, затем пытаетесь вычислить' $ total' всех чисел в этом цикле, но для этого вы используете что-то, называемое '$ sum', которое вы никогда не устанавливаете, вы вычисляете '$ average' дважды за каждое число (так как вы все еще в цикле) и т. д. ... Вам нужно сделать шаг назад и подумать о потоке вашего суба, прежде чем переписывать его. И да, никогда не пишите perl-скрипт без 'strict' и' warnings', пока вы действительно не поймете, что делаете. Я бы сказал, даже не тогда, но это я. – DeVadder

ответ

0

Как я объяснил в моем комментарии в коде есть другие вопросы, но позвольте мне еще ответить на ваш вопрос о том, как можно передать массив в подпрограмму правильно.

Ваш путь только используя массив в качестве аргумента и прямого доступа к @_ делает на самом деле работы, до тех пор, как вы хотите только передать один массив:

use strict; 
use warnings; 

my @array = (1, 2, 3); 

foo(@array); 

sub foo 
{ 
    foreach my $num (@_) 
    { 
     print "$num\n"; 
    } 
} 

Однако то, что на самом деле происходит здесь является то, что ваш массив преобразуется в список и передается, а содержимое этого списка хранится в @_. Это быстро становится проблемой, если вы хотите передать два массива неизвестной длины, которые вам нужно различить в вашем суб, поскольку все их элементы будут просто следовать друг за другом в @_.

Чем лучше практика при прохождении массивов (или хэшей или что-нибудь на самом деле), чтобы подлодки использует ссылки:

use strict; 
use warnings; 

my @array = (1, 2, 3); 

foo(\@array); 

sub foo 
{ 
    my @passedArray = @{$_[0]}; #Interpret the reference passed to us first as an array 
    foreach my $num (@passedArray) 
    { 
     print "$num\n"; 
    } 
} 

В этом случае я скопировать массив как первое, в суб. Я сделал это здесь, чтобы сделать его более читаемым, но он также служит цели безопасности. Поскольку это передается по ссылке, если вы должны были непосредственно работать с @{$_[0]} и изменять его, эти изменения также отображались бы в @array вне суб. Конечно, во многих случаях это именно то, что нужно. Сравнить:

use strict; 
use warnings; 

my @array = (1, 2, 3); 

square(\@array); 

foreach my $num (@array) 
{ 
    print "$num\n"; 
} 

sub square 
{ 
    foreach my $num (@{$_[0]}) 
    { 
     $num *= $num; 
    } 
} 
+3

Пожалуйста, не поощряйте людей к вызовам подпрограмм, используя '&'. Он не был необходим в течение двадцати лет, и он может потенциально запутать побочные эффекты. –

+0

Я не понимаю, что вы подразумеваете под «не выдавать предупреждение». Нет никаких случаев, когда 'foo()' создает предупреждение, но '& foo()' не делает. '&' просто не нужно при вызове подпрограммы, поэтому она становится бессмысленной пунктуацией, которая просто путает программистов, которые раньше этого не видели. Прототипы не имеют к этому никакого отношения. У большинства подпрограмм не должно быть прототипов. «Потенциально запутывающие» побочные эффекты - это когда вы вызываете '& foo' (что для большинства людей не так сильно отличается от' & foo() '), а Perl передает' foo' текущее значение '@ _', а не пустое массив. –

+0

Ох. Я вижу, что у вас есть:) удалил комментарий, на который я только что ответил, и b) удалил амперсанды. Спасибо. –

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