Существует ли когда-нибудь потребность в, “делают {…} в то время как ()” цикл?

Да, я согласен, что прототип можно использовать для значений свойств (переменных) по умолчанию. Функция конструктора не должна объявлять свойство; это может быть сделано условно.

function Person( name, age ) {
    this.name = name;

    if ( age ) {
        this.age = age;
    }
}

Person.prototype.sayHello = function() {
    console.log( 'My name is ' + this.name + '.' );
};

Person.prototype.sayAge = function() {
    if ( this.age ) {
        console.log( 'I am ' + this.age + ' yrs old!' ); 
    } else {
        console.log( 'I do not know my age!' );
    }
};

Person.prototype.age = 0.7;

//-----------

var person = new Person( 'Lucy' );
console.log( 'person.name', person.name ); // Lucy
console.log( 'person.age', person.age );   // 0.7
person.sayAge();                           // I am 0.7 yrs old!

Посмотрите, как Люси age условно объявлен и инициализирован.

68
задан 6 revs, 3 users 100% 15 June 2009 в 18:11
поделиться

15 ответов

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

#include <stdio.h>

int main() {
    char c;

    do {
        printf("enter a number");
        scanf("%c", &c);

    } while (c < '0' ||  c > '9'); 
}

Это, конечно, можно переписать в цикл while, но обычно это рассматривается как нечто большее элегантное решение.

89
ответ дан 24 November 2019 в 14:04
поделиться

Цикл do-while всегда можно переписать как цикл while.

Следует ли использовать только циклы while или циклы while, do-while и for (или любую их комбинацию ) во многом зависит от вашего вкуса к эстетике и условностей проекта, над которым вы работаете.

Лично я предпочитаю циклы while, потому что они упрощают рассуждения об инвариантах цикла. ИМХО.

Что касается того, есть ли ситуации, когда вы это делаете нужны циклы do-while: вместо

do
{
  loopBody();
} while (condition());

вы всегда можете

loopBody();
while(condition())
{
  loopBody();
}

, так что нет, вам никогда не нужно использовать do-while, если вы не можете по какой-то причине. (Конечно, этот пример нарушает DRY, но это только доказательство концепции. По моему опыту, обычно существует способ преобразования цикла do-while в цикл while и не нарушать DRY в любом конкретном случае использования.)

«Находясь в Риме, поступайте, как римляне».

BTW: Цитата, которую вы ищете, может быть следующей ([1], последний абзац раздела 6.3.3):

По моему опыту, оператор do является источником ошибок и путаницы. Причина в том, что его тело всегда выполняется один раз перед проверкой условия. Однако для правильного функционирования тела необходимо, чтобы при первом запуске выполнялось условие, аналогичное конечному. Чаще, чем я ожидал, я обнаруживал, что эти условия не выполняются. Так было как тогда, когда я писал данную программу с нуля и затем тестировал ее, так и после изменения кода. Кроме того, я предпочитаю условие «впереди, где я могу это видеть». Поэтому я стараюсь избегать заявлений о делах.

(Примечание: это мой перевод немецкого издания. Если вам посчастливилось владеть английским изданием, не стесняйтесь редактировать цитату, чтобы она соответствовала его исходной формулировке. К сожалению, Аддисон-Уэсли ненавидит Google.)

[1] B. Страуструп: Язык программирования C ++. 3-е издание. Addison-Wessley, Reading, 1997.

2
ответ дан 24 November 2019 в 14:04
поделиться

Прочтите теорему о структурированной программе . Do {} while () всегда можно переписать на while () do {}. Последовательность, выбор и итерация - это все, что когда-либо требовалось.

Поскольку все, что содержится в теле цикла, всегда можно инкапсулировать в подпрограмму, необходимость использования while () do {} никогда не будет хуже, чем

LoopBody()
while(cond) {
    LoopBody()
}
]
2
ответ дан 24 November 2019 в 14:04
поделиться

В ответ на вопрос / комментарий от unknown (google) к ответу Дэна Олсона:

«do {...} while (0) - важная конструкция для создания макросов ведите себя хорошо. "

#define M do { doOneThing(); doAnother(); } while (0)
...
if (query) M;
...

Вы видите, что происходит без do {...} while (0) ? Он всегда будет выполнять doAnother ().

2
ответ дан 24 November 2019 в 14:04
поделиться

В наших соглашениях о кодировании

  • if / while / ... условия не имеют побочных эффектов, и
  • переменные должны быть инициализированы.

Итак, у нас есть почти никогда не делать {} while (xx) Потому что:

int main() {
    char c;

    do {
        printf("enter a number");
        scanf("%c", &c);

    } while (c < '0' ||  c > '9'); 
}

переписан на:

int main() {
    char c(0);
    while (c < '0' ||  c > '9');  {
        printf("enter a number");
        scanf("%c", &c);
    } 
}

, а

Handle handle;
Params params;
if( ( handle = FindFirstFile( params ) ) != Error ) {
   do {
      process( params ); //process found file
   } while( ( handle = FindNextFile( params ) ) != Error ) );
}

переписан на:

Params params(xxx);
Handle handle = FindFirstFile( params );
while( handle!=Error ) {
    process( params ); //process found file
    handle = FindNextFile( params );
}
6
ответ дан 24 November 2019 в 14:04
поделиться

Это полезно, когда вы хотите «что-то сделать», пока «условие не будет выполнено.

Это можно исправить в цикле while следующим образом:

while(true)
{

    // .... code .....

    if(condition_satisfied) 
        break;
}
7
ответ дан 24 November 2019 в 14:04
поделиться

На мой взгляд, это только личный выбор.

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

Если вы посмотрите выше, ответ TimW говорит сам за себя. Второй вариант с Handle, на мой взгляд, особенно запутан.

3
ответ дан 24 November 2019 в 14:04
поделиться

do {...}, а (0) - важная конструкция для обеспечения правильного поведения макросов.

Даже если это неважно в реальном коде (с чем я не обязательно согласен), это важно для исправления некоторых недостатков препроцессора.

Редактировать: Я столкнулся с ситуацией, когда do / while сегодня было намного чище. в моем собственном коде. Я делал кроссплатформенную абстракцию парных инструкций LL / SC . Их необходимо использовать в цикле, например:

do
{
  oldvalue = LL (address);
  newvalue = oldvalue + 1;
} while (!SC (address, newvalue, oldvalue));

(Эксперты могут понять, что старое значение не используется в реализации SC, но оно включено, чтобы эту абстракцию можно было эмулировать с помощью CAS.)

LL и SC являются отличный пример ситуации, когда do / while значительно чище, чем эквивалентная форма while:

17
ответ дан 24 November 2019 в 14:04
поделиться

Все дело в читабельности .
Более читаемый код снижает головную боль при сопровождении кода и улучшает совместную работу.
Другие соображения (например, оптимизация) в большинстве случаев гораздо менее важны.
Я уточню, так как я получил здесь комментарий:
Если у вас есть фрагмент кода A , в котором используется do {...} while () , и он более читабелен, чем его while () {...} эквивалент B , то я бы проголосовал за A . Если вы предпочитаете ​​B , поскольку вы видите условие цикла «впереди», и считаете его более читаемым (и, следовательно, поддерживаемым и т. Д.) - тогда продолжайте, используйте B .
Моя точка зрения: используйте код, который более читается для ваших глаз (и для ваших коллег). Выбор, конечно, субъективен.

5
ответ дан 24 November 2019 в 14:04
поделиться

(Предполагая, что вы знаете разницу между ними)

Do / While подходит для начальной загрузки / предварительной инициализации кода перед проверкой вашего условия и запуском цикла while.

6
ответ дан 24 November 2019 в 14:04
поделиться

Я почти никогда не использую их просто из-за следующего:

Несмотря на то, что цикл проверяет наличие постусловия, вам все равно нужно проверять это условие поста в своем цикле, чтобы вы не не обрабатывает условие публикации.

Возьмем пример псевдокода:

do {
   // get data 
   // process data
} while (data != null);

Теоретически это звучит просто, но в реальных ситуациях это, вероятно, будет выглядеть так:

do {
   // get data 
   if (data != null) {
       // process data
   }
} while (data != null);

Дополнительная проверка «если» просто не является т стоит ИМО. Я нашел очень мало случаев, когда было бы проще выполнить do-while вместо цикла while. YMMV.

2
ответ дан 24 November 2019 в 14:04
поделиться

do-while - это цикл с постусловием. Он нужен в случаях, когда тело цикла нужно выполнить хотя бы один раз. Это необходимо для кода, который требует некоторых действий перед тем, как условие цикла может быть разумно оценено. С циклом while вам придется вызывать код инициализации с двух сайтов, с do-while вы можете вызывать его только с одного сайта.

Другой пример - когда у вас уже есть действительный объект, когда должна быть запущена первая итерация, поэтому вы не хотите ничего выполнять (включая оценку условий цикла) до начала первой итерации. Примером являются функции Win32 FindFirstFile / FindNextFile: вы вызываете FindFirstFile, который либо возвращает ошибку, либо дескриптор поиска для первого файла, затем вы вызываете FindNextFile, пока он не вернет ошибку.

Псевдокод:

Handle handle;
Params params;
if( ( handle = FindFirstFile( params ) ) != Error ) {
   do {
      process( params ); //process found file
   } while( ( handle = FindNextFile( params ) ) != Error ) );
}
38
ответ дан 24 November 2019 в 14:04
поделиться

Моя проблема с do / , а строго связана с его реализацией в C. Из-за повторного использования while ключевое слово, оно часто сбивает людей с толку, потому что выглядит ошибкой.

Если while было зарезервировано только для , а циклы и do / в то время как был изменен на делать / до или повторять / до , я не думаю, что цикл (который, безусловно, удобен и является «правильным» способом кодирования некоторых циклов) вызвал бы столько проблем.

Я уже говорил об этом ранее в отношении JavaScript ,который также унаследовал этот жалкий выбор от C.

1
ответ дан 24 November 2019 в 14:04
поделиться

рассмотрите что-то вроде этого:

int SumOfString(char* s)
{
    int res = 0;
    do
    {
        res += *s;
        ++s;
    } while (*s != '\0');
}

Так получилось, что '\ 0' равно 0, но я надеюсь, что вы поняли.

1
ответ дан 24 November 2019 в 14:04
поделиться

Следующая распространенная идиома кажется мне очень простой:

do {
    preliminary_work();
    value = get_value();
} while (not_valid(value));

Переписать, чтобы избежать do , похоже:

value = make_invalid_value();
while (not_valid(value)) {
    preliminary_work();
    value = get_value();
}

Эта первая строка используется, чтобы убедиться, что тест всегда оценивается как истина в первый раз. Другими словами, тест всегда бывает лишним с первого раза. Если бы этого лишнего теста не было, можно было бы также опустить начальное задание. Этот код производит впечатление, что он борется сам с собой.

В подобных случаях конструкция do является очень полезной опцией.

6
ответ дан 24 November 2019 в 14:04
поделиться