Циклы в C - для () или в то время как () - который является ЛУЧШИМ?

для () или в то время как () - который является ЛУЧШИМ?

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

ИЛИ

i=1;
while (i<a) {
/* do something */
i++;
}
6
задан aks 11 February 2010 в 06:16
поделиться

4 ответа

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

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

. Обратите внимание, что цикл начинается с нуля. Это сделает что-то a раз.Если вы собираетесь написать цикл while , который эквивалентен циклу for , как указано выше, я настоятельно рекомендую вам написать его как цикл for . Опять же, это то, что ожидают увидеть C-кодеры. Кроме того, как цикл 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;

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

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

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

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 (;;) .

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

17
ответ дан 8 December 2019 в 05:21
поделиться

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

3
ответ дан 8 December 2019 в 05:21
поделиться

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

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

Vs.

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

И еще: если вы обнаружите, что в for не хватает условий, подумайте, что будет, если переделать его в while.

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

2
ответ дан 8 December 2019 в 05:21
поделиться

Если текст является HTML, текст не будет выделен серым цветом из-за следующего кода в BasicLabelUI # paint ()

        View v = (View) c.getClientProperty(BasicHTML.propertyKey);
        if (v != null) {
        v.paint(g, paintTextR);
        }

Как видно, если текст является html, то вид используется для рисования и не проверяется, включена ли метка. Поэтому мы должны сделать это прямо, как показано ниже:

label2.addPropertyChangeListener(new PropertyChangeListener() {
   public void propertyChange(PropertyChangeEvent evt) {
    if (!evt.getPropertyName().equals("enabled"))
     return;
    if (evt.getNewValue().equals(Boolean.FALSE))
     label2.setText("<html><font color=gray>HTML <b>text</b></html>");
    else
     label2.setText("<html><font color=black>HTML <b>text</b></html>");
   }
  });
-121--3311380-

К сожалению, МГавк просто запускает процессы RRDTool для каждой команды RRD. Вместо этого SUggested MHawk подключается к библиотеке, чтобы вызовы можно было поддерживать в процессе.

-121--3623050-

Какой из них имеет наибольший смысл в данной ситуации.

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

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

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

1
ответ дан 8 December 2019 в 05:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: