Циклы в C - for () или while () - что лучше? - PullRequest
6 голосов
/ 11 февраля 2010

for () или while () - что лучше?

for (i=1; i<a; i++)
  /* do something */

OR

i=1;
while (i<a) {
/* do something */
i++;
}

Ответы [ 4 ]

17 голосов
/ 11 февраля 2010

Первый - идиоматический путь; это то, что ожидает большинство C-кодеров. Тем не менее, я должен отметить, что большинство людей также ожидают увидеть

for(i = 0; i < a; i++)

Обратите внимание, что цикл начинается с нуля. Это будет делать что-то a раза. Если вы собираетесь написать цикл while, который эквивалентен циклу for, как указано выше, я настоятельно рекомендую вам написать его как цикл for. Опять же, именно это ожидают увидеть C-кодеры. Кроме того, как цикл for легче читать, поскольку все (инициализация, условие цикла, выражение, которое будет выполнено после каждой итерации) находятся в одной строке. Для цикла while они разложены, что затрудняет чтение.

Обратите внимание, однако, есть обстоятельства, при которых кажущиеся эквивалентными циклы for и while фактически не являются. Например:

for(i = 0; i < 10; i++) {
    if(i == 5) continue;
    printf("%d\n", i);
}

и

i = 0;
while(i < 10) {
    if(i == 5) continue;
    printf("%d\n", i);
    i++;
}

на первый взгляд кажутся эквивалентными, но это не так. Цикл for напечатает 0--9 пропуск 5 на консоли, тогда как цикл while выведет 0--4 на консоли и затем введет бесконечный цикл.

Теперь, это обрабатывает простой случай, о котором вы спрашивали. А как насчет более сложных случаев, о которых вы не спрашивали? Ну, это действительно зависит, но хорошее эмпирическое правило таково: если вы собираетесь повторять что-то фиксированное заранее определенное количество раз, цикл for обычно лучше. В противном случае используйте петлю while. Это не жесткое правило, но хорошее практическое правило. Например, вы можете написать

unsigned int v;
unsigned int c;
for(c = 0; v; v >>= 1) c += v & 1;

но я думаю, что большинство программистов на С написали бы это как

unsigned int v;
unsigned int c;
c = 0;
while(v) { c += v & 1; v >>= 1; }

Или, в качестве другого примера, если вы собираетесь читать до конца файла, вам следует использовать цикл while. Таким образом

FILE *fp;
fp = fopen(path, "r");
while(fgets(buf, max, fp) != NULL) { /* something */ }

вместо

FILE *fp;
for(fp = fopen(path, "r"); fgets(buf, max, fp) != NULL; ) { /* something */ }

Теперь, достигнув религиозной территории, именно поэтому я предпочитаю while(1) как правильный способ сделать бесконечный цикл над for(;;).

Надеюсь, это поможет.

3 голосов
/ 11 февраля 2010

Это зависит. Что делает чтение наиболее легким, должно быть руководящим принципом ИМХО. Если вы знаете границы заранее, вы, вероятно, должны использовать «для». Поскольку в одной строке четко указано, где начинается цикл, он заканчивается и как перейти от одного элемента к другому.

2 голосов
/ 11 февраля 2010

Голосуйте за Дэна МакГа - если цикл имеет фиксированный счет и т. Д., Используйте для - это более идиоматично.Классические случаи каждого из них:

for (i = 0; i < THRESHOLD; ++i) {
  something;
}

Vs.

while (foo->next) {
  foo = foo -> next; 
}

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

В конце дня: вернитесь назад и прочитайте каждую версию цикла.Какой из них выделяется в вашем сознании как «чистый» в намерениях?

1 голос
/ 11 февраля 2010

Какой из них наиболее целесообразен в данной ситуации.

Цикл for говорит вам, что это, скорее всего, цикл с фиксированным счетом. Начиная с 1 и заканчивая перед.

Цикл while не подразумевает ничего подобного, просто он заканчивается один раз i >= a (по крайней мере, от простого чтения while (i<a){ вверху).

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...