if ( minVal ivec[ i ] ) {

minVal = ivec[ i ];

occurs = 1;

}

// если minVal только что получила новое значение,

// то occurs будет на единицу больше, чем нужно

if ( minVal == ivec[ i ] )

++occurs;

Выполнение второго сравнения не обязательно: один и тот же элемент не может одновременно быть и меньше и равен minVal. Поэтому появляется необходимость выбора одного из двух блоков в зависимости от условия, что реализуется инструкцией if-else, второй формой if-инструкции. Ее синтаксис выглядит таким образом:

if ( условие )

инструкция1

else

инструкция2

инструкция1 выполняется, если условие истинно, иначе переходим к инструкция2. Например:

if ( minVal == ivec[ i ] )

++occurs;

else

if ( minVal ivec[ i ] ) {

minVal = ivec[ i ];

occurs = 1;

}

Здесь инструкция2 сама является if-инструкцией. Если minVal меньше ivec[i], никаких действий не производится.

В следующем примере выполняется одна из трех инструкций:

if ( minVal ivec[ i ] )

{} // пустая инструкция

else

if ( minVal ivec[ i ] ) {

minVal = ivec[ i ];

occurs = 1;

}

else // minVal == ivec[ i ]

++occurs;

Составные инструкции if-else могут служить источником неоднозначного толкования, если частей else больше, чем частей if. К какому из if отнести данную часть else? (Эту проблему иногда называют проблемой висячего else). Например:

if ( minVal = ivec[ i ] )

if ( minVal == ivec[ i ] )

++occurs;

else {

minVal = ivec[ i ];

occurs = 1;

}

Судя по отступам, программист предполагает, что else относится к самому первому, внешнему if. Однако в С++ неоднозначность висячих else разрешается соотнесением их с последним встретившимся if. Таким образом, в действительности предыдущий фрагмент означает следующее:

if ( minVal = ivec[ i ] ) {

if ( minVal == ivec[ i ] )

++occurs;

else {

minVal = ivec[ i ];

occurs = 1;

}

}

Одним из способов разрешения данной проблемы является заключение внутреннего if в фигурные скобки:

if ( minVal = ivec[ i ] ) {

if ( minVal == ivec[ i ] )

++occurs;

}

else {

minVal = ivec[ i ];

occurs = 1;

}

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

Вот первый вариант функции min(). Второй аргумент функции будет возвращать количество вхождений минимального значения в вектор. Для перебора элементов массива используется цикл for. Но мы допустили ошибку в логике программы. Сможете ли вы заметить ее?

#include vector

int min( const vectorint ivec, int occurs )

{

int minVal = 0;

occurs = 0;

int size = ivec.size();

for ( int ix = 0; ix size; ++ix ) {

if ( minVal == ivec[ ix ] )

++occurs;

else

if ( minVal ivec[ ix ] ) {

minVal = ivec[ ix ];

occurs = 1;

}

}

return minVal;

}

Обычно функция возвращает только одно значение. Однако согласно нашей спецификации в точке вызова должно быть известно не только само минимальное значение, но и количество его вхождений в вектор. Для возврата второго значения мы использовали параметр типа ссылка. (Параметры-ссылки рассматриваются в разделе 7.3.) Любое присваивание значения ссылке occurs изменяет значение переменной, на которую она ссылается:

int main()

{

int occur_cnt = 0;

vector int ivec;

// occur_cnt получает значение occurs

// из функции min()

int minval = min( ivec, occur_cnt );

// ...

}

Альтернативой использованию параметра-ссылки является применение объекта класса pair, представленного в разделе 3.14. Функция min() могла бы возвращать два значения в одной паре:

// альтернативная реализация

// с помощью пары

#include uti1ity

#include vector

typedef pairint,int min_va1_pair;

min_va1_pair

min( const vectorint ivec )

{

int minVal = 0;

int occurs = 0;

// то же самое ...

Перейти на страницу:

Похожие книги