Открыть сервис

Оператор do

Оператор do — это конструкция в языке программирования C, а также в ряде других языков (C++, C#, Java, JavaScript, Go, Rust и т. д.), реализующая цикл с постусловием: тело цикла выполняется как минимум один раз, после чего проверяется условие продолжения. В отличие от цикла while, где условие проверяется перед выполнением тела, в цикле do условие проверяется после выполнения тела, что гарантирует хотя бы один проход.

Синтаксис и семантика

В языках, произошедших от C (C, C++, C#, Java, JavaScript, PHP, Perl, Objective-C), синтаксис выглядит следующим образом:

`` do { // тело цикла } while (условие); ``

  • Ключевое слово do — обозначает начало цикла.
  • Фигурные скобки {} — заключают тело цикла. В большинстве языков обязательны, даже если тело состоит из одного оператора (исключение — C и C++, где можно опустить скобки для одного оператора, но это считается плохой практикой).
  • Ключевое слово while — вводит условие.
  • Условие — логическое выражение, которое вычисляется после каждого выполнения тела. Если оно истинно (не равно нулю в C/C++), цикл повторяется; если ложно (равно нулю) — выполнение продолжается с оператора, следующего за while.
  • Точка с запятой ; — обязательна после условия в конце конструкции.

Семантика выполнения

  1. Выполняется тело цикла (один раз).
  2. Вычисляется условие.
  3. Если условие истинно — возврат к шагу 1.
  4. Если условие ложно — выход из цикла.

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

Примеры использования

Простейший пример на C

```c

include <stdio.h>

int main() { int i = 0; do { printf("%d ", i); i++; } while (i < 5); return 0; } ```

Вывод: 0 1 2 3 4

Пример с гарантированным однократным выполнением

``c int x = 10; do { printf("x = %d\n", x); x++; } while (x < 5); ``

Вывод: x = 10 — тело выполнится один раз, хотя условие x < 5 ложно с самого начала.

Пример на Java

``java public class DoWhileExample { public static void main(String[] args) { int n = 1; do { System.out.println("n = " + n); n++; } while (n <= 3); } } ``

Пример на JavaScript

``javascript let i = 0; do { console.log(i); i++; } while (i < 3); ``

Отличия от цикла while

Характеристикаwhiledo
Проверка условияПеред теломПосле тела
Минимальное количество выполнений тела01
Тип циклаЦикл с предусловиемЦикл с постусловием
Синтаксическая конструкцияwhile (условие) { тело }do { тело } while (условие);

Типичные сценарии применения

Цикл do применяется в ситуациях, когда необходимо гарантировать хотя бы одно выполнение тела цикла до проверки условия. Наиболее распространённые случаи:

  • Ввод данных с проверкой — например, запрос пароля у пользователя, который должен быть введён хотя бы один раз, а затем проверяется на корректность.
  • Обработка меню — вывод меню, выполнение действия, затем проверка, не выбрал ли пользователь выход.
  • Итерация по структурам данных, где первая операция обязательна — например, чтение первого элемента из очереди перед проверкой её пустоты.
  • Реализация алгоритмов, где условие выхода зависит от результата выполнения тела — например, метод Ньютона для поиска корня уравнения.

Пример: ввод пароля на C

```c

include <stdio.h>

include <string.h>

int main() { char password[20]; do { printf("Введите пароль: "); scanf("%19s", password); } while (strcmp(password, "secret") != 0); printf("Доступ разрешён.\n"); return 0; } ```

Реализация в различных языках программирования

C и C++

Цикл do присутствует в C с момента его создания (1972 год, Керниган и Ритчи). В C++ синтаксис и семантика полностью унаследованы от C. В C++ допускается объявление переменной внутри условия цикла do, но это редко используется на практике.

C#

В C# цикл do работает аналогично C, но с одним важным отличием: условие должно быть логического типа bool, а не целочисленным (как в C, где ноль — ложь, ненулевое значение — истина).

``csharp int i = 0; do { Console.WriteLine(i); i++; } while (i < 5); ``

Java

В Java цикл do полностью идентичен C# по синтаксису и семантике. Условие — строго boolean.

JavaScript

В JavaScript цикл do работает так же, как в C, но с динамической типизацией: условие приводится к логическому типу.

Go

В языке Go нет цикла do. Вместо него используется комбинация for с проверкой условия в конце тела, имитирующая поведение do:

``go i := 0 for { fmt.Println(i) i++ if i >= 5 { break } } ``

Rust

В Rust также нет цикла do. Для достижения аналогичного поведения используется loop с условием выхода:

``rust let mut i = 0; loop { println!("{}", i); i += 1; if i >= 5 { break; } } ``

Python

В Python цикл do отсутствует. Для гарантированного однократного выполнения тела используется while True с проверкой условия внутри:

``python i = 0 while True: print(i) i += 1 if i >= 5: break ``

PHP

В PHP цикл do работает аналогично C:

``php $i = 0; do { echo $i; $i++; } while ($i < 5); ``

Perl

В Perl синтаксис do с while поддерживается, но точка с запятой не требуется после условия:

``perl my $i = 0; do { print "$i\n"; $i++; } while ($i < 5); ``

Особенности и ограничения

  • Гарантированное выполнение тела — может быть как преимуществом, так и недостатком. Если тело цикла содержит операции с побочными эффектами (например, запись в файл, отправку сетевого запроса), однократное выполнение при ложном условии может быть нежелательным.
  • Риск бесконечного цикла — если условие никогда не становится ложным, цикл выполняется бесконечно. Однако это свойство всех циклов, а не только do.
  • Отсутствие в некоторых языках — современные языки (Python, Go, Rust) отказались от do в пользу более универсальных конструкций, что снижает путаницу между while и do.
  • Читаемость — цикл do может быть менее интуитивным для начинающих программистов, так как условие расположено после тела, что нарушает естественный порядок «сначала проверка, потом действие».

Историческая справка

Цикл do был введён в языке программирования C в начале 1970-х годов Деннисом Ритчи и Брайаном Керниганом. Он был заимствован из более ранних языков, таких как ALGOL и BCPL, где существовали аналогичные конструкции (например, do в ALGOL 60). В C цикл do стал стандартной частью языка, а затем перешёл в C++, Java, C# и многие другие языки, основанные на синтаксисе C.

В 1990-х годах, с ростом популярности объектно-ориентированных языков, цикл do сохранился практически во всех языках, наследующих синтаксис C. Однако в 2000-х годах некоторые новые языки (Python, Go, Rust) отказались от него в пользу более простых и единообразных конструкций, что отражает общую тенденцию к уменьшению количества синтаксических конструкций в современных языках программирования.

Критика и альтернативы

Основная критика цикла do связана с его избыточностью: любое поведение, реализуемое с помощью do, можно реализовать с помощью while с дублированием кода или с помощью while True с проверкой условия в конце тела. Некоторые программисты считают, что do увеличивает сложность языка без существенной выгоды, особенно в свете того, что его использование относительно редко.

В языках, где do отсутствует, программисты используют следующие альтернативы:

  • Дублирование кода тела перед циклом while — не рекомендуется, так как нарушает принцип DRY (Don't Repeat Yourself).
  • Использование while True с break — наиболее распространённый подход, который, однако, может снизить читаемость при большом количестве вложенных условий.
  • Использование функций высшего порядка — например, в функциональных языках или в Python с помощью itertools.

Интересные факты

  • В языке C существует форма do { ... } while(0), которая часто используется в макросах для создания блоков, выполняющихся один раз, но при этом позволяющих использовать точку с запятой в конце макроса (так называемый идиоматический приём «do-while-zero»).
  • В языке программирования D цикл do называется do-while и работает аналогично C.
  • В языке Swift цикл do не используется; вместо него применяется repeat-while, который семантически идентичен do-while в C.
  • В языке программирования Kotlin цикл do отсутствует; для аналогичного поведения используется do-while с синтаксисом, похожим на C.

Источники

  • Керниган Б., Ритчи Д. — «Язык программирования C» (1978)
  • Страуструп Б. — «Язык программирования C++» (1985)
  • Гослинг Дж. — «The Java Language Specification» (1996)
  • ECMA-334 — «C# Language Specification» (2001)
  • Флэнаган Д. — «JavaScript: The Definitive Guide» (1996)
  • Документация языка Go (golang.org)
  • Документация языка Rust (rust-lang.org)

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →