Зачем использовать цикл 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 66

28 ответов:

в вашем случае вы не получите много, кроме одной строки кода в for петли.

однако, если вы объявите цикл так:

for(int i = 0; i < x; i++)

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

кроме того, в цикле while, у вас есть объявление переменной, условие и инкремент в 3 разных местах. С петлей for все это в одном удобном, удобном для чтения место.

последняя мысль:
Еще одно важное замечание. Между ними существует семантическая разница. В то время как циклы, в общем случае, должны иметь неопределенное количество итераций. (т. пока файл не был read..no неважно, сколько в нем строк), а для петель должно быть более определенное количество итераций. (цикл через все элементы в коллекции, которые мы можем рассчитывать на основе размера коллекции.)

есть одна причина, чтобы выбрать for over while: читабельность.

С помощью for цикл, вы явно говорите, что ваше намерение состоит в том, чтобы выполнить некоторый тип операции, которая требует инициализации, операции "шаг" и условия завершения.

С while, С другой стороны, вы только говорите, что вам нужно условие завершения.

Я использую 'while', когда мне не обязательно нужен счетчик, например, когда вы читаете из файла, и вы ждете, чтобы достичь EOF. В этом случае " for " может быть не лучшей альтернативой. Когда вы просматриваете элементы в массиве, я бы предпочел использовать "для", Потому что он лучше передает намерение.

единственное заметное различие между циклом for() и while() заключается в том, что оператор "continue" в цикле while() будет ветвиться в верхней части цикла, в то время как один в цикле for() будет ветвиться в третью часть предложения for () [тот, который после условия, обычно используется для изменения переменных].

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

  • for-петли для подсчета. подсчитать, обратный отсчет.
  • while/do-while конструкции предназначены для всех других условий. c!=EOF,diff<0.02 и т. д. Итераторы / Перечислители-это счетчики, очень подходящие для циклов for.

то есть ваш 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.карта или список.сложите; -)

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

С точки зрения java, я нахожу для циклов очень удобно для коллекций:

for (Object o : objects){
    o.process();
}

намного легче читать, чем:

int i=0;
while(i < objects.size()){
    objects.get(i).process();
    i++;
}

они обычно компилируются с тем же конечным результатом. Я предпочитаю for'S или for-each большую часть времени. Пишу

for (;x<5;x++){ 
    //do work 
} 

не так зловеще, но писать

while(x<5){
    x++
    //do work
}

вместо

while(x<5){
    //do work
    x++
}

может запутать некоторых людей и вызвать ошибки off-by-one.

на языке, подобном Паскалю, конструкции 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 в 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 дней wend всякий раз, когда я вижу, когда я хочу плакать.

есть некоторые случаи, когда петли хорошо использовать. Вызов функции для объекта, который возвращает 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 счетчик циклов как константа.

просто выберите один, а затем скопируйте и вставьте / отрегулируйте его во всех ваших проектах. Меньше решений, меньше типизации, быстрее кодирование. Незначительная разница в производительности.

также я не с Джастином держать 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 { ... }

проще говоря:

В 'для' петли, как правило, используется для использовать итерационные численные. Вам нужно перебирать массив, вам нужны числа от 1 до 100 (или другие диапазоны) по разным причинам.

цикл 'while' имеет тенденцию быть условным циклом. Вы хотите продолжать что-то делать, пока contition является ложным. Предполагая, что у вас есть класс под названием "тост", и вы хотите приготовить тост, пока он не поджарится, у вас будет что-то вроде следующее:

while (!toast.isToasted) cook(toast);

вы можете почти всегда (я не могу придумать пример, где вы не можете) написать цикл for как цикл while и цикл while как цикл for, но выбирая тот, который лучше всего подходит для первой ситуации, обычно сводится к моим вышеперечисленным пунктам.

читаемость является очень важным моментом, но он работает в обоих направлениях. Я преобразую цикл for в цикл while-даже когда я использую переменную счетчика, или в противном случае было бы "естественно" использовать for-когда это более читаемо таким образом. Это часто встречается, когда у вас есть длинное или сложное выражение в любой из трех частей 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 (++i

одна из причин заключается в том, что условие 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.