Типы циклов в C++

User Rating: 5 / 5

Если в программе на C++ требуется выполнять какую-то операцию или последовательность операций несколько раз, то для этой цели как нельзя лучше подойдут циклы (англ. loops)

Операторы в C++ всегда выполняются последовательно, один за другим. И если представить, что у Вас есть некоторый блок кода, который нужно использовать (т.е. повторить) более 1 раза, то вместо того, чтобы копировать этот блок кода несколько раз, Вы можете заключить его внутрь цикла и задать условия выполнения этого цикла.

Циклы в C++ бывают следующих видов:

  • цикл for
  • цикл while
  • цикл do ... while
  • вложенные циклы

Давайте рассмотрим каждый вид цикла более детально.

Цикл for в C++

Чтобы лучше погрузиться в тему циклов, давайте для начала рассмотрим пример, в котором у Вас есть некоторый массив (назовём его array_of_int) целых чисел из 10-ти элементов, и Вы хотите проинициализировать каждый элемент этого массива значением индекса, умноженного на 100, а затем вывести на отдельных строках все значения элементов массива на экране консоли.

Вот как будет выглядеть код на C++, решающий эту задачу без использования циклов:

#include <iostream>

using namespace std;

int main() {
    int array_of_int[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };

    array_of_int[0] = 0 * 100;
    array_of_int[1] = 1 * 100;
    array_of_int[2] = 2 * 100;
    array_of_int[3] = 3 * 100;
    array_of_int[4] = 4 * 100;
    array_of_int[5] = 5 * 100;
    array_of_int[6] = 6 * 100;
    array_of_int[7] = 7 * 100;
    array_of_int[8] = 8 * 100;
    array_of_int[9] = 9 * 100;
    
    cout << array_of_int[0] << endl;
    cout << array_of_int[1] << endl;
    cout << array_of_int[2] << endl;
    cout << array_of_int[3] << endl;
    cout << array_of_int[4] << endl;
    cout << array_of_int[5] << endl;
    cout << array_of_int[6] << endl;
    cout << array_of_int[7] << endl;
    cout << array_of_int[8] << endl;
    cout << array_of_int[9] << endl;
}

Запустите эту программу и увидите на экране консоли следующий вывод:

0
100
200
300
400
500
600
700
800
900

Эта программа, если в неё вглядеться, содержит существенный недостаток - нам приходится дублировать код для инициализации каждого очередного элемента массива, а также дублировать код, который выводит значение определенного элемента массива на консоль. Чтобы избежать дублирования, давайте посмотрим на вариант этой же программы, но с использованием цикла for, который предоставляется средствами языка C++:

#include <iostream>

using namespace std;

int main() {
    int array_of_int[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };

    for (int i = 0; i < 10; i++) {
        array_of_int[i] = i * 100;
        cout << array_of_int[i] << endl;
    }
}

Если запустить данный вариант программы с циклом for, Вы увидите, что её результат ничем не отличается от предыдущего варианта: на консоль будет выведено те же самые значения. Однако программа стала существенно компактнее, и за счёт цикла мы смогли объединить две операции над элементами нашего массива:

  • инициализация каждого элемента нужным нам значением
  • вывод значения текущего перебираемого элемента на консоль

Цикл for устроен следующим образом:

for (/* <инициализирующие операторы> */; /* <условие выполнения цикла> */; /* <операторы инкремента> */) {
    // "тело цикла" - операторы, которые выполняются до тех пор, 
    // пока истинно <условие выполнения цикла>
}

В примере, который мы рассматривали выше, инициализирующим оператором цикла является int i = 0. Т.е. мы инициализируем так называемую переменную цикла с именем i. Условием выполнения цикла является оператор i < 10,  т.е. пока значение переменной цикла i меньше 10, операторы, помещённые в тело цикла, будут выполняться. Оператором инкремента в нашем случае является i++, где мы наращиваем значение переменной цикла каждый раз на единицу. Операторы инкремента выполняются после каждого очередного прохода цикла, т.е. после выполнения всех операторов, представляющих собой тело цикла

Наиболее часто в реальных программах встречается цикл for с одним инициализирующим оператором (например, как у нас int i = 0), однако Вы не ограничены в том, чтобы задать несколько инициализирующих операторов. Давайте посмотрим, как это может выглядеть:

for (int i = 0, j = 0; i < 10 && j < 5; i++, j++) {
    array_of_int[i] = i * 100;
    cout << array_of_int[i] << endl;
}

Если Вы запустите программу с этим вариантом цикла, то увидите на экране следующее:

0
100
200
300
400

Это говорит о том, что наш цикл теперь выполнился только 5 раз, поскольку в условие выполнения цикла добавилось дополнительное условие: j < 5. Как видите, можно легко задать более одного инициализирующего оператора, а также условие цикла и операторы инкремента могут быть более сложными, при необходимости.

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

  • в самом начале и только один раз исполняются инициализирующие операторы, как правило, устанавливая начальные значения переменных цикла (или переменной, если она одна)
  • затем сразу же проверяется условие выполнения цикла. Если оно в начале первой итерации цикла возвращает результат false или 0, то цикл не будет выполнен ни разу, и произойдет моментальный выход из цикла. Если же условие выполнения цикла возвращает результат true или 1, то выполняются операторы, расположенные в теле цикла.
  • После выполнения всех операторов в теле цикла выполняются операторы инкремента (или оператор, если он всего один). После выполнения операторов инкремента условие выполнения цикла проверяется вновь, и если оно возвращает true или 1, то цикл продолжается, а если возвращает false или 0, то происходит выход из цикла (т.е. завершение цикла).

Цикл while в C++

Давайте немного перепишем наш пример с циклом for, который рассматривали выше, и посмотрим на то, как можно выполнить ту же самую исходную задачу с инициализацией элементов нашего массива и их выводом на экран при помощи цикла while:

#include <iostream>

using namespace std;

int main() {
    int array_of_int[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };

    int i = 0;
    while (i < 10) {
        array_of_int[i] = i * 100;
        cout << array_of_int[i] << endl;
        i++;
    }
}

Если Вы запустите этот вариант программы, то увидите тот же результат, что мы получили в самом начале изучения работы цикла for:

0
100
200
300
400
500
600
700
800
900

Цикл while, как видим, просто содержит условие выполнения цикла, в нём нет никаких операторов инициализации и операторов инкремента. Только условие выполнения цикла и само тело цикла. Из-за этого программисту необходимо самому позаботиться о том, что будет являться условием выхода из цикла while, и как это условие будет изменяться. С циклом while нужно быть внимательным, чтобы не забывать изменять переменную, от которой зависит условие выполнения цикла. Если забыть это сделать, Вы получите бесконечный цикл (англ. infinite loop) - цикл, который никогда не закончится и будет "съедать" процессорное время и ресурсы вашего компьютера (например, выделять всё больше и больше памяти). Если это произойдет, то программа попросту "зависнет", и Вам придётся её завершать принудительно через диспетчер задач, если Вы работаете под ОС Windows. Убрав всего один оператор i++ из примера выше, мы получим такой бесконечный цикл:

#include <iostream>

using namespace std;

int main() {
    int array_of_int[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };

    int i = 0;
    while (i < 10) { // это условие будет всегда истинно!
        array_of_int[i] = i * 100;
        cout << array_of_int[i] << endl;
        // оператора i++ нет, поэтому цикл превращается в "бесконечный"
    }
}

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

Напоследок, говоря про цикл while, можно отметить его некоторую схожесть с циклом for в том плане, что если условие выполнения цикла при входе в него вернёт false или 0, то тело цикла не будет выполнено ни разу, и программа C++ перейдет сразу к операторам, следующим за циклом. Если же условие выполнения цикла при входе в него вернёт true или 1, то мы будем выполнять цикл до тех пор, пока это условие возвращает true или 1.

Цикл do ... while в C++

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

#include <iostream>

using namespace std;

int main() {
    int array_of_int[] = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 };

    int i = 0;
    do {
        array_of_int[i] = i * 100;
        cout << array_of_int[i] << endl;
        i++;
    } while (i < 10);
}

Эта программа с вариантом цикла do ... while решает всё ту же задачу инициализации элементов массива и вывода их значений на экран консоли. Вывод на консоль ничем не отличается от предыдущих вариантов с циклами for и while:

0
100
200
300
400
500
600
700
800
900

Цикл do ... while так же, как и обычный цикл while, содержит условие выполнения цикла внутри while. Сразу после ключевого слова do идёт блок операторов, представляющих собой тело цикла. Ещё один момент: обратите внимание, что в самом конце цикла do ... while стоит точка запятой: она необходима для завершения цикла, и без неё компилятор C++ выдаст Вам ошибку.

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

Вложенные циклы

Возможности языка C++ позволяют Вам как программисту организовывать вложенные циклы. Без труда можно догадаться, что речь идёт о ситуации, когда Вы "вкладываете" один цикл в другой. Комбинировать и вкладывать друг в друга можно любые типы циклов: можете организовать, к примеру, три вложенных цикла for или внутрь цикла for поместить цикл while. Ваши возможности здесь безграничны, и всё зависит от Вашей фантазии и задачи, выполняемой программой.

Давайте посмотрим на небольшой пример вложенных циклов for:

#include <iostream>

using namespace std;

int main() {
    int matrix_of_int[3][3] = { { 10, 20, 30}, {40, 50, 60}, {70, 80, 90} };

    for (int i = 0; i < 3; i++) {
        for (int j = 0; j < 3; j++) {
            matrix_of_int[i][j] = (i + 1) * (j + 1);
            cout << "[" << i << ", " << j << "] = " << matrix_of_int[i][j] << "\t";
        }
        cout << endl;
    }
}

В этом примере мы задаём двумерный массив целых чисел с именем matrix_of_int и инициализируем его статически целочисленными константами от 10 до 90. Двумерный массив ещё принято называть матрицей (англ. matrix), что и отражено в названии массива. Матрицу можно представить в виде таблицы с определённым количеством строк и столбцов. В нашем примере у нашей "таблицы" 3 строки и 3 столбца.

Дальше мы организовали два цикла forвнешний цикл for по строкам и второй, внутренний, - по столбцам нашей матрицы.

Во внутреннем цикле мы переписываем каждый элемент нашей матрицы, присваивая ему значение произведения индекса строки на индекс столбца, к которым прибавлено по единице: (i + 1) * (j + 1)

Далее мы выводим на экран консоли индекс строки и индекс столбца нашей матрицы, а также значение матрицы в данной строке и столбце, разделённые символом табуляции ( \t ). Когда внутренний цикл по столбцам завершается, мы делаем переход на следующую строку при помощи оператора cout << endl;

Если Вы запустите эту программу, то увидите на экране следующее:

[0, 0] = 1   [0, 1] = 2   [0, 2] = 3
[1, 0] = 2 [1, 1] = 4 [1, 2] = 6
[2, 0] = 3 [2, 1] = 6 [2, 2] = 9

Всё вывелось так, как должно было: каждый элемент матрицы является произведением индексов его строки и столбца, к которым прибавлены единицы.

Заключение

В этой статье мы познакомились с ключевыми видами циклов, используемых в языке C++, а также посмотрели на их отличительные особенности. Попробуйте теперь использовать и скомбинировать различные виды циклов C++ в своих программах. Напишите в комментариях к статье свои мысли о циклах в языке C++, а также поделитесь мнением, какой цикл, по Вашему мнению, лучше и чаще используется при написании программ.

 

Яндекс.Метрика