- •Вложенные циклы и двумерные массивы
- •Инициализация двумерного массива
- •Использование двумерного массива
- •Операторы Ветвления
- •Оператор if
- •If (проверочное-условие)
- •Оператор if else
- •Форматирование операторов if else
- •Конструкция if else if else
- •Условные операции и предотвращение ошибок
- •Логические выражения
- •Операция ?:
- •Оператор switch
- •Использование перечислителей в качестве меток
- •Операторы break и continue
Конструкция if else if else
В компьютерных программах, как и в жизни, иногда приходится выбирать из более чем двух вариантов. Оператор C++ if else можно расширить, чтобы он отвечало таким потребностям. Как уже говорилось, за else должен следовать единственный оператор, который может быть и блоком операторов. Поскольку конструкция if else сама является единым оператором, она может следовать за else:
if (ch == 'А' )
a_grade++; // альтернатива # 1
else
if (ch == 'B') // альтернатива # 2
b_grade++; // подальтернатива # 2a
else
soon++; // подальтернатива # 2b
Если значение ch не равно 'A', программа переходит к else. Там второй оператор if else разделяет эту альтернативу еще на два варианта. Свойство свободного форматирования C++ позволяет расположить эти элементы в более читабельном виде:
if (ch == 'А')
Вложенные циклы и двумерные массивы 1
Инициализация двумерного массива 3
Использование двумерного массива 4
Операторы Ветвления 7
Оператор if 7
Оператор if else 10
Форматирование операторов if else 13
Конструкция if else if else 15
Условные операции и предотвращение ошибок 16
Логические выражения 17
Операция ?: 27
Оператор switch 29
Использование перечислителей в качестве меток 35
Операторы break и continue 38
Это выглядит как совершенно новая управляющая структура — if else if else. Но на самом деле это один оператор if else, вложенный в другой. Пересмотренный формат выглядит намного яснее и позволяет даже при поверхностном взгляде оценить все альтернативы. Вся эта конструкция по-прежнему трактуется как единственный оператор.
8. Любимое число с подсказками.
Условные операции и предотвращение ошибок
Многие программисты превращают более интуитивно понятное выражение переменная == значение в значение == переменная, чтобы предотвратить ошибки, связанные с опечатками, когда вместо операции проверки равенства (==) вводится операция присваивания (=). Например, следующее условие корректно и будет работать правильно:
if (3 == myNumber)
Однако если допустить ошибку и ввести оператор, как показано ниже, то компилятор выдаст сообщение об ошибке, поскольку расценит это как попытку присвоить значение литералу (3 всегда равно 3, и ему нельзя присвоить ничего другого):
if (3 = myNumber)
Предположим, что сделана та же опечатка, но используется обычный формат:
if (myNumber = 3)
В этом случае компилятор просто присвоит значение 3 переменной myNumber, и блок внутри if будет выполнен — очень распространенная ошибка, которую трудно обнаружить. (Однако многие компиляторы будут выдавать предупреждение, на которое разумно обратить внимание.)
В качестве общего правила запомните следующее: написать код, позволяющий компилятору обнаружить ошибку, гораздо легче, чем разбираться с непонятными мистическими результатами неверного выполнения программ.
Логические выражения
Часто приходится проверять более одного условия. Например, чтобы символ относился к прописным буквам, его значение должно быть больше или равно ’ а ’ и меньше или равно ’ z ’. Либо же, если вы просите пользователя ответить у или n, то наряду с прописными должны приниматься и заглавные буквы (Y или N). Чтобы обеспечить такие возможности, C++ предлагает три логических операции, с помощью которых можно комбинировать или модифицировать существующие выражения: логическое “ИЛИ” (которое записывается как | | ), логическое “И” (записывается как &&) и логическое “НЕ” (записывается как !).
Рассмотрим каждую из них.
Логическая операция ”ИЛИ”: | |
В английском языке слово “or” (или) означает, что одно из двух условий либо оба сразу удовлетворяют некоторому требованию. Например, вы можете поехать на пикник, устроенный компанией Mega, если вы или ваш(а) супруг(а) работаете в этой компании. Эквивалент логической операции “ИЛИ” в C++ записывается как | |. Эта операция комбинирует два выражения в одно. Если одно или оба исходных выражения возвращают true или не ноль, то результирующее выражение имеет значение true (истина). В противном случае выражение имеет значение false. Ниже показаны некоторые примеры:
Поскольку | | имеет более низкий приоритет, чем операции сравнения, нет необходимости использовать в этих выражениях скобки. В табл. 6.1 показано, как работает операция | |.
В C++ предполагается, что операция | | является точкой следования. Это значит, что любое изменение, проведенное в левой части, вычисляется прежде, чем вычисляется правая часть. Например, рассмотрим следующее выражение:
i++ <6 | | i == j
Предположим, что изначально переменная i имела значение 10. К моменту сравнения с j переменная i получает значение 11. Таким образом, C++ не заботится о правой части выражения, если выражение слева истинно, потому что одного истинного выражения достаточно, чтобы все составное выражение было оценено как истинное.
В листинге используется операция | | внутри if для того, чтобы проверить заглавную и прописную версии символа. К тому же применяется средство конкатенации строк C++ для разнесения одной строки на три строки в коде.
#include <iostream>
int main()
{
using namespace std;
cout << "This program may reformat your hard disk\n"
"and destroy all your data.\n"
"Do you wish to continue? <y/n> ";
char ch;
cin >> ch;
if (ch == 'y' || ch == 'Y') // y or Y
cout << "You were warned!\a\a\n";
else if (ch == 'n' || ch == 'N') // n or N
cout << "A wise choice ... bye\n";
else
cout << "That wasn't a y or n! Apparently you "
"can't follow\ninstructions, so "
"I'll trash your disk anyway.\a\a\a\n";
getchar();
getchar();
return 0;
}
Эта программа читает только один символ, поэтому принимается во внимание только первый символ ответа. Это значит, что пользователь может ввести N0! вместо N, но программа прочитает только N. Но если ей пришлось бы читать еще входные символы, то первым оказался бы символ О.
Логическая операция “И”: &&
Логическая операция “И”, которая записывается как &&, также комбинирует два выражения в одно. Результирующее выражение имеет значение true только в том случае, когда оба исходных выражения также равны true.
Ниже приведены некоторые примеры:
Поскольку && имеет меньший приоритет, чем операции сравнения, нет необходимости использовать скобки. Подобно | |, операция && действует как точка следования, а потому возможны любые побочные эффекты перед тем, как будет вычислено правое выражение. Если левое выражение ложно, то и все составное выражение также ложно, поэтому в таком случае C++ можно не беспокоиться о вычислении правой части. Работа операции && описана в табл. 6.2.
while (i < ArSize && temp >= 0) // 2 quitting criteria
{
naaq[i] = temp;
++i;
if (i < ArSize) // room left in the array,
{
cout << "Next value: ";
cin >> temp; // so get next value
}
}
Установка диапазонов с помощью &&
Операция && также позволяет установить последовательность операторов if else if else, где каждый выбор соответствует определенному диапазону значений. В листинге иллюстрируется такой подход. В нем также демонстрируется полезная техника обработки серии сообщений.
#include <iostream>
int main()
{
using namespace std;
int age;
cout << "Enter your age in years: ";
cin >> age;
int index;
if (age > 17 && age < 35)
index = 0;
else if (age >= 35 && age < 50)
index = 1;
else if (age >= 50 && age < 65)
index = 2;
else
index = 3;
cout << "You qualify for the " << index;
getchar();
getchar();
return 0;
}
Логическая операция "НЕ": !
Операция ! выполняет отрицание, или обращает, истинность выражения, следующего за ней. То есть если expression равно true, то ! expression равно false, и наоборот. Точнее говоря, если expression имеет значение true, или ненулевое, то ! expression будет равно false.
Обычно выражение отношения можно представить яснее без применения операции !:
if ( ! (х > 5) ) //в этом случае if (х <= 5) яснее
Однако операция ! может быть полезна с функциями, которые возвращают значения true/false либо значения, которые могут интерпретироваться подобным образом. Например, strcmp (s1, s2) возвращает не ноль (true), если две строки в стиле С, s1 и s2, отличаются друг от друга, и ноль, если они одинаковы. Это значит, что !strcmp (s1, s2) равно true, если две строки эквивалентны.
В листинге 6.7 используется прием применения операции ! к значению, которое возвращается функцией проверки числового ввода на предмет возможности его присваивания типу int. Пользовательская функция isint (), которая будет рассматриваться позже, возвращает true, если ее аргумент находится в диапазоне допустимых значений для присваивания типу int. Затем программа применяет проверку условия while (! isint (num) ) , чтобы отклонить значения, которые не входят в диапазон.
#include <iostream>
#include <climits>
bool is_int(double);
int main()
{
using namespace std;
double num;
cout << "Yo, dude! Enter an integer value: ";
cin >> num;
while (!is_int(num))//continue while num is not int-able
{
cout << "Out of range -- please try again: ";
cin >> num;
}
int val = int (num); // type cast
cout << "You've entered the integer " << val << "\nBye\n";
getchar();
getchar();
return 0;
}
bool is_int(double x)
{
if (x <= INT_MAX && x >= INT_MIN) // use climits values
return true;
else
return false;
}
Замечания по программе
В случае ввода слишком большого значения при выполнении программы, читающей тип int, многие реализации C++ просто усекают значение, не сообщая о потере данных. Программа в листинге избегает этого за счет того, что читает потенциальное значение int как double. Тип double имеет более чем достаточную точность для того, чтобы сохранить обычное значение int, а его диапазон допустимых значений намного больше. Другим вариантом могло быть сохранение веденного значения в переменной типа long long, предполагая, что этот тип шире, чем int.
Булевская функция isint() использует две символические константы (INT_MAX и INT_MIN), определенные в файле climits, для проверки, что значение ее аргумента находится в допустимых пределах. Если это так, функция возвращает true; в противном случае — false.
В функции main () используется условие цикла для отклонения неправильного ввода пользователя. Можно сделать программу более дружественной за счет отображения допустимых границ int, когда введено неправильное значение. После проверки достоверности введенного значения программа присваивает его переменной типа int.
Факты, связанные с логическими операциями
Как упоминалось ранее в этой главе, логические операции “ИЛИ” и “И” в C++ обладают более низким приоритетом, чем операции сравнения. Это значит, что такое выражение, как
х > 5 && х < 10
интерпретируется следующим образом:
(х > 5) && (х < 10)
С другой стороны, операция “НЕ” (!) имеет более высокий приоритет, чем любая арифметическая операция и операция сравнения. Таким образом, для отрицания выражения его необходимо заключить в скобки:
! (х > 5) // равно false, если х больше 5
!х > 5 // равно true, если !х больше 5
Кстати, результатом второго из приведенных выражений всегда будет false, т.к. !х принимает значения true или false, что преобразуется, соответственно, в 1 и 0.
Логическая операция “И” имеет более высокий приоритет, чем логическая операция “ИЛИ”. Поэтому следующее выражение:
age > 30 && age <45 | | weight > 300
означает вот что:
(age > 30 && age < 45) | | weight > 300
Здесь первое условие говорит о том, что возраст должен быть от 31 до 44 лет включительно, а второе — что вес должен быть больше 300 (фунтов). Все выражение будет истинным, если истинно одно из выражений или оба сразу.
Разумеется, можно использовать скобки, чтобы явно указать программе, как следует интерпретировать выражение. Например, предположим, что вы хотите использовать && для комбинирования условий о том, что возраст (аде) должен быть больше 50 или вес (weight) — больше 300, с условием, что размер пожертвования (donation) должен быть больше 1000. Для этого часть “ИЛИ” потребуется поместить в скобки:
(аде >50 | | weight > 300) && donation > 1000
Иначе компилятор скомбинирует условие weight с условием donation, вместо того чтобы скомбинировать его с условием age.
Хотя правила приоритетов операций C++ часто позволяют писать составные выражения без использования скобок, все же проще всегда применять скобки для группирования проверок, независимо от того, нужны они или нет. Это улучшает читабельность кода, исключает неправильное понимание порядка приоритетов и снижает вероятность ошибки из-за того, что вы не помните точно правил приоритетов.
C++ гарантирует, что когда программа вычисляет логическое выражение, то делает это слева направо, и прекращает вычисление, как только ответ становится ясен.
Альтернативные представления
Не все клавиатуры предоставляют возможность ввода символов, используемых для обозначения логических операций, поэтому в стандарте C++ предусмотрены их альтернативные представления, которые показаны в табл. 6.3. Идентификаторы and, or и not являются зарезервированными словами C++, а это значит, что их нельзя использовать в качестве имен переменных и тому подобного. Они не рассматриваются как ключевые слова, потому что являются альтернативными представлениями существующих средств языка. Кстати, они не являются зарезервированными словами в С, но в программах на С они могут применяться в качестве операций только при условии включения заголовочного файла iso646.h. В C++ этот файл не требуется.