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;
// то же самое ...
return make_pair( minVal, occurs );
}
К сожалению, и эта реализация содержит ошибку. Где же она? Правильно: мы инициализировали minVal нулем, поэтому, если минимальный элемент вектора больше нуля, наша реализация вернет нулевое значение минимума и нулевое значение количества вхождений.
Программу можно изменить, инициализировав minVal первым элементом вектора:
int minVal = ivec[0];
Теперь функция работает правильно. Однако в ней выполняются некоторые лишние действия, снижающие ее эффективность.
// исправленная версия min()
// оставляющая возможность для оптимизации ...
int minVal = ivec[0];
occurs = 0;
int size = ivec.size();
for ( int ix = 0; ix size; ++ix )
{
if ( minVal == ivec[ ix ] )
++occurs;
// ...
Поскольку ix инициализируется нулем, на первой итерации цикла значение первого элемента сравнивается с самим собой. Можно инициализировать ix единицей и избежать ненужного выполнения первой итерации. Однако при оптимизации кода мы допустили другую ошибку (наверное, стоило все оставить как было!). Сможете ли вы ее обнаружить?
// оптимизированная версия min(),
// к сожалению, содержащая ошибку...
int minVal = ivec[0];
occurs = 0;
int size = ivec.size();
for ( int ix = 1; ix size; ++ix )
{
if ( minVal == ivec[ ix ] )
++occurs;
// ...
Если ivec[0] окажется минимальным элементом, переменная occurs не получит значения 1. Конечно, исправить это очень просто, но сначала надо найти ошибку:
int minVal = ivec[0];
occurs = 1;
К сожалению, подобного рода недосмотры встречаются не так уж редко: программисты тоже люди и могут ошибаться. Важно понимать, что это неизбежно, и быть готовым тщательно тестировать и анализировать свои программы.
Вот окончательная версия функции min() и программа main(), проверяющая ее работу:
#include iostream
#include vector
int min( const vector int ivec, int occurs )
{
int minVal = ivec[ 0 ];