Четверг, 25.04.2024, 04:00
Приветствую Вас Гость | RSS

Программирование на ЯВУ

Меню сайта
Статистика

Онлайн всего: 1
Гостей: 1
Пользователей: 0
Форма входа

Лекция 7

Выбор вариантов

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

  1. Выполнение последовательности операторов.
  2. Выполнение определенной последовательности операторов до тех пор, пока некоторое условие истинно.
  3. Использование проверки истинности условия для выбора между различными возможными способами действия.

Первая форма нам уже хорошо известна. Все наши предшествующие программы представляли собой некоторую последовательность операторов. Цикл while служит одним из примеров использования второй формы, другие способы будут рассмотрены в следующей лекции. Последняя форма делает программы гораздо более интеллектуальными, и чрезвычайно увеличивает эффективность работы компьютера

Оператор if

Подсчитаем число строк в файле. Это можно сделать путем счета числа символов "новая строка" в файле.

Пример:

/*подсчет строк */
#include <stdio.h>
main( )
{
 int ch;
 int line_count=0;
 while((ch = getchar( )) != EOF)
 if(ch == '\n') line_count++;
 printf("Мы насчитали %d строк. \n", line_count);
}

Оператор if служит указанием компьютеру увеличить значение переменной line_count на 1, если только что прочитанный символ, содержимое переменной ch, представляет собой символ "новая строка". Что происходит в случае, когда значение переменной ch не является символом "новая строка"? Тогда в цикле while производится чтение следующего символа. Оператор if считается одиночным оператором, начинающимся от ключевого слова if и завершающимся символом "точка с запятой". Модифицируем программу. Подсчитаем одновременно число символов и строк в файле:

/* подсчет числа строк и символов */
#include <stdio.h>
main( )
{
 int ch = 0;
 int line_count = 0;
 int char_count = 0;
 while((ch = getchar( )) != EOF) {
 char_count++;
 if(ch == '\n')
 line_count++;
 }
 printf("Мы насчитали %d символов и %d строк.\n",
 char_count, line_count);
} 

Теперь в цикл while входят два оператора, поэтому мы использовали фигурные скобки, чтобы отметить начало и конец цикла.

Расширение оператора if

Простейшей формой оператора if является

if(выражение)
оператор

Под выражением здесь понимаем условное выражение. С его помощью сравниваются значения двух величин. Если такое выражение истинно, то оператор выполняется. В противном случае он пропускается. В общем случае в качестве условия может быть использовано любое выражение, и если его значение равно 0, то оно считается ложным.

Оператор может быть простым или составным, т. е. блоком.

Пример:

/* пример одиночного оператора и блока */
#include <stdio.h>
main( )
{
 int i;
 i=getchar( );
 if(i > 5) 
 /* одиночный оператор*/
 printf("Значение больше 5.\n"); 
 if(i < 5) {
 /* составной оператор*/
 printf("Значение\n");
 printf(" меньше 5.\n");
 }
} 

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

Напишем программу, заменяющую каждый символ из таблицы ASCII на следующий символ, кроме символа "новая строка".

Пример:

/* код_1*/
#include <stdio.h>
int main( )
{
 char ch;
 while ((ch=getchar( )) != EOF) {
 /* оставить символ "новая строка неизменным" */
 if (ch == '\n') 
 putchar(ch); 
 else
 /* заменить остальные символы*/
 putchar(ch + 1); 
 }
}

Общий вид оператора if-else выглядит следующим образом:

if(выражение)
 оператор
else
 оператор

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

!Правила языка Си не требуют отступа в строке, но это стало обычной практикой. Отступ позволяет с первого взгляда заметить те операторы, выполнение которых зависит от проверяемого условия.

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

Подведем итоги.

Оператор if имеет две формы:

if(выражение) оператор;

и

if(выражение)
 оператор1;
else
 оператор2;

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

Совместное использование обеих форм оператора if приводит к неоднозначности, называемой "проблемой висящего else".

Например, вложенный оператор if

if(e1) if( e2) оператор1; else оператор2;

может быть интерпретирован так

if (e1)
 if(e2)
 оператор1;
 else
 оператор2;

или так

if(e1)
 if(e2) оператор1;
else
 оператор2;

Эта неоднозначность разрешается в языке Си с помощью правила, в соответствии с которым часть else оператора всегда относится к синтаксически самому правому, игнорируя любые отступы, оператору if без части else. Следовательно, первая интерпретация является интерпретацией, принятой в языке Си.

!Существует простой способ, позволяющий избавиться от такой неоднозначности: следует избегать одновременного использования обеих форм операторов if в конструкциях с вложенными операторами if. При необходимости можно воспользоваться пустым оператором. Например, вторая интерпретация вышеприведенного оператора if может быть записана как
if(e1)
if(e2) оператор1;
else
; /* точка с запятой здесь обозначает пустой
оператор*/
else оператор2;

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

if(e1) {
 if(e2)
 оператор1;
 else
 оператор2
}

и

if(e1) {
 if(e2) оператор1;
}
else
 оператор2;

Операции отношения

Операции отношения используются для сравнений. Мы уже обсуждали их, но здесь мы остановимся на их обсуждении подробнее.

Операциясмысл
<меньше
<=меньше или равно
==равно
>=больше или равно
>больше
!=не равно

Этот список хорошо соответствует возможным числовым соотношениям.

!Главное предостережение, которое мы хотим сделать, состоит в том, чтобы не использовать знак = вместо ==. С помощью операции присваивания некоторое значение присваивается переменной слева от знака равенства. В то же время с помощью операции отношения "равенство" проверяется: равно ли выражение, стоящее слева от знака, выражению справа от него. Эта операция не изменяет значения переменной в левой части, если она там присутствует. При программировании требуется аккуратность, потому что в ряде случаев компилятор не сможет обнаружить ошибки, связанные с неправильным использованием знаков этих отношений, что приведет к результатам, отличным от тех, которые вы должны были бы получить.

Операции отношения применяются при формировании условных выражений, используемых в операторах if и while. Указанные операторы проверяют, истинно или ложно данное выражение.

Пример:

#include <stdio.h>
main( ) 
{
 int mark;
 mark = getchar( );
 if(mark == '4')
 printf("Оценка 4.\n");
 else if (mark > '4')
 printf("Оценка больше 4!\n");
 else /* случай, когда оценка меньше 4 */
 {
 mark--;
 printf("Теперь оценка на 1 меньше.\n");
 }
}

Что такое истина

Мы ответим на этот вопрос, как он решается в языке Си. В Си выражение всегда имеет значение. Это утверждение остается верным даже для условных выражений, как показывает пример, приведенный ниже. В нем определяются значения двух условных выражений, одно из которых оказывается истинным, а второе - ложным:

/* истина и ложь*/
main( )
{
 int true, false;
 true = (12 > 2); /*отношение истинно*/
 false = (12 == 2) ; /*отношение ложно*/
 printf("true = %d; false = %d\n",true,false);
}

При выполнении программы получим следующие результаты:

true = 1, false = 0.

В языке Си значение истина равно 1, а значение ложь равно 0. В языке Си все ненулевые значения являются истинными, и только 0 являются ложью. Например, два оператора

if(i !=0 ) 

можно заменить на

if(i)

поскольку выражение (i !=0 ) и выражение (i) оба примут значения 0, или ложь, только в том случае, если значение переменной i равно 0.

Осложнение с понятием истина

Рассмотрим следующую программу:

/* занятость */
#include <stdio.h>
main( )
{
 int age =20;
 while (age++ <= 63) {
 /* делится ли возраст на 20*/
 if((age % 20) == 0) 
 printf(" Вам %d.\n", age);
 if(age = 63)
 printf("Вам уже %d.\n",age);
 }
}

Мы хотели написать программу, чтобы результат работы программы выглядел так:

Вам 40.
Вам 60.
Вам уже 63.

На самом деле выход будет таким:

Вам уже 63.
Вам уже 63.
Вам уже 63.

и т. д. - до бесконечности. Это произошло, потому что мы ошибочно написали

if(age = 63)

вместо

if(age == 63)

В операторе

if(age = 63) 

переменной age присваивается значение 63, т. е. результат этого оператора - истина и выполняется оператор

printf("Вам %d.\n",age);

В операторе

while(age++ <= 63)

условие выполняется, и программа зацикливается.

Приоритеты операций отношения мы описали в лекции 3.

Логические операции

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

/* число символов */
main( )
{
 int ch;
 int count=0;
 while((ch=getchar( )) != EOF)
 if(ch !=' ' && ch != '\n' && ch != '\t')
 count++;
 printf("Всего %d непустых символов. \n", count);
}

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

Операция Смысл
&& И
|| ИЛИ
! НЕ

Если прочитанный символ - не пробел и не символ "новая строка", и не символ табуляции, то происходит увеличение значения переменной count на единицу. Все выражение будет истинным, если указанные три условия - истинны. В языке Си имеются три логические операции.

Операция условия: ?:

В языке Си имеется короткий способ записи одного из видов оператора if-else. Он называется "условным выражением" и использует операцию условия - ?:. Эта операция состоит из двух частей и содержит три операнда. Рассмотрим, как можно найти абсолютное значение числа:

x = (y < 0) ? -y : y;

Все, что находится между знаком = и символом "точка с запятой" представляет собой условное выражение. Смысл этого оператора заключается в следующем: если y меньше 0, то x=-y; в противном случае x=y. В терминах оператора if-else данный оператор мог выглядеть так:

if (y < 0) x=-y;
else x=y;

В общем виде условное выражение можно записать следующим образом:

выражение1 ? выражение2 : выражение3

Если выражение1 истинно (не равно нулю), то значением всего условного выражения является величина выражение2; если выражение1 ложно (равно 0), то значение всего условного выражения - величина выражение3.

!Условное выражение удобно использовать в тех случаях, когда имеется некоторая переменная, которой можно присвоить одно из двух возможных значений. Использование условных выражений не является обязательным, поскольку тех же результатов можно достичь при помощи оператора if-else. Однако условные выражения более компактны, и их применение обычно приводит к получению более компактного машинного кода.

Множественный выбор

Когда в программе нужно осуществить выбор одного из нескольких вариантов, мы можем сделать это, используя конструкцию if-else if-else_...else Во многих случаях оказывается более удобным применять оператор switch.

Оператор switch (переключатель) используется для разветвления программы по нескольким направлениям. Он имеет следующую форму:

switch(e) {
 сase c1: s1; break;
 case c2: s2; break;
 ...
 case ck: sk; break;
 default: s(k+1);
}

где

  1. e - целое выражение (или выражение, которое может быть преобразовано в целое выражение);
  2. ci - целое выражение с постоянным значением (или выражение, которое может быть преобразовано к такому выражению);
  3. si обозначает операторы, число которых может быть больше или равно нулю.

Метки ci, обозначающие альтернативы case, должны быть уникальными; двух одинаковых меток быть не может. Только одна альтернатива может получить префикс default.

Результатом выполнения оператора switch является выбор альтернативы с меткой ci, которая равна значению выражения переключателя e; в этом случае выполняются операторы si. В случае, если выражение переключателя не равно ни одному из выражений альтернатив case, то выполняются операторы s(k+1); при отсутствии альтернативы default не выполняется ни одна из альтернатив оператора switch.

Пример:

/* Реализация работы калькулятора. Сначала задается 
число - сколько раз нужно подсчитать. Вводятся 
левый операнд, операция, правый операнд. Оператор 
выбора определяет, какой оператор должен работать. 
Результат выводится на экран. */
#include <stdio.h>
#include <conio.h>
#include <process.h>
main()
{
 float a,b;
 char opr;
 float result=0;
 int I,i=0;
 clrscr();
 printf("Сколько раз будете считать?:\n");
 scanf("%d",&I);
 printf("Введите операнд, операцию, операнд:\n");
 while(i<I) {
 i++;
 scanf("%f%c%f",&a,&opr,&b);
 switch(opr) {
 case '+': result=a+b; break; 
 case '-': result=a-b; break; 
 case '*': result=a*b; break; 
 case '/': result=a/b; break; 
 default:
 printf("Ошибка. Неверен знак операции "); 
 exit(1); /* функция берется 
 из заголовочного 
 файла process.h*/
 }
 textcolor (15); /* функция берется из
 заголовочного файла conio.h*/
 cprintf("Результат равен %g\n",result); 
 if (i<I)
 printf("Введите операнд, операцию, операнд\n"); 
 else
 {
 textcolor(12);
 /* функция берется из заголовочного файла
 conio.h */
 cprintf("Конец работы\n"); 
 /* текст печатается красным цветом*/
 }
 }
 getchar () ;
 exit(0); 
 /* функция берется из заголовочного файла
 process.h */
}
Поиск

Яндекс.Метрика