2016-06-01 2 views
2

Я пытаюсь прочитать файл,оператора, чтобы читать с помощью файла дескриптора файла

while($line = $file_handle) 

Когда я запустил этот код, программа зависла.

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

while($line = <file_handle>) 

Поздний код явно бежал.

Теперь я знаю, что оператор <> должен прочитать файл по строкам, я хочу знать, что именно происходит, когда я не предоставляю оператора <>? Не может ли он найти конец линии? Или?

Thankyou

+0

Без '<>' вы делаете копию '$ file_handle' в' $ line' –

ответ

1

Короткие   Файл считывается оператором <>, поэтому без него это только задание, таким образом, бесконечный цикл.


В while (...) { ... } проверяет состояние внутри () и если это верно выполняет тело в блоке {}. Он продолжает делать это до тех пор, пока условие в () не будет оценено как ложное (обычно 0, '0', '' или undef). Это то, что оператор <> обеспечивает, например, таким образом, мы имеем идиом

while (my $line = <$file_handle>) { ... } 

Оператор <> считывает строку на каждую итерацию из ресурса, который $file_handle связан с и когда она достигает окончание срока файла он возвращает undef, поэтому цикл завершается, и выполнение программы продолжается после следующего цикла после цикла. Оператор алмаза <> является формой оператора для функции readline. См. I/O Operators in perlop. Для этого необходимо, чтобы $file_handle был действительным ресурсом, который может извлекать данные.

Без оператора <> ничего не читается нигде, но есть только задание. Код делает следующее. Он копирует переменную $file_handle в переменную $line. Возвращаемое значение этой операции в Perl - это значение, которое заканчивается в $line, и если это «истинное» значение, тогда выполняется тело { ... }. $file_handle явно оценивает значение «true», иначе тело цикла не будет выполняться ни разу, и программа продолжит работу. Таким образом, верно и $line. Поэтому, если $file_handle не изменяется в теле {...} цикла, условие всегда верно.

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


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

while (1) { 
    # Compute what is needed 
    # Recalculate the condition for when to stop 
    last if $condition_to_terminate; 
} 

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

Совершенно другой пример представляет собой цикл события, где важно, чтобы войти в бесконечный цикл, так что мы можем ждать события каких-то, на котором отсчитываются определенное действие. Вот как работает графический интерфейс, например, и ряд других систем.

0

Для примера, что 'висело':

while($line = $file_handle) 

Элементы $line = $file_handle чисто присваивание. В этот момент ваш while просто проверяет, что присвоение является правдивым, то есть $line не является числом 0, строкой 0, пустой строкой или undef, что, конечно же, не является -> hense вы получаете бесконечный цикл.

+3

«ваше время просто проверяет, произошло ли задание». Фактически, это проверка того, что возвращаемое значение оператора скалярного присваивания является правдивым, т.е. '$ line' не является числом 0, строкой 0, пустой строкой или' undef'. – ThisSuitIsBlackNot

+0

Правда. Спасибо, что исправил меня –

3

Учитывая этот код:

use warnings; 
use strict; 

open my $fh, '<', 'in.txt' or die $!; 

while (my $x = $fh){ 
    $DB::single=1; 
    print "$x\n"; 
} 

при запуске в отладчике, вы можете увидеть, что $x теперь содержит GLOB (копию дескриптора файла). На каждой итерации $x воспринимает весь дескриптор как назначение и вызывает бесконечный цикл, потому что утверждение всегда верно. Поскольку вы всегда назначаете истинное значение (дескриптор), оператор while фактически не отличается от записи while(1){....

perl -d script.pl 

main::(x.pl:4):  open my $fh, '<', 'in.txt' or die $!; 
    DB<1> s 
main::(x.pl:6):  while (my $x = $fh){ 
    DB<1> s 
main::(x.pl:7):   $DB::single=1; 
    DB<1> x $x 
0 GLOB(0xbfdae8) 
    -> *main::$fh 
     FileHandle({*main::$fh}) => fileno(6) 
    DB<2> s 
main::(x.pl:7):   $DB::single=1; 
    DB<2> x $x 
0 GLOB(0xbfdae8) 
    -> *main::$fh 
     FileHandle({*main::$fh}) => fileno(6) 

<$fh> по существу извлекает одну строку из дескриптора файла, и когда EOF поражен (или произойдет ошибка), возвращает undef, который завершает цикл (потому что undef ложно).

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