C++ - Страустрап Бьярн
Шрифт:
Интервал:
Закладка:
while ( выражение ) оператор do оператор while (выражение) for ( оператор выражение opt; выражение opt ) оператор
case константное_выражение : оператор default : оператор break ; continue ;
return выражение opt ;
goto идентификатор ; идентификатор : оператор
список_операторов: оператор оператор список_операторов
Заметьте, что описание является оператором, и что нет операторов присваивания и вызова процедуры. Присваивание и вызов функции обрабатываются как выражения.
3.3.1 Проверки
Проверка значения может осуществляться или оператором if, или оператором switch:
if ( выражение ) оператор if ( выражение ) оператор else оператор switch ( выражение ) оператор
В С++ нет отдельного булевского типа. Операции сравнения
== != « „= “ »=
возвращают целое 1, если сравнение истинно, иначе возращают 0. Не так уж непривычно видеть, что ИСТИНА определена как 1, а ЛОЖЬ определена как 0.
В операторе if первый (или единственный) оператор выпоняется в том случае, если выражение ненулевое, иначе выполнется второй оператор (если он задан). Отсюда следует, что в качестве условия может использоваться любое целое выражение. В частности, если a целое, то
if (a) // ...
эквивалентно
if (a != 0) // ...
Логические операции amp; amp; !! ! наиболее часто используются в условиях. Операции amp; amp; и !! не будут вычислять второй аргмент, если это ненужно. Например:
if (p amp; amp; 1«p-»count) // ...
вначале проверяет, является ли p не нулем, и только если это так, то проверяет 1«p-»count.
Некоторые простые операторы if могут быть с удобством
заменены выражениями арифметического if. Например:
if (a «= d) max = b; else max = a;
лучше выражается так:
max = (a«=b) ? b : a;
Скобки вокруг условия необязательны, но я считаю, что когда они используются, программу легче читать.
Некоторые простые операторы switch можно по-другому зписать в виде набора операторов if. Например:
switch (val) (* case 1: f(); break; case 2; g(); break; default: h(); break; *)
иначе можно было бы записать так:
if (val == 1) f(); else if (val == 2) g(); else h();
Смысл тот же, однако первый вариант (switch) предпочттельнее, поскольку в этом случае явно выражается сущность действия (сопоставление значения с рядом констант). Поэтому в нетривиальных случаях оператор switch читается легче.
Заботьтесь о том, что switch должен как-то завершаться, если только вы не хотите, чтобы выполнялся следующий case. Например:
switch (val) (* // осторожно case 1: cout «„ „case 1n“; case 2; cout „« «case 2n“; default: cout «« «default: case не найденn“; *)
при val==1 напечатает
case 1 case 2 default: case не найден
к великому изумлению непосвященного. Самый обычный спсоб завершить случай – это break, иногда можно даже использвать goto. Например:
switch (val) (* // осторожно
case 0: cout «„ „case 0n“; case1: case 1: cout „„ «case 1n“; return; case 2; cout «« «case 2n“; goto case1; default: cout «« «default: case не найденn“; return; *)
При обращении к нему с val==2 выдаст
case 2 case 1
Заметьте, что метка case не подходит как метка для упоребления в операторе goto:
goto case 1; // синтаксическая ошибка
3.3.2 Goto
С++ снабжен имеющим дурную репутацию оператором goto.
goto идентификатор; идентификатор : оператор
В общем, в программировании высокого уровня он имеет очень мало применений, но он может быть очень полезен, когда С++ программа генерируется программой, а не пишется непоредственно человеком. Например, операторы goto можно исползовать в синтаксическом анализаторе, порождаемом генератором синтаксических анализаторов. Оператор goto может быть также важен в тех редких случаях, когда важна наилучшая эффектиность, например, во внутреннем цикле какой-нибудь программы, работающей в реальном времени.
Одно из немногих разумных применений состоит в выходе из вложенного цикла или переключателя (break лишь прекращает вполнение самого внутреннего охватывающего его цикла или преключателя). Например:
for (int i = 0; i«n; i++) for (int j = 0; j«m; j++) if (nm[i][j] == a) goto found // найдено // не найдено // ...
found: // найдено // nm[i][j] == a
Имеется также оператор continue, который по сути делает переход на конец оператора цикла, как объясняется в #3.1.5.
3.4 Комментарии и выравнивание
Продуманное использование комментариев и согласованное использование отступов может сделать чтение и понимание прораммы намного более приятным. Существует несколько различных стилей согласованного использования отступов. Автор не видит никаких серьезных оснований предпочесть один другому (хотя как и у большинства, у меня есть свои предпочтения). Сказаное относится также и к стилю комментариев.
Неправильное использование комментариев может серьезно повлиять на удобочитаемость программы, Компилятор не понимает содержание комментария, поэтому он никаким способом не может убедиться в том, что комментарий
1. осмыслен,
2. описывает программу и
3. не устарел.
Непонятные, двусмысленные и просто неправильные комметарии содержатся в большинстве программ. Плохой комментарий может быть хуже, чем никакой.
Если что-то можно сформулировать средствами самого язка, следует это сделать, а не просто отметить в комментарии. Данное замечание относится к комментариям вроде:
// переменная "v" должна быть инициализирована.
//переменная"v"должна использоваться только функцией «f()».
// вызвать функцию init() перед вызовом // любой другой функции в этом файле.
// вызовите функцию очистки «cleanup()» в конце вашей // программы.
// не используйте функцию «wierd()».
// функция «f()» получает два параметра.
При правильном использовании С++ подобные комментарии как правило становятся ненужными. Чтобы предыдущие комментрии стали излишними, можно, например, использовать правила компоновки (#4.2) и видимость, инициализацию и правила очиски для классов (см. #5.5.2).
Если что-то было ясно сформулировано на языке, второй раз упоминать это в комментарии не следует. Например:
a = b+c; // a становится b+c count++; // увеличить счетчик
Такие комментарии хуже чем просто излишни, они увеличвают объем текста, который надо прочитать, они часто затумнивают структуру программы, и они могут быть неправильными.
Автор предпочитает:
1. Комментарий для каждого исходного файла, сообщающий, для чего в целом предназначены находящиеся в нем комментарии, дающий ссылки на справочники и руководства, общие рекомендции по использованию и т.д.,
2. Комментарий для каждой нетривиальной функции, в ктором сформулировано ее назначение, используемый алгоритм (если он неочевиден) и, быть может, что-то о принимаемых в ней предположениях относительно среды выполнения,
3. Небольшое число комментариев в тех местах, где прорамма неочевидна и/или непереносима и
4. Очень мало что еще.
Например:
// tbl.c: Реализация таблицы имен /* Гауссовское исключение с частичным См. Ralston: «A first course ...» стр. 411. */
// swap() предполагает размещение стека AT amp;T sB20.
/**************************************
Copyright (c) 1984 AT amp;T, Inc. All rights reserved
****************************************/
Удачно подобранные и хорошо написанные комментарии – сщественная часть программы. Написание хороших комментариев может быть столь же сложным, сколь и написание самой програмы.
Заметьте также, что если в функции используются исключтельно комментарии //, то любую часть этой функции можно зкомментировать с помощью комментариев /* */, и наоборот.
3.5 Упражнения
1. (*1) Перепишите следующий оператор for в виде эквивалентного оператора while: for (i=0; i«max_length; i++) if (input_line[i] == '?') quest_count++;