Легко для вашего дизайна. Вы можете разместить свою метку внутри панели. и установить фоновое изображение панели - это то, что вы хотите. установленный фон метки прозрачен
В большинстве целей Вы, вероятно, не заметите различия. Однако foreach
чтения каждая строка в список ( не массив ) перед прохождением через него линию за линией, тогда как while
чтения одна строка за один раз. Как foreach
будет использовать больше памяти и требовать времени обработки заранее, обычно рекомендуется использовать while
для итерации через строки файла.
РЕДАКТИРОВАНИЕ (через Schwern): foreach
цикл эквивалентен этому:
my @lines = <$fh>;
for my $line (@lines) {
...
}
неудачно, что Perl не оптимизирует этот особый случай, как это делает с оператором диапазона (1..10
).
, Например, если я считал/usr/share/dict/words с for
цикл и while
цикл и сделал, чтобы они спали, когда они сделаны, я могу использовать ps
для наблюдения, сколько памяти процесс использует. Как управление я включал программу, которая открывает файл, но ничего не делает с ним.
USER PID %CPU %MEM VSZ RSS TT STAT STARTED TIME COMMAND
schwern 73019 0.0 1.6 625552 33688 s000 S 2:47PM 0:00.24 perl -wle open my $fh, shift; for(<$fh>) { 1 } print "Done"; sleep 999 /usr/share/dict/words
schwern 73018 0.0 0.1 601096 1236 s000 S 2:46PM 0:00.09 perl -wle open my $fh, shift; while(<$fh>) { 1 } print "Done"; sleep 999 /usr/share/dict/words
schwern 73081 0.0 0.1 601096 1168 s000 S 2:55PM 0:00.00 perl -wle open my $fh, shift; print "Done"; sleep 999 /usr/share/dict/words
for
программа использует почти 32 megs реальной памяти (RSS
столбец) для хранения содержания моих 2.4 meg/usr/share/dict/words. while
цикл только хранит одну строку в трудоемком просто 70k для буферизации строки.
В дополнение к предыдущим ответам другое преимущество использования while
- то, что можно использовать $.
переменная. Это - текущий номер строки последнего дескриптора файла, к которому получают доступ (см. perldoc perlvar
).
while ( my $line = <FILE> ) {
if ( $line =~ /some_target/ ) {
print "Found some_target at line $.\n";
}
}
В скалярном контексте (т.е. while
) <FILE>
возвраты каждая строка в свою очередь.
В контексте списка (т.е. foreach
) <FILE>
возвращает список, состоящий из каждой строки из файла.
Необходимо использовать while
создать.
См. perlop - Операторы ввода-вывода для больше.
Править: j_random_hacker справедливо говорит это
while (<FILE>) { … }
топчет
$_
в то время как foreach не делает (foreach, локализует$_
сначала). Конечно, это - самое важное поведенческое различие!
Обновление: j случайный хакер указывает в комментарии что особые случаи Perl тест ошибочности в некоторое время цикле при чтении из дескриптора файла. Я только что проверил, что чтение ложного значения не завершит цикл - по крайней мере, на современном жемчуге. Извините за регулирование Вас неправильно. После 15 лет записи Perl я - все еще новичок.;)
Все выше правы: используйте while
цикл, потому что это будет большей эффективной памятью и даст Вам больше контроля.
А забавная вещь о том while
цикл, хотя то, что это выходит, когда чтение является ложью. Обычно это будет концом файла, но что, если он возвратит пустую строку или 0? Ой! Из Вашей программы просто выходят слишком скоро. Это может произойти на любом дескрипторе файла, если последняя строка в файле не имеет новой строки. Это может также произойти с пользовательскими объектами файла, которые имеют метод чтения, который не рассматривает новые строки тот же путь как регулярные объекты файла Perl.
Вот то, как зафиксировать его. Проверьте на неопределенное чтение значения, которое указывает на конец файла:
while (defined(my $line = <FILE>)) {
print $line;
}
foreach
цикл не имеет этой проблемы между прочим и корректен даже при том, что неэффективный.
j_random_hacker упомянул это в комментариях к этому ответу , но фактически не поместил его в ответ само по себе, хотя это еще одно отличие, о котором стоит упомянуть.
Разница в том, что while (
перезаписывает $ _
, а foreach (< FILE>) {}
локализует его. То есть:
$_ = 100;
while (<FILE>) {
# $_ gets each line in turn
# do something with the file
}
print $_; # yes I know that $_ is unneeded here, but
# I'm trying to write clear code for the example
распечатает последнюю строку
.
Однако
$_ = 100;
foreach(<FILE>) {
# $_ gets each line in turn
# do something with the file
}
print $_;
распечатает 100
. Чтобы получить то же самое с while (<
Я добавил пример, посвященный этому, в следующее издание Эффективное программирование на Perl .
С помощью while
вы можете остановить обработку ФАЙЛА
и по-прежнему получать необработанные строки:
while( <FILE> ) { # scalar context
last if ...;
}
my $line = <FILE>; # still lines left
Если вы используете foreach
, вы потребляете все строки в foreach
, даже если вы прекратите их обработку:
foreach( <FILE> ) { # list context
last if ...;
}
my $line = <FILE>; # no lines left!
Вот пример, где foreach
не будет работать, но , а
выполнит задание
while (<FILE>) {
$line1 = $_;
if ($line1 =~ /SOMETHING/) {
$line2 = <FILE>;
if (line2 =~ /SOMETHING ELSE/) {
print "I found SOMETHING and SOMETHING ELSE in consecutive lines\n";
exit();
}
}
}
Вы просто не можете сделать это с помощью foreach
, потому что он прочитает весь файл в список перед входом в цикл, и вы не сможете прочитать следующую строку внутри петли. Я уверен, что для этой проблемы найдутся обходные пути даже в foreach (на ум приходит чтение в массив), но определенно предлагает очень простое решение.
Второй пример - это когда вам нужно проанализировать большой (скажем, 3 ГБ) файл на вашем компьютере с оперативной памятью всего 2 ГБ. foreach
просто не хватит памяти и произойдет сбой. Я усвоил это на собственном горьком опыте в самом начале моей жизни программирования на Perl.
Цикл foreach выполняется быстрее, чем цикл while (который является условным).