Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
unsigned swt = get_bufCnt();
switch(swt) {
case ival:
bufsize = ival * sizeof (int);
break;
case jval:
bufsize = jval * sizeof(int);
break;
case kval:
bufsize = kval * sizeof(int);
break;
}
5.4. Итерационные операторы
Итерационные операторы (iterative statement), называемые также циклами (loop), обеспечивают повторное выполнение кода, пока их условие истинно. Операторы while и for проверяют условие прежде, чем выполнить тело. Оператор do while сначала выполняет тело, а затем проверяет свое условие.
5.4.1. Оператор while
Оператор while многократно выполняет оператор, пока его условие остается истинным. Его синтаксическая форма имеет следующий вид:
while (условие)
оператор
Пока условие истинно (значение true), оператор (который зачастую является блоком кода) выполняется. Условие не может быть пустым. Если при первой проверке условие ложно (значение false), оператор не выполняется.
Условие может быть выражением или объявлением инициализированной переменной (см. раздел 5.2). Обычно либо само условие, либо тело цикла должно делать нечто изменяющее значение выражения. В противном случае цикл никогда не закончится.
Переменные, определенные в условии или теле оператора while, создаются и удаляются при каждой итерации.
Использование цикла whileЦикл while обычно используется в случае, когда итерации необходимо выполнять неопределенное количество раз, например, при чтении ввода. Цикл while полезен также при необходимости доступа к значению управляющей переменной после завершения цикла. Рассмотрим пример.
vector<int> v;
int i;
// читать до конца файла или отказа ввода
while (cin >> i)
v.push_back(i); // найти первый отрицательный элемент
auto beg = v.begin();
while (beg != v.end() && *beg >= 0)
++beg;
if (beg == v.end())
// известно, что все элементы v больше или равны нулю
Первый цикл читает данные со стандартного устройства ввода. Он может выполняться сколько угодно раз. Условие становится ложно, когда поток cin читает недопустимые данные, происходит ошибка ввода или встречается конец файла. Второй цикл продолжается до тех пор, пока не будет найдено отрицательное значение. Когда цикл заканчивается, переменная beg будет либо равна v.end(), либо обозначит элемент вектора v, значение которого меньше нуля. Значение переменной beg можно использовать вне цикла while для дальнейшей обработки.
Упражнения раздела 5.4.1Упражнение 5.14. Напишите программу для чтения строк со стандартного устройства ввода и поиска совпадающих слов. Программа должна находить во вводе места, где одно слово непосредственно сопровождается таким же. Отследите наибольшее количество повторений и повторяемое слово. Отобразите максимальное количество дубликатов или сообщение, что никаких повторений не было. Например, при вводе how now now now brown cow cow вывод должен указать, что слово now встретилось три раза.
5.4.2. Традиционный оператор for
Оператор for имеет следующий синтаксис:
for (инициализирующий-оператор условие; выражение)
оператор
Слово for и часть в круглых скобках зачастую упоминают как заголовок for (for header).
Инициализирующий-оператор должен быть оператором объявления, выражением или пустым оператором. Каждый из этих операторов завершается точкой с запятой, поэтому данную синтаксическую форму можно рассматривать так:
for (инициализатор; условие; выражение)
оператор
Как правило, инициализирующий-оператор используется для инициализации или присвоения исходного значения переменной, изменяемой в цикле. Для управления циклом служит условие. Пока условие истинно, оператор выполняется. Если при первой проверке условие оказывается ложным, оператор не выполняется ни разу. Для изменения значения переменной, инициализированной в инициализирующем операторе и проверяемой в условии, используется выражение. Оно выполняется после каждой итерации цикла. Как и в других случаях, оператор может быть одиночным оператором или блоком операторов.
Поток выполнения в традиционном цикле forРассмотрим следующий цикл for из раздела 3.2.3:
// обрабатывать символы,
// пока они не исчерпаются или не встретится пробел
for (decltype(s.size()) index = 0;
index != s.size () && !isspace(s[index]); ++index)
s[index] = toupper(s[index]); // преобразовать в верхний регистр
Порядок его выполнения таков.
1. В начале цикла только однажды выполняется инициализирующий-оператор. В данном случае определяется переменная index и инициализируется нулем.
2. Затем обрабатывается условие. Если index не равен s.size() и символ в элементе s[index] не является пробелом, то выполняется тело цикла for. В противном случае цикл заканчивается. Если условие ложно уже на первой итерации, то тело цикла for не выполняется вообще.
3. Если условие истинно, то тело цикла for выполняется. В данном случае оно переводит символ в элементе s[index] в верхний регистр.
4. И наконец, обрабатывается выражение. В данном случае значение переменной index увеличивается 1.
Эти четыре этапа представляют первую итерацию цикла for. Этап 1 выполняется только однажды при входе в цикл. Этапы 2–4 повторяются, пока условие не станет ложно, т.е. пока не встретится символ пробела в элементе s или пока index не превысит s.size().
Не забывайте, что видимость любого объекта, определенного в пределах заголовка for, ограничивается телом цикла for. Таким образом, в данном примере переменная index недоступна после завершения цикла for.
Несколько определений в заголовке forПодобно любому другому объявлению, инициализирующий-оператор способен определить несколько объектов. Однако только инициализирующий-оператор может быть оператором объявления. Поэтому у всех переменных должен быть тот же базовый тип (см. раздел 2.3). Для примера напишем цикл, дублирующий элементы вектора в конец следующим образом:
// запомнить размер v и остановиться,
// достигнув первоначально последнего элемента
for (decltype(v.size()) i = 0, sz = v.size(); i != sz; ++i)
v.push_back(v[i]);
В этом цикле инициализирующий-оператор определяется индекс i и управляющая переменная цикла sz.
Пропуск частей заголовка forВ заголовке for может отсутствовать любой (или все) элемент: инициализирующий-оператор, условие или выражение.
Когда инициализация не нужна, вместо инициализирующего оператора можно использовать пустой оператор. Например, можно переписать цикл, который искал первое отрицательное число в векторе так, чтобы использовался цикл for:
auto beg = v.begin();
for ( /* ничего */; beg != v.end() && *beg >= 0; ++beg)
; // ничего не делать
Обратите внимание: для указания на отсутствие инициализирующего оператора точка с запятой необходима, точнее, точка с запятой представляет пустой инициализирующий оператор. В этом цикле for тело также пусто, поскольку все его действия осуществляются в условии и выражении. Условие решает, когда придет время прекращать просмотр, а выражение увеличивает итератор.
Отсутствие части условие эквивалентно расположению в условии значения true. Поскольку условие истинно всегда, тело цикла for должно содержать оператор, обеспечивающий выход из цикла. В противном случае цикл будет выполняться бесконечно.
for (int i = 0; /* нет условия */ ; ++i) {