Выполнение программы
Компьютерная программа — это последовательность инструкций, которые компьютер (вычислительная машина) будет исполнять. Иногда под программой понимают исходный код этой программы. Когда пользователь компьютера «запускает программу», он создаёт т.н. процесс, который соответствует этой программе. Процесс — выполнение инструкций программы. Кроме того, каждый процесс может иметь один или несколько потоков выполнения (англ. thread). Этот курс не подразумевает использования нескольких потоков, поэтому понятие процесс и поток будут взаимозаменяемыми.
Логично, что процесс должен начинать выполнение с какой-либо команды. Место программы, откуда начинается выполнение программы, называется точкой входа в программу. В C++ точка входа в программу может быть только одна и записывается в следующем виде:
int main() { return 0; };
Фигурные скобки, {}, в С++ используются для группировки. В данном случае они указывают на начало и конец функции main, которая обязательно должна присутствовать
в программе, и с которой начинается работа программы. Точка с запятой (;) ставится после каждого оператора языка, например, после оператора «return», возвращающего значение 0 и, таким образом, завершающий программу. Целое значение, с которым завершается программа, называется кодом ошибки. Если код ошибки — 0, то такая программа завершилась успешно.
Разберём следующий код:
int main() { int addOne = 6; int addTwo = 8; return 0; int sum = addOne + addTwo; };
Внутри блока объявляются 3 переменные: addOne, addTwo и sum. Так как объявление переменной sum стоит после оператора return, то программа завершится ещё до того, как сможет узнать про существование переменной sum. Таким образом, sum не будет ни создана, ни инициализирована.
Операторы ветвления (выбора)
Часто необходимо выполнить (или не выполнить) последовательность команд в зависимости от осуществления какого-либо условия. К примеру, модуль любого числа равен самому числу, если оно не меньше 0, и самому числу, взятому с обратным знаком, в противном случае:
Перепишем это условие на языке C++
int main() { int value = 6;// Исходное значение X int result;// Сюда сохраним результат if (value >= 0) { // Если X ≥ 0, result = value; // тогда сохраняем само число } else { // Иначе result = -value; // его же, взятым с обратным знаком }; return 0; };
Ветвь else является необязательной. В этом случае оператор if ограничивает блок кода, который может быть выполнен только при наступлении определённого условия. Операторы if могут быть вложенными. Это позволяет использовать 2 и более ограничений. Листинг 4 реализует вычисление результата для следующей функции:
int main() { int value = 6; int result = 0; if (value >= 1) { result = value - 1; } else if (value < -1) { result = -value - 1; } else { result = 0; }; return 0; };
В этом примере во внешнем блоке if (value >= 1)
в части else
располагается внутренний блок if (value < -1)
. Внешний блок выбирает все значения не меньшие 1, тогда как внутренний делит оставшееся множество (т.е. все значения меньшие 1) на два: на множество значений, меньшие –1 и множество не меньшее –1 и меньшее 1.
На заметку
В языке программирования Python комбинация else if была заменена на сокращённый вариант elif. Также в Python отказались от оператора выбора switch, т.к. с помощью оператора if-elif-else легко реализуется его функциональность.
Кроме оператора if существует оператор выбора switch:
int main() { char op = ‘-’; float result = 0.0; float a = 4.0, b = 3.0; switch (op) { case ‘+’: result = a + b; break; case ‘-’: result = a - b; case ‘*’: result = a * b; break; case ‘/’: result = a / b; break; default: /* Вывести ошибку */; }; return 0; };
В круглых скобках после switch записывается любая переменная целого типа (или типа, который может быть представлен, как целочисленный). В фигурных скобках перечисляются значения, с которыми будет происходит сравнение переменной. Выполнение начнётся с той ветви, в которой произошло совпадение (в примере это ‘–’). Оператор break устанавливается для того, чтобы поток программы закончил выполнение ветвей и продолжил работу за закрывающейся фигурной скобкой. Поэтому в приведённом примере забытый оператор break приведёт к ошибке, т.к. после того, как будет вычислена разность поток программы перейдёт на следующую ветвь и выполнит умножение.
Необязательная ветвь default выполнится в том случае, если значение переменной не совпала не с одним из перечисленных в case-ветвях.
На заметку
Часто программисты используют перечисления для использования с оператором switch. Это достаточно правильное и умное использование оператора switch. Более того, достаточно умные компиляторы способны во время компиляции проверить, все ли значения перечисления были учтены, и сообщить об этом программисту.
Циклы
Циклы позволяют выполнять один и тот же блок кода, пока выполняется определённое условие. В языке C++ существует 3 цикла: while, for и do-while. Первые два являются циклами с предусловием, последний — с постусловием. Когда некоторое логическое условие цикла истинно, то начинает выполняться тело цикла. Программисту необходимо следить, чтобы цикл мог когда-нибудь закончиться, т.е. рано или поздно
логическое условие должно стать ложным, иначе программа «зациклится».
Цикл while трактуется так: «пока логическое условие верно, выполнять блок кода». В коде синтаксически записывается следующим образом:
int main() { string text = “So beautiful text!”; int pos = 0; while (text[pos] != ‘t’) { pos++; }; return 0; };
Если символ справа логического неравенства есть в искомой строке найден, то выполнение цикла прекратиться и переменная pos будет иметь значение позиции, в которой находится этот символ. Если же такого символа не будет вовсе, тогда программа завершится с ошибкой.
Синтаксис оператора цикла for следующий:
int main() { int arr1[] = {2, 5, 7}; int arr2[3]; for (int i = 0; i < 3; i++) { arr2[i] = arr1[i]; }; return 0; };
Оператор цикла for в данном случае имеет следующее значение: «присвоить переменной i значение 0; пока i меньше 3-х копировать i-й элемент массива и увеличить i на 1». Все три части оператора (присвоение переменной значения, проверка логического условия и изменение переменной) могут быть опущены по желанию программиста, т.е. заменены на пустой оператор.
Запись for (int i = 0; i < 3; i++) {};
и
int i = 0; while (i < 3) { i++; };
одинаковы.
Условие цикла do-while проверяется после того, как блок кода будет выполнен, другими словами, определённый кусок кода будет выполнен хотя бы один раз, тогда как в циклах с предусловием он может не выполниться вовсе. Синтаксически цикл записывается так:
do { // выполнить хотя бы один раз } while (true);
Отметим, что при приведённой записи код будет выполняться бесконечно, так как логическое условие состоит только из значения true. Чтобы выйти из цикла можно внутри блока воспользоваться уже знакомым оператором break, позволяющий прервать выполнение цикла с любого места. Кроме оператора break существует оператор continue, который завершает текущую итерацию и переходит к выполнению следующей итерации
цикла.
Область видимости переменной
Объявление переменной вводит имя в область видимости (scope); это значит, что имя можно использовать лишь в ограниченной части программы. Для имени, объявленного в конкретном блоке кода (его называют локальным), область видимости простирается от точки объявления до конца содержащего это объявление блока.
Переменная называется глобальной, если она объявлена вне функции main и других блоков кода. Чтобы отличить глобальную переменную от локальной можно использовать два двоеточия перед её именем. Лучше вовсе избегать использования глобальных переменных во избежания перекрытия имён и случайного изменения в коде значения глобальной переменной, вместо локальной.
Следующий код полностью поясняет все возможные ситуации:
int global = 5; // создание глобальной переменной int main() { int global = 4; // создание локальной переменной global; // =4, вызов локальной переменной ::global; // =5, вызов глобальной переменной int outer = 0; // создание локальной переменной { // начало внутреннего блока outer; // =0, вызов лок. переменной внешнего блока float outer = 3.0; // перекрытие имени внеш. перемен. outer; // =3.0 вызов лок. переменной типа float int inner = 2; // создание лок. внутр. переменной inner; // =2, вызов лок. переменной } // inner; // ошибка! Такой переменной в этом блоке нет. // float outer; // ошибка! Такая переменная уже существует return 0; };