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 ];
occurs = 1;
int size = ivec.size();
for ( int ix = 1; ix size; ++ix )
{
if ( minVal == ivec[ ix ] )
++occurs;
else
if ( minVal ivec[ ix ] ){
minVal = ivec[ ix ];
occurs = 1;
}
}
return minVal;
}
int main()
{
int ia[] = { 9,1,7,1,4,8,1,3,7,2,6,1,5,1 };
vectorint ivec( ia, ia+14 );
int occurs = 0;
int minVal = min( ivec, occurs );
cout "Минимальное значение: " minVal
" встречается: " occurs " раз.\n";
return 0;
}
Результат работы программы:
Минимальное значение: 1 встречается: 5 раз.
В некоторых случаях вместо инструкции if-else можно использовать более краткое и выразительное условное выражение. Например, следующую реализацию функции min():
template class valueType
inline const valueType
min( valueType vall, valueType va12 )
{
if ( vall va12 )
return vall;
return va12;
}
можно переписать так:
template class valueType
inline const valueType
min( valueType vall, valueType va12 )
{
return ( vall va12 ) ? vall : va12;
}
Длинные цепочки инструкций if-else, подобные приведенной ниже, трудны для восприятия и, таким образом, являются потенциальным источником ошибок.
if ( ch == 'a' ||
ch == 'A' )
++aCnt;
else
if ( ch == 'e' ||
ch == 'E' )
++eCnt;
else
if ( ch == 'i' ||
ch == 'I' )
++iCnt;
else
if ( ch == 'o' ||
ch == '0' )
++oCnt;
else
if ( ch == 'u' ||
ch == 'U' )
++uCnt;
В качестве альтернативы таким цепочкам С++ предоставляет инструкцию switch. Это тема следующего раздела.
Исправьте ошибки в примерах:
(a) if ( ivall != iva12 )
ivall = iva12
else
ivall = iva12 = 0;
(b) if ( ivat minval )
minvat = ival;
occurs = 1;
(c) if ( int ival = get_value())
cout "ival = "
ival endl;
if ( ! ival )
cout "ival = 0\n";