Основы программирования на языке C

         

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


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

/* истина и ложь*/ 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.



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


Когда в программе нужно осуществить выбор одного из нескольких вариантов, мы можем сделать это, используя конструкцию 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); }

где

e - целое выражение (или выражение, которое может быть преобразовано в целое выражение);ci - целое выражение с постоянным значением (или выражение, которое может быть преобразовано к такому выражению);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("%I",&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"); /* текст печатается красным цветом*/ } } getch () ; exit(0); /* функция берется из заголовочного файла process.h */ }



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




В языке Си имеется короткий способ записи одного из видов оператора 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


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

Пример:

/*подсчет строк */ #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 входят два оператора, поэтому мы использовали фигурные скобки, чтобы отметить начало и конец цикла.



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


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

/* занятость */ 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.



Расширение оператора 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> main( ) { char ch; while ((ch=getch( )) != EOF) { /* оставить символ "новая строка неизменным" */ if (ch == '\n') putchar(ch); else /* заменить остальные символы*/ putchar(ch + 1); } }

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

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

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


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;




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


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

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

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