Зачем использовать цикл for вместо цикла while? [дубликат]
Возможные Дубликаты:
итерация с циклом for или циклом while?
петли в C-for () или while () - что лучше?
когда следует использовать for
петли вместо while
петли?
Я думаю, что следующие циклы идентичны, за исключением их синтаксиса. Если так, то зачем выбирать одно вместо другого?
int i;
for (i = 0; i < arr.length; i++) {
// do work
}
int i = 0;
while (i < arr.length) {
// do work
i++;
}
28 ответов
в вашем случае вы не получаете много, кроме одной строки кода в for
петли.
однако, если вы объявите цикл так:
for(int i = 0; i < x; i++)
вам удается сохранить i
в пределах цикла, вместо того, чтобы позволить ему перейти к остальной части кода.
кроме того, в цикле while, у вас есть объявление переменной, условие и инкремент в 3 разных местах. С петлей for все это в одном удобном, удобном для чтения место.
последняя мысль:
Еще одно важное замечание. Между ними есть семантическое различие. В то время как циклы, как правило, должны иметь неопределенное количество итераций. (т. пока файл не был прочитан..независимо от того, сколько в нем строк), а для циклов должно быть более определенное количество итераций. (цикл через все элементы в коллекции, которые мы можем подсчитать на основе размера коллекции.)
есть одна причина, чтобы выбрать for
над while
: читабельность.
С помощью for
цикл, вы явно говорите, что ваше намерение состоит в выполнении некоторого типа операции, которая требует инициализации, операции "шаг" и условия завершения.
С while
, С другой стороны, вы только говорите, что вам нужно условие завершения.
Я использую "while", когда мне не обязательно нужен счетчик, например, когда вы читаете из файла, и вы ждете, чтобы достичь EOF. В этом случае " for " может быть не лучшей альтернативой. Когда вы просматриваете элементы массива, я бы предпочел использовать "для", Потому что он лучше передает намерение.
одно заметное различие между Для() и while() петли, что "продолжения" в цикле while() будет ветка в начале цикла, а в цикл for() выполняет переход к третьей части для() пункт [после состояние, как правило, используется, чтобы поднять переменные].
-
for
-петли для подсчета. подсчитать, обратный отсчет. -
while
/do-while
конструкции предназначены для всех других условий.c!=EOF
,diff<0.02
, etc. Итераторы / Перечислители-это счетчики, очень подходящие для for-loops.
т. е. int=0; while( ... )
отвратительно для моих глаз.
почему выберите Колу над Пепси?
между некоторое время и для цикла, вы можете использовать их взаимозаменяемо. Чтобы быть пуристом, вы могли бы принять решение на основе природы условий. Если вы выполняете цикл на основе подсчета, то цикл FOR будет иметь наибольший смысл.
for( cur = 0; cur < myList.Length; cur++ ){
doSomething( myList[cur] );
}
Если вы выполняете цикл на основе логики, то некоторое время будет для самой чистой реализации
Iterator i = myObject.getIterator();
while( i.hasNext() ){
doSomething( i.next() );
}
Как вы говорите, причины семантические и эстетические, а не производительность (их скомпилированный код, как правило, очень похож).
что сказал:for
обычно в циклах, которые имеют известное количество итераций, тогда как while
подразумевает, что условие не обязательно коррелирует с тем, что вы делаете внутри цикла, или что вы не знаете в начале, сколько итераций будет.
Как правило, я всегда предпочитаю для циклов, даже для случаев, когда цикл не имеет ничего общего с подсчетом, потому что он локализует обслуживание цикла в одном месте. Когда кто-то еще приходит и решает добавить/изменить цикл, если они используют цикл FOR, человек, делающий модификацию, обычно может быть уверен, что, пока они не связываются с элементами внутри выражения FOR, они не собираются прерывать итерацию в цикле.
однако, что-то как цикл while требует, чтобы программист полностью проанализировал тело цикла и понял, как он итерирует, чтобы убедиться, что они сохраняют код обслуживания цикла немодифицированным и в правильном порядке при внесении изменений.
Следовательно, Я только использовать в тех случаях, когда мне эффективно нужна только средняя часть для.
они функционально идентичны, однако можно утверждать, что цикл for менее подвержен ошибкам, потому что все функции цикла находятся прямо там вместе. если у вас есть несколько строк, разделяющих объявление i, объявление while и итератор индекса, вы можете забыть или запутаться в том, как он используется. Все это, конечно, субъективно.
в ранние времена программирования преобладающей структурой данных был линейный массив (он же вектор), и повторяющийся шаблон должен был пересекать и использовать каждый элемент массива. Этот сценарий был настолько обычным, что языки включали определенный синтаксис для этого шаблона: цикл for. Помимо этого исторического наследия вы можете использовать цикл while (ну, в настоящее время с функциональными языками, такими как F#, вы бы предпочли использовать List.карта или список.fold; -)
это в основном вопрос читабельности. Как правило, используйте для циклов, когда у вас есть определенный диапазон значений для итерации. Используйте циклы while, когда вы не повторяете или не знаете, когда ваше условие выхода будет истинным.
С точки зрения java, я нахожу для циклов очень удобным для коллекций:
for (Object o : objects){
o.process();
}
намного легче читать, чем:
int i=0;
while(i < objects.size()){
objects.get(i).process();
i++;
}
они обычно компилируются с тем же конечным результатом. Я предпочитаю за или за-каждый большую часть времени. Пишу
for (;x<5;x++){
//do work
}
не так зловеще, но писать
while(x<5){
x++
//do work
}
вместо
while(x<5){
//do work
x++
}
может запутать некоторых людей и вызвать ошибки off-by-one.
на языке, подобном Pascal, конструкции for и while имели разные приложения. Вы напишете цикл for В Pascal следующим образом:
for i := 1 to 5 do
begin
{ some code here }
end
Так, вы указываете, что I увеличивается на 1. Здесь явно не указано условие завершения. Таким образом, вы можете использовать цикл for только в тех местах, где вы знаете, что цикл будет выполняться определенное заранее определенное количество раз до начала фактического выполнения цикла. С другой стороны, можно указать точное условие завершения в случае цикла while.
i:=0;
while (i<>5) do
begin
{ some code here }
i:=i+1;
end
таким образом, цикл while намного более гибкий. Позже, когда C был разработан, хотя for и while поддерживались, значение конструкции for изменилось, и вы можете добавить явные условия завершения с помощью булевых операторов. Таким образом, сила while и for в C и C-подобных языках одинакова, и поэтому она становится больше проблемой читаемости, чем проблемой удобства использования.
взглянув на другие (очень хорошие) ответы, есть точка, которую я не видел. (Если это было сделано, я пропустил его и извинился.)
Я собираюсь дать вам два фрагмента, казалось бы, семантически идентичный код.
фрагмент #1:
for (int a = 0; a < arr.length; a++) {
/* do some work here */
}
фрагмент #2:
int b = 0;
while (b < arr.length) {
// do work
b++;
}
похоже, они делают то же самое, верно? Теперь позвольте мне добавить одну строку к каждому фрагменту и посмотрим, что произойдет:
фрагмент #3:
for (int c = 0; c < arr.length; c++) {
/* do some work here */
}
printf("%d\n", c);
фрагмент #4:
int d = 0;
while (d < arr.length) {
// do work
d++;
}
printf("%d\n", d);
поэтому, когда я компилирую мусорный файл с этими четырьмя фрагментами, встроенными (плюс немного клея, чтобы иметь arr.Длина что-то значит) я получаю следующую ошибку:
$ clang junk.c
junk.c:20:17: error: use of undeclared identifier 'c'
printf("%d\n", c);
^
1 diagnostic generated.
С помощью for
loop, оказывается, позволяет предоставить больше локальности для ваших фиктивных переменных счетчика и т. д. Это дает вам большую свободу действий при повторном использовании имен переменных без вероятности столкновения (хотя и за счет увеличения потенциала слежка.)
Как правило, разница между циклом while и циклом for связана с синтаксисом, а не с производительностью. Тем не менее, похоже, что этот вопрос уже был адресован для Java: в Java цикл for и цикл while. Разница в производительности?
читабельности. И от старого VB 6 дней венд всякий раз, когда я вижу, когда я хочу плакать.
есть несколько случаев, когда петли хороши для использования. Вызов функции для объекта, который возвращает true / false, но повторяет значение внутри этого объекта.
пример использования DataReader в C#:
List<string> strings = new List<string>();
while(DataReader.Read())
{
strings.Add(DataReader["foo"].ToString());
}
цикл for позволяет инкапсулировать вашу работу в функцию, что дает лучшее управление памятью. Кроме того, если есть ошибка в вашем while петля, она может спирально выйти из-под контроля, что угрожает всей жизни:
bool keepGoing = true;
while(keepgoing)
{
try
{
//something here that causes exception, fails to set keepGoing = false;
keepGoing = false;
}
catch(Exception)
{
//Do something, but forget to set keepGoing.
//maybe there is always an exception...
}
}
Я тоже думаю, что это просто общая практика. Как в строительстве. Вы используете гвозди для установки кровельных квартир на шпильки. Вы" можете " использовать винты, они будут делать ту же работу, но это просто не обычная практика.
никто не говорит, что это неправильно, мы просто говорим: "Пожалуйста, сложите под давлением ваших сверстников, чтобы сохранить функционирование мира кодирования".
существует семантическая разница между for
и while
петли. С for
циклы, количество итераций предварительно определено, тогда как с while
петли не надо.
некоторые языки (например, Ada) обеспечивают это, делая for
счетчик циклов константа внутри тела цикла. Следовательно, было бы незаконно говорить, например:
for i in values'range loop
...
i := i + 1; -- this is illegal, as i is a constant within the loop body
end if;
это семантическое различие, однако, не так ясно с большинством языков, которые не относятся к for
счетчик циклов как константа.
просто решите один, а затем скопируйте и вставьте / отрегулируйте его в своих проектах. Меньше решений, меньше набора текста, быстрее кодирование. Незначительная разница в производительности.
также я не с Джастином keeping i
в области цикла, и я использую
var aL = array.length
вне цикла тоже. Тогда используйте i
и aL
внутри for
конструктор цикла, поэтому вы не пересчитываете длину массива при каждом попадании (вместе с созданием var снова и снова ;)). Снова НЭГ. производительность действительно (см. Первый БИТ моего ответа), если у вас нет очень больших массивов, летающих вокруг. Если вы знаете длину массива заранее, сначала инициируйте его с фиксированной длиной (небольшая помощь с выделением памяти в дерьмовых браузерах ;), если это клиентская сторона, и у вас много данных).
в JS пример
<script>
var i=0;
var myArray = ["D","R","Y"];//literal style will do for now;)
var aL=myArray.length; //or use 3 if known upfront
for(i;i<aL;i++){/*always do DRY things here*/}
</script>
также убедитесь, когда условие выполнено, спросите себя: "мне все еще нужно завершить весь цикл?"Если нет, не забудьте вырваться из петли, как как можно раньше.
сопутствующие мелочи:
в новом Google идем язык, они решили не включать пока заявление. Вместо этого они позволяют вам написать на сообщении это имеет только условие. Таким образом, эквивалент
while (a < b) { ... }
просто
for a < b { ... }
проще говоря:
цикл " for " имеет тенденцию использоваться для итерационного использования. Вам нужно перебирать массив, вам нужны числа от 1 до 100 (или другие диапазоны) по разным причинам.
цикл "while" имеет тенденцию быть условным циклом. Вы хотите продолжать что-то делать, пока contition является ложным. Предположим, у вас есть класс под названием "тост" , и вы хотите приготовить тост, пока он не будет поджарен, у вас будет что-то вроде следующий:
while (!toast.isToasted) cook(toast);
вы всегда можете (я не могу придумать пример, где вы не можете) написать цикл for как цикл while и цикл while как цикл for, но выбирая тот, который лучше всего сначала, ситуация обычно сводится к моим выше пунктам.
читаемость-очень важный момент, но он работает в обоих направлениях. Я преобразую for-loop в while-loop-даже когда я использую переменную счетчика или иначе было бы "естественно" использовать для-Когда это более читаемо таким образом. Это обычно, когда у вас есть длинное или сложное выражение в любой из трех частей for или нескольких счетчиков (что связано с комплексом).
петля-полтора кнута также работает лучше, на нескольких языках, как бесконечный цикл с перерывом, а не с петлей.
однако существует очень важное семантическое различие:
for (int i = 0; i < arr.length; i++) {
if (filter(arr[i])) continue;
use(arr[i]);
}
int i = 0;
while (i < arr.length) {
if (filter(arr[i])) continue;
use(arr[i]);
i++;
}
используйте for-loop, когда это уместно. Решение while имеет синтаксические недостатки (оно длиннее), и вы должны проверить, что вы увеличиваете i перед любым вызовом continue в цикле.
предпочтения. Для меня вся логика цикла встроена в оператор for, поэтому вам не нужно объявлять переменную счетчика или делать материал инкремента/декремента в фактическом цикле. Кроме того, вы можете объявить счетчик/указатель локального оператора for.
для циклов часто легче распараллелить. Поскольку программа может заранее сказать количество итераций, которые будут выполнены, и значение итератора в любой момент, распараллеливание с помощью API, такого как OpenMP, тривиально. Конечно, если вы попадаете в перерывы, продолжается, и изменение итератора вручную это преимущество исчезает.
одна из причин заключается в том, что условие while может быть строкой.
кроме того, если мы добавим " Do " в микс, мы можем использовать цикл do while, когда мы хотим, чтобы операция выполнялась хотя бы один раз независимо от ее текущего состояния.
Это просто моя логика, которую мы обычно используем для цикла, когда мы знаем точное количество наших итераций, и мы используем цикл while, когда мы обычно хотим проверить условие.Затем мы используем их в соответствии с требованиями ur. В противном случае они оба ведут себя одинаково.
цикл while, определенный как
while(condition)
представляет этот шаблон программирования:
1:
if(!condition) goto 2;
...
goto 1;
2:
тогда как цикл for, определенный как
for(var i = seed; condition; operation)
представляет структуру:
var i = seed
1:
if(!condition) goto 2;
...
operation;
goto 1;
2:
оба шаблона настолько часто используются, что они были названы и встроены в языки.
Если вам нужно определить счетчик для управления циклом, используйте цикл for. Если нет, используйте цикл while.