Выбрать главу

5.3. Инструкция if

Инструкция if обеспечивает выполнение или пропуск инструкции или блока в зависимости от условия. Ее синтаксис таков:

if ( условие )

инструкция

условие заключается в круглые скобки. Оно может быть выражением, как в этом примере:

if(a+bc) { ... }

или инструкцией объявления с инициализацией:

if ( int ival = compute_value() ){...}

Область видимости объекта, объявленного в условной части, ограничивается ассоциированной с if инструкцией или блоком. Например, такой код вызывает ошибку компиляции:

if ( int ival = compute_value() ) {

// область видимости ival

// ограничена этим блоком

}

// ошибка: ival невидим

if ( ! ival ) ...

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

* Сравнить элемент с текущим значением минимума.

* Если элемент меньше, присвоить текущему минимуму значение элемента и сбросить счетчик в 1.

* Если элемент равен текущему минимуму, увеличить счетчик на 1.

* В противном случае ничего не делать.

* После проверки последнего элемента вернуть значение минимума и счетчика.

Необходимо использовать две инструкции if:

if ( minVal ivec[ i ] )...// новое значение minVal

if ( minVal == ivec[ i ] )...// одинаковые значения

Довольно часто программист забывает использовать фигурные скобки, если нужно выполнить несколько инструкций в зависимости от условия:

if ( minVal ivec[ i ] )

minVal = ivec[ i ];

occurs = 1; // не относится к if!

Такую ошибку трудно увидеть, поскольку отступы в записи подразумевают, что и minVal=ivec[i], и occurs=1 входят в одну инструкцию if. На самом же деле инструкция

occurs = 1;

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

if ( minVal ivec[ i ] )

{

minVal = ivec[ i ];

occurs = 1;

}

Вторая инструкция if выглядит так:

if ( minVal == ivec [ i ] )

++occurs;

Заметим, что порядок следования инструкций в этом примере крайне важен. Если мы будем сравнивать minVal именно в такой последовательности, наша функция всегда будет ошибаться на 1:

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. Таким образом, в действительности предыдущий фрагмент означает следующее: