C++ предоставляет стандартный набор операторов для условий выбора и циклов.
Ключевыми словами, относящимися к конструкциями условий ветвления кода, являются:
- if
- else
- switch
- case
- break
- default
Ключевыми словами, относящимися к конструкциям циклов, являются:
- do
- while
- break
- continue
- for
Операторы условий
Оператор if
Конструкция условия с использованием оператора if формируется следующим образом:
int x = 56; bool check_x() { if (x > 0) return true; return false; }
В данном случае условие помещено в скобках после оператора if. В данной конструкции код return true; будет выполняться в том случае, если x будет больше 0. следующая строка return false; уже не относится к коду который будет выполняться при выполнении условия. В конструкциях условия при выполнении данного условия будет выполняться только одна строка кода, если код не обрамлён в фигурные скобки, то есть если не сформировано тело кода выполняемого при условии. Рассмотрим два варианта кода:
Первый вариант:
int x = 56; bool check_x() { if (x > 0) x = 0; return true; return false; }
В данном коде return true; будет выполняться всегда, поскольку к коду выполняемому при условии относится только строка x = 0;
Второй вариант:
int x = 56; bool check_x() { if (x > 0) { x = 0; return true; } return false; }
В данном коде return true; будет выполняться только при выполнении условия x > 0 .
Оператор else
Оператор else используется совместно с оператором if для формирования последовательности условий.
int x = 56; bool check_x() { if (x > 0) { x = 0; return true; } else if (x < 0) { x = 0; return false; } else { return false; } }
Оператор else может использоваться как для добавления нового условия, если не выполнилось предыдущее условие - конструкция else if. Так и в качестве завершающего кода в последовательности условий, если предыдущие условия не выполнились. Также возможен вариант без применения фигурных скобок для тела кода в том случае, если код умещается в одну строку.
Операторы switch, case, break, default
Конструкция switch case используется для выбора ветвления кода, в условии которого применяется выбор по целочисленным значениям. Это означает, что switch case может применяться для просто целочисленных значений, перечислений и выбора по коду символа.
int x = 100; bool check_x() { switch (x) { case 0: return true; case 50: x = 0: break; case 100: return false; default: return false; }
В выше представленном коде переменная x проверяется на равенство числам 0, 50, 100. Оператор default выполняет выбор кода, который выполняется в том случае, если ни одно из условий не подошло. Заметьте также, что в блоке кода с case 50: добавлен оператор break , этот оператор выполняет выход из условия, тогда как оператор return выполняет выход из функции. Если не добавлять оператор break, то выполнение кода продолжится и в блоке case 100: . Благодаря этой особенности конструкции switch case имеется возможность объединения условий, для которых необходимо выполнить один и тот же код. Например:
int x = 100; bool check_x() { switch (x) { case 0: case 50: case 100: return true; default: return false; } }
Таким образом для x равного 0, 50, 100 функция вернёт true, тогда как для всех остальных значений функция будет возвращать false.
Также код для выбора case в этой конструкции можно оборачивать в блоки кода, что позволит ограничить область видимости и использовать объявление переменных с одинаковыми именами.
int x = 100; int check_x() { switch (x) { case 0: { int y = 1; return y; } case 50: { int y = 2; return y; } case 100: { int y = 3; return y; } default: return x; } }
Таким образом, ограничив область видимости, мы получаем возможность использовать переменные с одинаковыми именами в условиях case. Но не забывайте, что за пределами области видимости, ограниченной фигурными скобками переменная y в данном случае существовать не будет.
Операторы циклов
Оператор while
Оператор while повторяет код в своём теле до тех пор, пока выполняет условие. Например:
int i = 0; while (i < 10) { i = i + 1; }
В данном коде i будет равно 10 после выполнения цикла.
Оператор do
Оператор do используется совместно с оператором while и позволяет выполнить тело цикла хотя бы один раз, до того, как будет выполнена проверка условия цикла. Например:
int i = 15; do { i = i - 5; std::cout << i << std::endl; } while (i > 0 && i < 13);
В данном коде переменная I изначально не соответствует условию и в обычном цикле while код тела цикла не выполнился, но поскольку здесь используется do-while цикла, то проверка будет произведена после выполнения тела цикла. В результате вывод std::cout будет следующим:
10 5 0
Вы можете спросить, почему в выводе присутствует 0? Ведь это не подходит по условию. Опять же из-за того, что проверка выполняется после выполнения кода в теле цикла. То есть выполнилось тело цикла, а потом уже выполнилась проверка, по результату которой цикла завершает свою работу.
Оператор break
Как и в конструкции switch case, в циклах может использоваться этот оператор. Это необходимо для того, чтобы выйти из цикла, раньше, чем выполнится условие цикла. Например:
int i = 15; while (i < 50) { if (i < 0) { break; } i = i - 5; }
В данном искусственном примере получился бы вечный цикл из-за того, что переменная i уменьшается вместо увеличения, а по условию цикла выход будет произведён только в том случае, если i будет больше 50. Но благодаря оператору break и условию проверки на отрицательное значение переменной i выполнение программы выйдет из этого цикла, как только i станет меньше 0.
Оператор continue
Данный оператор позволяет прервать итерацию цикла и начать новую итерацию цикла до выполнения всего кода в теле цикла. Например:
int i = 0; while (i < 5) { if (i == 3) { i = i + 1; continue; } std::cout << i << std::endl; i = i + 1; }
При выполнении данного кода мы получим следующий вывод:
0 1 2 4
То есть вывод числа 3 будет пропущен.
Оператор for
Циклы с оператором for позволяют объединить инициализацию переменных, условие и изменение этих переменных.
То есть следующий цикл while
int i = 0; while (i < 10) {
Будет эквивалентен следующему циклу for:
for (int i = 0; i < 10; i++) { // ToDo Something }
Плюсом данного цикла for будет в том, что переменная I будет в локальной области видимости цикла for.
Циклы for могут инициализироваться несколькими переменными одного типа. Например:
for (int i = 0, *p = &i; i < 9; i += 2) { std::cout << i << ':' << *p << ' '; }
Также условие может быть объявлением, инициализацией переменной. Например:
char cstr[] = "Hello"; for (int n = 0; char c = cstr[n]; ++n) { std::cout << c; }
Учитывая стандарт C++11, в качестве типа переменной может использоваться оператор auto , который позволяет выводить тип переменной из инициализатора:
std::vector<int> v = {3, 1, 4, 1, 5, 9}; for (auto iter = v.begin(); iter != v.end(); ++iter) { std::cout << *iter << ' '; }
Также интересным моментом является то, что инициализатором, условием и блоком изменения может быть выражение:
int n = 0; for (std::cout << "Loop start\n"; std::cout << "Loop test\n"; std::cout << "Iteration " << ++n << '\n') { if(n > 1) break; }
Начиная со стандарта C++11, для циклов for добавлена возможность итераций по контейнерам, поддерживающим итерацию. Например, контейнер vector из стандартной библиотеки:
std::vector<int> v = {0, 1, 2, 3, 4, 5}; for (const int& i : v) std::cout << i << ' ';
В данном коде конструкция цикла следующая:
for (извлекаемый из контейнера при каждой итерации объект : контейнер) { // Тело цикла }
Также Range-based циклы for поддерживают оператор auto. Например:
std::vector<int> v = {0, 1, 2, 3, 4, 5}; for (auto& i : v) std::cout << i << ' ';