Программирование разветвляющихся алгоритмов

Условная инструкция

Условная инструкция – это инструкция управления реализующая алгоритмическую структуру “ветвление”. Синтаксически условная инструкция (далее – инструкция if) записывается следующим образом:

if (выражение)
{
    // Инструкции, если условное выражение
    // принимает значение "истинно" или не равно 0 
}
else
{
    // Инструкции, если условное выражение
    // принимает значение "ложь" или равно 0   
}

Выше описана полная форма условной инструкции if. В неполной форме блок на else отсутствует. Выражение-условие следует после служебного слова if и всегда заключается в круглые скобки.
Выражение-условие – это логическое выражение или выражение скалярного типа. Если выражение принимает значение true или любое ненулевое значение, то будут выполняться инструкции, находящиеся в блоке if. Если выражение принимает значение false или 0, то будут выполняться инструкции, находящиеся в блоке else. Если в блоке более одной инструкции, то эта группа инструкций называется составной и должна обязательно заключаться в фигурные скобки.
Фигурные скобки в C++ определяют область видимости данных. Те данные, которые определяются внутри фигурных скобок будут недоступными вне этих скобок. Например:
Программа 8.4.1

#include <iostream>

int main() {
    if (true) {
    	int x = 12;
    }
    cout << x << endl;
    return 0;
}

Такая программа содержит одну ошибку (попытка использования неопределенного объекта) и одно предупреждение (переменная x не используется). Иными словами, переменная x, объявленная в блоке if, не видна вне этого блока.
Для более компактного оформления программного кода мы будем использовать следующий стиль написания инструкции if (стиль Java):

if (...) {
    //...
} else {
    //...
}

Неполная форма инструкции if

Неполная форма ветвления используется столь же часто, как и полная. Приведем примеры нескольких задач.
Программа 8.4.2 На вход программе подаются 4 числа определить количество положительных чисел в исходном наборе. Если таких чисел нет, то сообщить об этом.

#include <iostream>
using namespace std;

int main() {
    int a, b, c, d;
    cout << "a = "; cin >> a;
    cout << "b = "; cin >> b;
    cout << "c = "; cin >> c;
    cout << "d = "; cin >> d;
    int i = 0;    
    if (a > 0) ++i;
    if (b > 0) ++i;
    if (c > 0) ++i;
    if (d > 0) ++i;
    if (i) cout << "Количество положительных "
                   "чисел равно " << i << endl;
    if (!i) cout << "Положительных чисел - нет!" << endl; 
    return 0;
}

Обсуждение. Если счетчик i не изменит своего значения после прохождения каскада инструкций if, то его значение так и останется нулевым. Результат операции !itrue, если значение i == 0 (логическое отрицание).
Программа 8.4.3 Даны три числа. Определить максимальное из этого набора.

#include <iostream>
using namespace std;

int main() {
    int a, b, c;
    cout << "a = "; cin >> a;
    cout << "b = "; cin >> b;
    cout << "c = "; cin >> c;
    int max = a;    
    if (b > max) max = b;
    if (c > max) max = c;
    cout << "Максимальное из трех чисел" << max << endl; 
    return 0;
}

Обсуждение. Предположим, что max – это первое введенное число, тогда сверим с max и остальные два. Если какое-то из двух значений больше max, переприсвоим значение max.

Задачи с использованием полной формы инструкции if

Решим простую задачу. Даны две переменные целого типа. Присвоить переменной с меньшим значением большее. Вывести новые значения переменных.
Программа 8.4.4

#include <iostream>
using namespace std;

int main() {
    int a, b;
    cout << "a = "; cin >> a;
    cout << "b = "; cin >> b;   
    if (a > b)
        b = a;
    else
        a = b;
    cout << "a = " << a
         << "b = " << b
         << endl; 
    return 0;
}

Даны два действительных числа a и b. Возвести в третью степень большее из них и в четвертую степень меньшее. Вывести новые значения a и b.
Программа 8.4.5

#include <iostream>
#include <cmath>
using namespace std;

int main() {
    double a, b;
    cout << "a = "; cin >> a;
    cout << "b = "; cin >> b;
    if (a > b) {
        a = pow(a, 3);
        b = pow(b, 4);
    } else {
        a = pow(a, 4);
        b = pow(b, 3);
    }
    cout << "a = " << a << "\n"
         << "b = " << b << endl;
    return 0;
}
Обратите внимание, что после фигурной скобки блока точка с запятой не ставится.

Многообразие способов записи ветвлений

Поскольку ветвление предполагает максимум два пути решения, то часто приходится вставлять одно ветвление внутрь другого, то есть применять вложенные ветвления (частный случай – это инструкция switch, с которой мы познакомимся позднее).
Глубина вложенности, впринципе, не ограничена, но на практике следует избегать инструкций слишком глубокой вложенности. Это может привести к нечитаемости алгоритма и трудно выявляемым ошибкам. Подумайте как упростить задачу.
Пример задачи. Дана точка A с координатами x и y. Определить, какой координатной четверти принадлежит A.
Программа 8.4.6

#include <iostream>
using namespace std;

int main() {
    double x, y;
    cout << "x = "; cin >> x;
    cout << "y = "; cin >> y;
    cout << "Точка находится ";
    if (x > 0)
        if (y > 0)
            cout << "в I четверти.";
        else
            cout << "в IV четверти.";
    else
        if (y > 0)
            cout << "во II четверти.";
        else
            cout << "в III четверти.";
    cout << endl;
    return 0;
}

Обратите внимание, что при написании кода вложенные инструкции if оформляются с дополнительным отступом.

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

Программа 8.4.7 Даны коэффициенты a, b и c. Найдите вещественные корни квадратного уравнения, если вещественных корней нет – сообщите об этом.

#include <iostream>
#include <cmath>
using namespace std;

int main() {
    double a, b, c, x1, x2;
    cout << "a = "; cin >> a;
    cout << "b = "; cin >> b;
    cout << "c = "; cin >> c;
    double d = b * b - 4 * a * c;
    if (d > 0) {
        x1 = (-b - sqrt(d))/2/a;
        x2 = (-b + sqrt(d))/2/a;
        cout << "x1 = "   << x1
             << "\nx2 = " << x2
             << endl;
    } else {
        if (d < 0) {
            x1 = -b/2/a;
            cout << "x = " 
                 << x1 
                 << endl;
        } else {
            cout << "Уравнение не имеет корней."
                 << endl;
        }
    }
    return 0;
}
Print Friendly, PDF & Email

Comments are closed.