Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C++ для начинающих.pdf
Скачиваний:
183
Добавлен:
01.05.2014
Размер:
3.97 Mб
Скачать

int iva1=512 jva1=1024, kva1=4096;

int bufsize; // ...

switch( swt ) { case ival:

bufsize = ival * sizeof( int );

break; case jval:

bufsize = jval * sizeof( int );

break; case kval:

bufsize = kval * sizeof( int );

break;

}

enum { illustrator = 1, photoshop, photostyler = 2 };

switch ( ival ) { case illustrator:

--i11us_1icense; break;

case photoshop: --pshop_1icense; break;

case photostyler: --psty1er_license;

(e)

break;

}

5.5. Инструкция цикла for

Как мы видели, выполнение программы часто состоит в повторении последовательности инструкций – до тех пор, пока некоторое условие остается истинным. Например, мы читаем и обрабатываем записи файла, пока не дойдем до его конца, перебираем элементы массива, пока индекс не станет равным размерности массива минус 1, и т.д. В С++ предусмотрено три инструкции для организации циклов, в частности for и while, которые начинаются проверкой условия. Такая проверка означает, что цикл может закончиться без выполнения связанной с ним простой или составной инструкции. Третий тип цикла, do while, гарантирует, что тело будет выполнено как минимум один раз: условие цикла проверяется по его завершении. (В этом разделе мы детально рассмотрим цикл for; в разделе 5.6 разберем while, а в разделе 5.7 – do while.)

Цикл for обычно используется для обработки структур данных, имеющих фиксированную длину, таких, как массив или вектор:

#include <vector> int main() {

int ia[ 10 ];

for ( int ix = 0; ix < 10; ++-ix ) ia[ ix ] = ix;

vector<int> ivec( ia, ia+10 ); vector<int>::iterator iter =

ivec.begin() ;

for ( ; iter != ivec.end(); ++iter ) *iter *= 2;

return 0;

}

for (инструкция-инициализации; условие; выражение )

Синтаксис цикла for следующий:

инструкция

инструкция-инициализации может быть либо выражением, либо инструкцией объявления. Обычно она используется для инициализации переменной значением, которое увеличивается в ходе выполнения цикла. Если такая инициализация не нужна или выполняется где-то в другом месте, эту инструкцию можно заменить пустой (см. второй из приведенных ниже примеров). Вот примеры правильного использования

// index и iter определены в другом

месте

for ( index =0; ...

for ( ; /* пустая инструкция */ ...

for ( iter = ivec.begin(); ...

for ( int 1o = 0,hi = max; ...

инструкции-инициализации:

for ( char *ptr = getStr(); ...

условие служит для управления циклом. Пока условие при вычислении дает true, инструкция продолжает выполняться. Выполняемая в цикле инструкция может быть как простой, так и составной. Если же самое первое вычисление условия дает false,

(... index < arraySize; ... ) (... iter !=

ivec.end(); ... ) (... *stl++ = *st2++; ... )

инструкция не выполняется ни разу. Правильные условия можно записать так:

(... char ch = getNextChar(); ... )

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

инструкции-инициализации. Если самое первое вычисление условия дает false,

( ... ...; ++-index ) ( ... ...; ptr = ptr-

>next )

( ... ...; ++i, --j, + +cnt )

выражение не выполняется ни разу. Правильные выражения выглядят таким образом:

( ... ...; ) // пустое выражение

const int sz = 24; int ia[ sz ];

vector<int> ivec( sz );

for ( int ix = 0; ix < sz; ++ix )

{

ivec[ ix ] = ix; ia[ ix ]= ix;

Для приведенного ниже цикла for

}

порядок вычислений будет следующим:

1.инструкция-инициализации выполняется один раз перед началом цикла. В данном примере объявляется переменная ix, которая инициализируется значением 0.

2.Вычисляется условие. Если оно равно true, выполняется составная инструкция тела цикла. В нашем примере, пока ix меньше sz, значение ix присваивается элементам ivec[ix] и ia[ix]. Когда значением условия станет false, выполнение цикла прекратится. Если самое первое вычисление условия даст false, составная инструкция выполняться не будет.

3.Вычисляется выражение. Как правило, его используют для модификации переменной, фигурирующей в инструкции-инициализации и проверяемой в условии. В нашем примере ix увеличивается на 1.

Эти три шага представляют собой полную итерацию цикла for. Теперь шаги 2 и 3 будут повторяться до тех пор, пока условие не станет равным false, т.е. ix окажется равным или большим sz.

В инструкции-инициализации можно определить несколько объектов, однако все они должны быть одного типа, так как инструкция объявления допускается только одна:

for ( int ival = 0, *pi = &ia, &ri = val;

ival < size; ++iva1, ++pi, ++ri )

// ...

Объявление объекта в условии гораздо труднее правильно использовать: такое объявление должно хотя бы раз дать значение false, иначе выполнение цикла никогда

#include <iostream>

int main()

{

for ( int ix = 0;

bool done = ix == 10; ++ix )

cout << "ix: " << ix << endl;

не прекратится. Вот пример, хотя и несколько надуманный:

}

Видимость всех объектов, определенных внутри круглых скобок инструкции for, ограничена телом цикла. Например, проверка iter после цикла вызовет ошибку

int main()

{

string word;

vector< string > text; // ...

for ( vector< string >::iterator iter = text.begin(), iter_end =

text.end();

iter != text.end(); ++iter )

{

if ( *iter == word ) break;

// ...

}

// ошибка: iter и iter_end невидимы if ( iter != iter_end )

компиляции8:

// ...

8 До принятия стандарта языка С++ видимость объектов, определенных внутри круглых скобок for, простиралась на весь блок или функцию, содержащую данную инструкцию. Например, употребление двух циклов for внутри одного блока

}

{

 

 

в

// верно для стандарта С++

 

 

ранних//версияхпредыдущихязыка вызываловерсиях ошибку:C++ - ошибка:определенаival определенаважды. В стандарте С++

 

ival

ival

 

данный текст дважды

является

 

синтаксически правилен, так как каждый экземпляр

 

локальнымforдля(intсвоегоivalблока.= 0; ival < size; ++iva1 ) // ...

 

 

 

for (int ival = size-1; ival > 0; ival ) // ...

 

 

Упражнение 5.8

(a)

for ( int *ptr = &ia, ix = 0; ix < size && ptr != ia +size;

++ix, ++ptr ) // ...

Допущены ли ошибки в нижеследующих циклах for? Если да, то какие?

(b)

for ( ; ; ) { if

( some_condition

)

break; // ...

}

(c)

for ( int ix = 0; ix < sz; ++ix )

// ...

if ( ix != sz )

// ...

(d)

int ix;

for ( ix < sz; ++ix ) // ...

(e)

for ( int ix = 0; ix < sz; ++ix, ++ sz )

// ...

Упражнение 5.9

Представьте, что вам поручено придумать общий стиль использования цикла for в вашем проекте. Объясните и проиллюстрируйте примерами правила использования каждой из трех частей цикла.

Упражнение 5.10

Дано объявление функции: