робити {…} поки (помилково)


125

Я дивився на якийсь код окремої людини і помітив, що він, здається, має шаблон у своїх функціях:

<return-type> function(<params>)
{
 <initialization>

 do
 {
   <main code for function>
 }
 while(false);

 <tidy-up & return>
}

Це непогано , більш своєрідно (власне код досить акуратний і не дивно). Це не те, що я бачив раніше, і я замислювався, чи може хтось придумати якусь логіку, що лежить в ньому - можливо, іншою мовою?


2
Ви спробували змінити його на "звичайну" версію і побачити, чи вона все ще збирається? Якщо не вдасться компілювати, коли пишеться нормально, помилка компілятора може дати зрозуміти, чому це було зроблено.
Марк Байєрс

11
Чому б не попросити "індивіда", а не попросити нас здогадатися про його намір?

1
Можливо, його професор вимагав, щоб він використовував do...while()і він використовував цей код як шаблон функції.
Хоган

6
@Neil ... Я хочу уникати дурного вигляду, коли я стикаюся з ним, і він пояснює надсучасне використання C ++, про яке я ніколи не думав.
Містер Хлопчик

6
Здається, вже є декілька різних відповідей, чи можете ви запитати у оригінального автора, які були їхні наміри, і опублікувати назад?
nevets1219

Відповіді:


175

Ви можете breakз do{...}while(false).


95
+1, тому що це, мабуть, намір коду, але робити щось подібне - це просто ідіотсько замасковане гото. Якщо ви вважаєте, що гото - це правильний інструмент для роботи, тоді вам слід просто скористатися # $ (* # @ goto.
dsimcha

55
Це більше, ніж замасковане гото. Це обмежений (структурований) гото.
Томас Едінг

19
Яким чином це "обмежено"? Тільки стрибки вперед навряд чи є "обмеженням". Гото - це гото, і переодягати його так, щоб він виглядав так, що це не гірше, ніж просто використовувати гото в першу чергу.
Анон.

44
@Anon .: Стрибки вперед - це обмеження на гото, а вистрибування - безумовно, обмеження. Справжня проблема у готосі - це код спагетті, а також дуже сильно обмежує стрибок уперед та вперед.
Девід Торнлі

33
Фактичний цикл не є семантично гото. Умовно - це не семантично гото. "Перейти до кінця функції та зробити код очищення" - це семантично гото. Використовуйте готи, коли застосовується семантика, не одягайте щось семантично інше, тому що ви їх боїтеся.
Анон.

126

Дуже багато людей зазначають, що його часто використовують із перервою як незручний спосіб написання "гото". Це, мабуть, вірно, якщо це записано безпосередньо у функції.

У макросі, OTOH, do { something; } while (false)це зручний спосіб ВИЗНАЧИТИ крапку з комою після виклику макросу, абсолютно жоден інший маркер не дотримується.

І інша можливість полягає в тому, що або колись там був цикл, або очікується, що в майбутньому буде додана ітерація (наприклад, у розробці, що проходить тест, ітерація не потрібна для проходження тестів, але, логічно, було б сенс зациклитися там, якщо функція повинна бути дещо більш загальною, ніж зараз вимагається)


18
+1 для згадування про корисність цього в макросах; Я здивований, що ніхто більше не згадував про це!
Нік Мейєр

7
Так, макрос - це насправді цілком правильне використання цього. Звичайно, за межами макросів це просто нерозумно ...;)
jalf

12
Це не незручно, це корисно, тому що це Scoto goto - це означає, що будь-які змінні, які ви оголошуєте в циклі do, руйнуються, тоді як goto цього не робить.
Ана Беттс

9
@Paul: Ніщо не заважає вам додавати дужки навколо групи тверджень, щоб змусити цю поведінку з goto.
erikkallen

5
@Paul: вихід із блоку, безумовно, призводить до знищення локальних змінних у C ++, як і розрив. І в змінні C насправді не зруйновано, їх стековий простір просто відновлюється.
Бен Войгт

25

Перерва як goto - це, мабуть, відповідь, але я висуну ще одну ідею.

Можливо, він хотів мати локально визначені змінні і використовував цю конструкцію, щоб отримати новий обсяг.

Пам’ятайте, хоча останній C ++ дозволяє {...}де завгодно, це було не завжди так.


30
У цьому випадку він міг просто використовувати фігурні брекети.
Неманья Трифунович

2
@Nemanja, ви здивуєтеся тому, що багато розробників цього не знають, і спробуйте щось, що стосується того, що пропонує Хоган
Polaris878

8
@Polaris @Nemanja, це було не до того, як я програмував на C / C ++, як 4 роки, і я зрозумів, що ви можете створити нову локальну область в {} будь-якому місці . Це особливо зручно в switch-caseкоді
Earlz

1
@Nemanja: Я точно не знаю, коли, але я впевнений, що {...}десь є більш сучасна розробка в C ++ (пам'ятаю, перший C ++, який я використовував, був реалізований за допомогою попереднього процесора, і це не дозволило це сучасне використання.) Можливо автор був якраз старою школою.
Хоган

2
Коли це не дозволяло скрізь дужки? Я почав програмувати, як 15 років тому, і це було дозволено тоді (і в моїй текстовій книзі, і в кожному компіляторі, який я спробував).
erikkallen

20

Я бачив, що він використовується як корисний зразок, коли для функції існує багато потенційних точок виходу, але завжди потрібен той самий код очищення незалежно від того, як функція завершується.

Це може зробити виснажливим, якщо / else - якщо дерево набагато простіше для читання, просто потрібно переламати щоразу, коли буде досягнута точка виходу, а решта логіки введена згодом.

Цей шаблон також корисний для мов, які не мають goto-оператора. Можливо, саме тут оригінальний програміст дізнався цю схему.


15
Тоді просто використовуйте чесний, прямий гото замість тонко замаскованого гото.
dimimcha

4
Мені так подобається краще. Це легко читати і не несе в собі клеймо гото.
Камерон

8
Готос ідеально легко читати, якщо використовувати його скупо та локально. Вони отримали стигму ззаду, коли вони були основною формою контролю потоку і перестрибували через сотні ліній.
dimimcha

13
Не використовувати goto через «стигму» - це вірний ознака програмування культового культу.
Анон.

6
Не кажучи вже про те, що маса коду очищення - це неприємний запах. Оскільки C ++, код очищення, як правило, повинен бути в деструкторах, викликаних під час обробки RAII.
Девід Торнлі

12

Я бачив такий код, щоб його можна було використовувати breakяк gotoрізновид.


10

Це просто збочення, whileщоб отримати сематику goto tidy-upбез використання слова goto.

Це погана форма, тому що, коли ви використовуєте інші петлі всередині зовнішнього, whileвони breaksстають неоднозначними для читача. "Це повинно йти до виходу? Або це призначене лише вирватися з внутрішньої петлі?"


10

Я думаю, що зручніше писати breakзамість goto end. Вам навіть не потрібно придумувати назву для етикетки, що робить намір зрозумілішим: ви не хочете переходити до мітки із конкретним іменем. Ви хочете вийти звідси.

Також є ймовірність, що вам все одно знадобляться брекети. Отже, це do{...}while(false);версія:

do {
   // code
   if (condition) break; // or continue
   // more code
} while(false);

І це так, як ви хотіли б це висловити goto:

{
   // code
   if (condition) goto end;
   // more code
}
end:

Я думаю, що сенс першої версії набагато простіше зрозуміти. Крім того, легше писати, простіше розширити, легше перекласти на мову, яка не підтримує gotoі т.д.


Найчастіше занепокоєння щодо використання breakполягає в тому, що він погано маскується goto. Але насправді breakмає більше подібності до return: Обидві інструкції вискакують із блоку коду, який в значній мірі структурований порівняно з goto. Тим не менш, обидві інструкції дозволяють отримати кілька точок виходу в блоці коду, що може часом заплутатись. Зрештою, я б спробував досягти найбільш чіткого рішення, незалежно від конкретної ситуації.


О, я щойно помітив, що не зрозумів питання повністю, перш ніж відповісти. Я думав, що це стосується використання do{ ... }while(false);загалом. Але насправді йдеться про його використання для емуляції якогось try{ ... }finally{ ... }.
Роберт

Приємне спостереження за паралеллю між перервою та поверненням, а не гото. Погодьтеся, що найбільш чітке рішення - найкраще. У багатьох випадках, мабуть, зрозуміліше інкапсулювати такий код у його власній окремій функції, яка використовує функцію return, а не перерву, а потім виконує очищення функції виклику.
persiflage

7

Цей трюк використовують програмісти, які занадто сором'язливі, щоб використовувати явний gotoу своєму коді. Автор наведеного вище коду хотів мати можливість перейти безпосередньо до точки "очищення та повернення" з середини коду. Але вони не хотіли використовувати ярлики та явні goto. Натомість вони можуть використовувати breakвнутрішню частину тіла вищезгаданого "підробленого" циклу, щоб досягти такого ж ефекту.


7

Це дуже поширена практика. В С . Я намагаюся думати про це так, ніби ти хочеш брехати собі таким чином, що "я не використовую goto". Думаючи про це, не було б нічого поганого з gotoподібним вживаним. Насправді це також знизило б рівень відступу.

Однак, як я помітив, дуже часто ця do..whileпетля має тенденцію до зростання. А потім вони потрапляють всередину ifі elseназад, що робить код насправді не дуже читабельним, не кажучи вже про тестувальним.

Вони do..whileзазвичай призначені для прибирання . Я в усіх можливостях вважаю за краще використовувати RAII і повернутися рано з короткої функції. З іншого боку, C не надає вам стільки зручностей, як C ++ , що робить do..whileодин з найкращих підходів до очищення.


6

Це схоже на програміста на C. У C ++ автоматичні змінні мають деструктори, які ви використовуєте для очищення, тому перед поверненням не повинно бути нічого необхідного. У C у вас не було цієї ідіоми RAII , тому якщо у вас є загальний код очищення, ви такожgoto його або використовуєте, або перетворюєте цикл, як описано вище.

Основний його недолік порівняно з ідіомою C ++ полягає в тому, що вона не буде приведена в порядок, якщо в організм буде викинуто виняток. У C не було винятків, тому це не було проблемою, але це робить шкідливу звичку в C ++.


4

Кілька пояснень. Перший - загальний, другий - специфічний для макросів препроцесора C з параметрами:

Управління потоком

Я бачив, що це використовується в простому коді С. В основному, це більш безпечна версія goto, оскільки ви можете вийти з нього, і вся пам'ять очищається належним чином.

Чому щось подібне gotoбуло б добре? Ну, якщо у вас є код, де майже кожен рядок може повернути помилку, але вам потрібно реагувати на них однаково (наприклад, передавши помилку своєму абонентові після очищення), як правило, це читабельніше уникати if( error ) { /* cleanup and error string generation and return here */ }як це дозволяє уникнути дублювання коду очищення.

Однак у C ++ у вас є винятки + RAII саме для цієї мети, тому я вважаю це поганим стилем кодування.

Перевірка з комою

Якщо ви забудете крапку з комою після виклику макросу, подібного до функції, аргументи можуть скоротитися небажаним чином і скомпілюватись у дійсний синтаксис. Уявіть собі макрос

#define PRINT_IF_DEBUGMODE_ON(msg) if( gDebugModeOn ) printf("foo");

Це випадково називається як

if( foo )
    PRINT_IF_DEBUGMODE_ON("Hullo\n")
else
    doSomethingElse();

"Інше" вважатиметься асоційованим із тим gDebugModeOn, коли fooце єfalse , точний реверс задуманого будуть.

Надання області для тимчасових змінних.

Оскільки do / while має фігурні дужки, тимчасові змінні мають чітко визначену область, з якої вони не можуть уникнути.

Уникання попереджень про "можливо небажану крапку з комою"

Деякі макроси активуються лише у складах налагодження. Ви визначаєте їх як:

#if DEBUG
#define DBG_PRINT_NUM(n) printf("%d\n",n);
#else
#define DBG_PRINT_NUM(n) 
#endif

Тепер, якщо ви використовуєте це у версії версії всередині умовного, він компілюється в

if( foo )
    ;

Багато компіляторів бачать це як те саме, що

if( foo );

Що часто пишеться випадково. Так ви отримуєте попередження. Do {} while (false) приховує це від компілятора і приймається ним як ознака того, що ви дійсно не хочете нічого робити тут.

Уникайте захоплення ліній умовними умовами

Макрос із попереднього прикладу:

if( foo )
    DBG_PRINT_NUM(42)
doSomething();

Тепер, у налагодженнях налагодження, оскільки ми також звично включали крапку з комою, це складеться чудово. Однак у складанні випуску це раптом перетворюється на:

if( foo )

doSomething();

Або більш чітко відформатований

if( foo )
    doSomething();

Що зовсім не те, що було призначено. Додавання do {...} while (false) навколо макроса перетворює відсутню крапку з комою в помилку компіляції.

Що це означає для ОП?

Загалом, ви хочете використовувати винятки в C ++ для обробки помилок, а шаблони замість макросів. Однак у дуже рідкісному випадку, коли вам все-таки потрібні макроси (наприклад, при генерації імен класів за допомогою вставки лексеми) або обмежуються простою C, це корисна модель.


Щодо масштабування, то вам не потрібен циклічний апарат; «Прикрас» блок є законним: x =1; y = 2; { int tmp = y; y = x; x = tmp; }.
чепнер

Неприхований блок не вимагає наявності пропущеної крапки з комою, що може спричинити небажані побічні ефекти. Зробіть {} while (); ПОТРЕБАЄ крапку з комою, і, отже, наприклад, не спричиняє виведення наступних операцій у "якщо", якщо макрос не визначає нічого у складі випуску, як у моєму прикладі вище.
uliwitness

Не вдалося цього уникнути, просто надавши краще визначення макросу? #define DBG_PRINT_NUM(n) {}.
чепнер

1
Ні, тому що {} - це повне твердження, тобто еквівалент ";". Тож якщо ви пишете, if(a) DBG_PRINT_NUM(n); else other();це не складатиметься. Тільки if(a) {} else other();або if(a) ; else other();є дійсним, але if(a) {}; else other();це не так, тому що стаття "якщо" складається з двох тверджень.
uliwitness

2

Можливо, він використовується таким чином, що breakможе бути використаний всередині для припинення виконання подальшого коду в будь-який момент:

do {
    if (!condition1) break;
    some_code;
    if (!condition2) break;
    some_further_code;
    // …
} while(false);

7
Це виглядає як спроба уникнути використання gotoлише тому, що хтось чув, що це "погано".
Анон.

1
Можливо, але C ++ має винятки саме з цієї причини.
ТЕД


2

Це просто: мабуть, ви можете вискочити з підробленого циклу в будь-який час, використовуючи breakоператор. Крім того, doблок є окремою сферою (яка також може бути досягнута { ... }лише).

У такій ситуації може бути кращою ідеєю використовувати RAII (об'єкти автоматично руйнуються правильно, коли функція закінчується). Ще одна подібна конструкція - використання goto- так, я знаю, що це зло , але він може використовуватися, щоб мати загальний код очищення, наприклад:

<return-type> function(<params>)
{
 <initialization>

 <main code for function using "goto error;" if something goes wrong>

 <tidy-up in success case & return>

 error:

 <commmon tidy-up actions for error case & return error code or throw exception>
}

(Вбік: Конструкт do-while-false використовується в Lua, щоб розібратися за відсутнім continueтвердженням.)


2

Багато відповідачів дали причину do{(...)break;}while(false). Я хотів би доповнити картину ще одним прикладом із реального життя.

У наступному коді я повинен був встановити нумератор operationна основі адреси, на яку вказував dataпокажчик. Оскільки шафа комутатора спочатку можна використовувати лише на скалярних типах, я зробив це неефективно таким чином

if (data == &array[o1])
    operation = O1;
else if (data == &array[o2])
    operation = O2;
else if (data == &array[on])
    operation = ON;

Log("operation:",operation);

Але оскільки Log () і решта коду повторюються для будь-якого обраного значення операції, я розмовляв, як пропустити решту порівнянь, коли адресу вже виявлено. І ось це do{(...)break;}while(false)стане в нагоді.

do {
    if (data == &array[o1]) {
        operation = O1;
        break;
    }
    if (data == &array[o2]) {
        operation = O2;
        break;
    }
    if (data == &array[on]) {
        operation = ON;
        break;
    }
} while (false);

Log("operation:",operation);

Можна задатися питанням, чому він не зміг би зробити те ж саме breakу ifзаяві, як:

if (data == &array[o1])
{
    operation = O1;
    break;
}
else if (...)

breakвзаємодіє тільки з найближчим укладає циклу або перемикача, будь то for, whileабо do .. whileтип, тому , на жаль , що не працюватиме.


1

Скільки років було автору?

Я запитую, бо я колись стикався з деяким кодом Fortran в реальному часі, який це робив, ще в кінці 80-х. Виявляється, це дійсно хороший спосіб імітувати потоки в ОС, яка їх не має. Ви просто помістіть всю програму (ваш планувальник) у цикл і по черзі викликаєте "підпрограми" підпрограми. Самі підпрограми потоку - це петлі, які повторюються до тих пір, поки не відбудеться одна з низки умов (часто одна - це певна кількість Час минув). "Кооперативна багатозадачність" полягає в тому, що від окремих потоків потрібно раз у раз відмовлятись від процесора, щоб інші не голодували. Ви можете вкладати дзвінки підпрограми циклу, щоб імітувати пріоритет потоку групи.


1

На додаток до вже згаданих "прикладів goto", ідентифікація do ... while (0) іноді використовується в макроозначенні для забезпечення дужок у визначенні і все ще має роботу компілятора з додаванням напівкрапки до кінця виклик макросу

http://groups.google.com/group/comp.soft-sys.ace/browse_thread/thread/52f670f1292f30a4?tvc=2&q=time+(0)


0

Я погоджуюся з більшістю плакатів про використання як тонко замаскованого гото. Макроси також згадуються як потенційна мотивація для написання коду в стилі.

Я також бачив цю конструкцію, яка використовується в змішаних середовищах C / C ++ як виключення бідної людини. "Do {} while (false)" з "перервою" може використовуватися для переходу до кінця блоку коду, якщо в циклі трапляється щось, що зазвичай вимагає винятку.

Я також відчув цей конструкт, який використовується в магазинах, де застосовується ідеологія "єдиного повернення на функцію". Знову ж таки, це замість явного "goto" - але мотивація полягає у тому, щоб уникнути декількох точок повернення, а не "пропускати" код і продовжувати фактичне виконання в межах цієї функції.


0

Я працюю з Adobe InDesign SDK, і приклади InDesign SDK мають майже кожну функцію, написану так. Це пов'язано з тим, що функції, як правило, дуже довгі. Там, де вам потрібно виконати QueryInterface (...), щоб отримати що-небудь з моделі об’єкта програми. Тому зазвичай за кожним QueryInterface дотримується ifне вдалося, перерва.


0

Багато хто вже заявив про схожість між цією конструкцією та a goto, і висловив перевагу гото. Можливо, фон цієї людини включав оточення, в яких директивам кодування суворо заборонялося гото?


0

Інша причина, про яку я можу подумати - це те, що вона прикрашає брекети, тоді як я вважаю, що нові нові голі брекети C ++ не в порядку (ISO C їм не подобається). Інакше заспокоїти статичний аналізатор, як ворсинка.

Не впевнені, чому ви хочете їх, можливо, змінної області застосування чи переваги за допомогою налагоджувача.

Дивіться цикл Trivial Do while , і Braces are Good від C2.

Щоб уточнити мою термінологію (яка, на мою думку, відповідає стандартному використанню):

Голі брекети :

init();
...
{
c = NULL;
mkwidget(&c);
finishwidget(&c);
}
shutdown();

Порожні дужки (NOP):

{}

напр

while (1)
   {}  /* Do nothing, endless loop */

Блок :

if (finished)
{
     closewindows(&windows);
     freememory(&cache);
}

який би став

if (finished)
     closewindows(&windows);
freememory(&cache);

якщо дужки зняті, тим самим змінивши потік виконання, а не лише область локальних змінних. Таким чином, не "вільно стоячи" або "голі".

Голі дужки або блок можуть використовуватися для позначення будь-якого розділу коду, який може бути потенційним для (вбудованої) функції, яку ви хочете відзначити, але не рефактор на той час.


Дійсно? Це ганьба. Однією з небагатьох речей, які мені сподобалися в C, було те, що вона дозволила вам оголосити нову вкладену область просто де завгодно.
ТЕД

1
Голі брекети іноді допомагають виправити дивні збої. Дивіться blogs.msdn.com/oldnewthing/archive/2004/05/20/135841.aspx .
Брайан

1
У C ++ блок (тобто ваші "голі фігурні дужки") можна використовувати де завгодно, дозволено одне твердження.
Бен Войгт

@BenVoigt Порожні дужки, тобто NOP відрізняється від "голих дужок", що є блоком, доданим навколо лінійної послідовності інструкцій. Наприклад, printf ("Привіт"); {putchar (','); путчар (0х20); } printf ("world! \ n"); `де дужки не є частиною керування циклом або гілкою.
mctylr

@mctylr: Я не говорив про порожні дужки.
Бен Войгт

0

Це надуманий спосіб емуляції a, GOTOоскільки ці два практично однакові:

// NOTE: This is discouraged!
do {
    if (someCondition) break;
    // some code be here
} while (false);
// more code be here

і:

// NOTE: This is discouraged, too!
if (someCondition) goto marker;
// some code be here
marker:
// more code be here

З іншого боку, і те, і інше дійсно слід робити з ifs:

if (!someCondition) {
    // some code be here
}
// more code be here

Хоча вкладення може стати трохи потворним, якщо ви просто перетворите довгу нитку вперед GOTOу вкладені if. Справжня відповідь - це власне рефакторинг, однак, не імітуючи архаїчні мовні конструкції.

Якщо ви відчайдушно намагалися транслітерацію алгоритму з GOTOs в ньому, ви, ймовірно, могли б зробити це з цією ідіомою. Це, звичайно, нестандартний і хороший показник, що ви не дуже дотримуєтесь очікуваних ідіом мови.

Я не знаю жодної мови, схожої на C, де "/ while" є ідіоматичним рішенням для чогось насправді.

Можливо, ви могли б перетворити весь безлад на щось більш розумне, щоб зробити його ідіоматичнішим і набагато легше зрозумілим.


1
Алан, do..while(false)це НЕ для запуску «невизначені» кілька разів, то для запуску один раз .
Дмитро

2
Він працює невизначено кілька разів, якщо у вас є continueкінцева умовна заява в кінці, як я показав. До undefinedI просто означає , що ви не знаєте , чи є це більш ніж один раз , якщо ви не можете передбачити , чи буде виконуватися умови , при певній ітерації виконується. Без будь-якого continues в ньому, do..while(false)він запуститься один раз, але також без будь-якого breaks в ньому while(true)буде працювати назавжди, тому "поведінка за замовчуванням" насправді не має значення для розуміння того, що можна зробити з циклами.
Алан Плюм

Це корисно, коли ви визначаєте макрос, який містить кілька операторів. Якщо ви загортаєте їх у do / while (false), ви можете використовувати макрос у операторі if / else, як і будь-який інший виклик функції. дивіться romatheory.com/TechPapers/time.htm для пояснення
Джон Паквін

5
Хтось не розуміє семантики continue. continueНЕ повторює цикл. "Оператор continueмає відбуватися лише в ітераційному операторі і призводить до того, що контроль переходить до частини циклу-продовження найменшої заяви-ітерації , що додається , тобто до кінця циклу."
Бен Войгт

-1, перші два твердження не є ідентичними з причин, на які вказує @BenVoigt.
смт

0

Деякі кодери вважають за краще мати лише один вихід / повернення зі своїх функцій. Використання пустушки do {....} while (false); дозволяє "вирватися" з фіктивного циклу, коли ви закінчите і все одно отримаєте єдине повернення.

Я Java-кодер, тому мій приклад був би чимось подібним

import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class p45
{
    static List<String> cakeNames = Arrays.asList("schwarzwald torte", "princess", "icecream");
    static Set<Integer> forbidden = Stream.of(0, 2).collect(Collectors.toSet());

    public static  void main(String[] argv)
    {
        for (int i = 0; i < 4; i++)
        {
            System.out.println(String.format("cake(%d)=\"%s\"", i, describeCake(i)));
        }
    }


    static String describeCake(int typeOfCake)
    {
        String result = "unknown";
        do {
            // ensure type of cake is valid
            if (typeOfCake < 0 || typeOfCake >= cakeNames.size()) break;

            if (forbidden.contains(typeOfCake)) {
                result = "not for you!!";
                break;
            }

            result = cakeNames.get(typeOfCake);
        } while (false);
        return result;
    }
}


-1

Це кумедно. Напевно, є розриви всередині циклу, як говорили інші. Я зробив би це так:

while(true)
{
   <main code for function>
   break; // at the end.
}

2
З потенціалом петлі назавжди? do..while(false)виходить завжди, while(true)більше на ризикованій стороні.
Дмитро

1
while(true)- це правильна ідіома більшості мов. Ви часто знаходите його в додатках GUI як основний цикл програми. Оскільки ви, по суті, припускаєте, що програма не повинна вмирати, поки їй не скажуть, це do..while(false)спричинить усілякі надумані логіки. Такий підхід може бути більш ризикованим від перфекціоністських POV, але це семантично простіше і, таким чином, менше схильних до людських програмістів (вибачте, Skynet).
Алан Плюм

2
@dmitry do{...}while(false)точно такий же, якwhile(true){ .. break;}
N 1.1,

4
@ N1.1: Не в присутності continue, вони не однакові.
Бен Войгт
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.