2013-11-27 4 views
1

Я только что взял на себя обслуживание части системы Perl. Машина, с которой она работала, мертва, поэтому я не знаю, какую версию Perl она использовала, но она работала. Она включала в себя следующую строку для подсчета строк в странице ASCII текста

my $lcnt = $#{@{$page{'lines'}}}; 

В Perl 5.10.1 (мы сейчас работаем это на CentOS 6.3) выше код больше не работает. Вместо этого я использую следующее, которое отлично работает.

my @arr = @{$page{'lines'}}; 
my $lcnt = $#arr; 

Я признаю, мой Perl не велик, но от того, что я могу видеть первый вариант никогда не должен был сработать, как это пытается почтительным массив, а не реф массив

Первого вопроса - это моя догадка о том, почему эта первая строка кода теперь не работает правильно, а во-вторых, она работает раньше из-за исправленной ошибки в предыдущей версии Perl?

Спасибо!

+0

$ # дает вам последний индекс массива ... если ваш массив содержит строки, $ # arr - количество строк -1. здесь вы должны рассмотреть использование скаляра, который возвращает количество элементов в массиве. – Pierre

+0

- это '$ page {'lines'}' массив или ссылка на один? –

+0

Что означает «больше не работает»? Исходный код не является синтаксической ошибкой - что он делает сейчас (я бы догадался, что он возвращает -1), что он сделал, и как вы знаете? – pilcrow

ответ

3

Первая версия не работала. Предполагая, что $page{'lines'} является ссылкой на массив, это то, что вы хотите:

my $lcnt = $#{$page{'lines'}}; 

Обратите внимание, что это собирается дать вам один меньше, чем количество элементов в вашем arraref. Оператор $# является ИНДЕКСОМ последнего элемента, а не количеством элементов. Если вы хотите, чтобы количество элементов в $page{'lines'}, вы, вероятно, хотите:

my $lcnt = scalar(@{$page{'lines'}}); 
+0

Использование 'scalar()' в скалярном назначении является избыточным. Но +1 для правильного ответа. – TLP

+0

@TLP благодарим вас за комментарий. Хотя вы технически корректны, я решил использовать scalar() в этом случае, чтобы сделать мое намерение явным. С наилучшими пожеланиями. – codnodder

1

Некоторые вещи о вашем коде. Это:

my $lcnt = $#{@{$page{'lines'}}}; 

Не всегда правильно. Посмотрите на три вещи здесь происходит

$page{'lines'} # presumably an array ref 
@{ ... }   # dereference into an array 
$#{ ... }  # get last index of an array ref 

Это эквивалентно (продолжая свой собственный код):

my @arr = @{$page{'lines'}}; 
my $foo = @arr;     # foo is now the size of the array, e.g. 3 
my $lcnt = $#$foo; 

Если вы используете

use strict; 
use warnings; 

Что вы должны всегда делаю, без вопросов (!), Вы получите информативное фатальное сообщение об ошибке:

Can't use string ("3") as an ARRAY ref while "strict refs" in use 

(Где 3 будет размером вашего массива)

правильный способ получить размер (количество элементов) из массива является поместить массив в скалярном контексте:

my $size = @{ $page{'lines'} }; 

способом получить индекс последнего элемента с помощью $# сигила:

my $last_index = $#{ $page{'lines'} }; 

Как вы можете заметить, синтаксис такого же, это всего лишь вопрос использования @ или $#, чтобы получить то, что вы хотите, так же, как при использовании обычного массива

my $size = @array; 
my $last = $#array; 

Итак, для возврата к началу: Использование как@, так и $# не является и никогда не было правильным.

+0

Фактически он работал * в прошлом (проверен на 5.8.8), возможно, через ту же странность, что и '@arr -> [2]' синонимично с '$ arr [2]'. Но это, конечно, никогда не было правильным *. – hobbs

+0

Это действительно странно. – TLP

+0

@hobbs Поскольку вы тот, у кого есть ответ, ему нравится больше всего, возможно, вам следует отправить ответ, который он может принять. – TLP

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