Главная / Лекции / Основы алгоритмизации и программирования

Содержание данной главы
8.5. Операции, выражения и операторы.

Основными операциями языка Си считаются +, *, -, /, а также оператор присваивания =. Как и в языке Паскаль, в Си нет возведения в степень. Основные операции выполняются в Си также как и в Паскаль, но имеют несколько дополнений. Так, знак "-" может использоваться как унарная операция, изменяющая знак переменной на противоположный. Особое использование отличает операцию деления. Она может применяться как к целым, так и к вещественным числам. Если результат операции деления должен быть присвоен целочисленной переменной, то дробная часть просто отбрасывается. Это действие называется усечением. Если деление применяется к операндам разного типа, то целочисленное значение преобразуется к виду с плавающей точкой.
Среди наиболее распространенных операций Си можно выделить:
1) sizeof - она возвращает размер операнда, выраженный в байтах. Операндом может быть конкретная данная или тип данных. При использовании последнего, оно записывается в скобках.
2) деление по модулю (%). Используется в целочисленной арифметике. Ее аналогом в Паскаль является функция mod.
3) инкремент (++). Выполняет простое действие: увеличивает значение операнд на 1. Эта операция может быть записана в префиксной форме, когда символ "++" предшествует переменной, и в постфиксной форме, когда "++" следует за переменной. Эти формы различаются последовательностью приращения значения операнда.
Пример:
   a++;
   ++a;
   b=a++;
   b=++a;

Первые два оператора не имеют различий. В третьем примере сначала значение переменной a будет присвоено переменной b, а затем увеличено на 1. В четвертом примере сначала значение переменной a увеличится, а затем присвоится.
4) декремент (--). Существует в префиксной и постфиксной формах. Результат его действия - уменьшение значения оператора на 1.
Операции "++" и "--" имеют очень высокий приоритет исполнения. Выше только исполнение действий в скобках.
В языке Си существует несколько форм оператора присваивания:

Записи Действия
+= к переменной левой части прибавляется величина правой части
-= вычитается величина правой части из значения переменной левой части
*= умножается значение переменной левой части на величину правой части
/= делится значение переменной левой части на величину правой части
%= присваивается переменной левой части остаток от деления левой части на правую

Под выражением в языке Си понимают некоторую комбинацию операций и операндов. Важным свойством выражений является обязательное наличие у него значения. Из операторов языка Си можно составлять блоки. Операторы в блоке объединяются посредством фигурных скобок. Обычно в операторах и выражениях должны использоваться переменные и константы только одного типа. В Си употребление разных типов не прекратит исполнение программы. В этом случае будет активизирован набор правил для автоматического преобразования типов:
1) когда в выражении встречаются типы char и short, они автоматически преобразуются в int. Тип float преобразуется в double. Поскольку такие действия преобразуют к типу, обеспечивающему больший размер данных, то они называются повышением типа.
2) если операция выполняется над данными разных типов, то обе величины преобразуются к высшему из этих типов.
3) последовательность типов, упорядоченных по принципу от высшего к низшему выглядит так: long double, double, float, unsigned long, long, unsigned int, int.
4) в операторе присваивания окончательный результат вычислений преобразуется к типу переменной, которой присваивается вычисленный результат.
По мере возможности требуется избегать автоматического преобразования типов. При составлении выражения вы можете потребовать выполнение того вида преобразования, которое необходимо вам. Этот способ называется привидением типов и определяется следующим образом. Перед заданной величиной в круглых скобках записывается имя требуемого типа данных.
Пример:
   b=(int)3.3+4;


8.6. Директивы препроцессора.

Одной из самых распространенных директив является директива #define. Эта директива используется для определения назначения указанных в ней идентификаторов. Использование этой директивы внешне похоже на работу с константами. Каждая строка #define состоит из трех частей:
1) сама директива;
2) выбранная вами аббревиатура или идентификатор, который принято называть макрос;
3) подставляемые значения или список замены или тело.
Процесс начинающийся макросом и завершающийся процессом замены, называется макрорасширением.
Пример:
#include
#define TWO 2
#define FOUR TWO*TWO
#define PX printf ("x - это %d, \n", x)
int main (void)
{
   int x = TWO;
   PX;
   x = FOUR;
   PX;
}

При исполнении приведенной программы на этапе работы препроцессора происходят следующие замены: строка int x = TWO заменяется на int x = 2; строка PX на printf (…); x = FOUR на x = TWO*TWO, а затем на x = 2*2. На этом процесс макрорасширения заканчивается, т.е. на этапе препроцесса умножение не исполняется, а исполняются только предложенные подстановки.
Результатом работы программы будет вывод двух строк:
x - это 2
x - это 4

При объявлении директивой #define значений превышающих длину строки возможно разбиение значения на несколько строк с использованием символа "\".
Пример:
#include
#define PX printf ("Сегодня первой па\
рой - алгоритмизация.\n")
int main (void)
{
   PX
}

Если в приведенном примере перед слогом "рой" поставить несколько пробелов, то они будут выведены в результирующей строке. Используя аргументы директивы #define, можно создавать макросы функции, которые выглядят и действуют подобно функциям.
Пример:
#define SQUARE (x) x*x

Эта директива может быть использована в следующих операторах:
int x = 4;
int z;
1) z = SQUARE (2);
2) z = SQUARE (x);
3) z = SQUARE (x+2);
4) z = 100/SQUARE (2);

На этапе препроцесса первая запись будет заменена на z = 2*2; вторая на z = x*x; третья на z = x+2*x+2; четвертая на 100/2*2. Соответственно результатами будут значения: 4, 16, 14, 100.
Если в третьем случае необходимо исполнения действия (x+2)*(x+2), то подставляемое значение в директиве #define должно быть заменено на (x)*(x). При этом в четвертой записи получим z = 100/(2)*(2). Для исполнения этого действия как 100/(2*2) необходимо в директиве #define записать ((x)*(x)).
Иногда даже предусмотренные предосторожности не позволят обеспечить необходимый результат. Например, если в качестве аргумента используется инкремент или декремент.

8.7. Реализация циклов в языке Си.

Для реализации цикла с предусловием в языке Си используется ключевое слово while. Операторная часть может состоять как из одного оператора, так и из нескольких, объединенных фигурными скобками. В общем виде оператор можно записать так:
while (условие)
{
   оператор 1;
   оператор 2;
}

Операторная часть цикла повторяется до тех пор, пока условие не станет ложным или равным нулю. При составлении условий могут быть использованы следующие относительные операции: <, <=, ==, >=, >, !=. В условиях также можно использовать логические конструкции, которые в Си имеют следующий вид:
&& - логическое "И"
|| - логическое "ИЛИ"
! - логическое отрицание
Для реализации цикла с параметром используется ключевое слово for. В записи оператора используются 3 выражения, управляющие работой цикла. В общем виде цикл имеет следующую форму:
for (присвоение начального значения; проверяемое выражение; выражение изменяющее значение переменной) оператор;
Выражение присваивающее начальное значение выполняется только один раз перед первым действием в цикле. Затем оценивается проверяемое выражение. Затем вычисляется выражение изменяющее переменную цикла. Цикл for в Си - это цикл с предусловием.
Цикл с постусловием в Си реализуется ключевыми словами do и while. В общем случае оператор можно записать:
do
   оператор;
while (условие);

Задача: написать программу выводящую на экран следующую последовательность:
ABCDEF
BCDEF
CDEF
DEF
EF
F

#include
int main (void)
{
   const int a = 6;
   int i;
   char k;
   for (i=0; i<6; i++)
   {
      for (k='A'+i; k<'A'+a; k++)
         printf ("%c", k);
      printf ("\n");
   }
}


8.8. Условные и безусловные переходы в языке Си.

В языке Си оператор ветвления в общем виде имеет запись:
if (выражение)
   оператор;

Язык Си допускает использование конструкции if else, которая в общем виде имеет следующую запись:
if (выражение)
   оператор 1;
else
   оператор 2;

Язык Си также разрешает использование конструкции else if. В этом случае может возникнуть неправильное прочтение программы пользователем.
Пример:
if (выражение 1)
   if (выражение 2)
      оператор 1;
   else
      оператор 2;

В языке Си используется стенографическая запись одной из форм ветвления. Эта форма называется условным выражением и записывается условным оператором ?:
В общем виде условный оператор имеет две части и три операнда. Записать его можно следующим способом:
   (выражение1)? выражение2: выражение3;

Пример: требуется определить наибольшую из двух величин:
1 способ:
   if (a<b)
      max = b;
   else
      max = a;

2 способ:
   max = (a<b)?b:a;

Для разрешения ситуации с заранее известным числом исходов в языке Си используется конструкция выбор. В общем виде выбор записывается в следующем виде:
switch (выражение)
{
   case значение1:
      оператор1;
   case значение2:
      оператор2;
   default: оператор3;
}

Выбор в языке Си допускает краткую запись тех значений выражения, для которых исполняется одно и то же действие.
Пример:
switch (выражение)
{
   case значение1:
   case значение2:
      оператор1;
   case значение3:
      оператор2;
}

Язык Си может использовать следующие безусловные переходы или прерывания: break, continue и goto. Их использование в основном совпадает с использованием в Паскаль, а именно: break прерывает исполнение любого вида циклов, continue - завершает текущую итерацию цикла, goto - осуществляет переход по метке. В отличие от языка Паскаль, break может использоваться в Си для завершения выбора. Использование оператора goto в языке Си считается нежелательным. Метки специально не объявляются.

8.9. Использование массивов при реализации циклов.

Само понятие массива в языке Си не изменяется. При объявлении массива указывается общее имя элементов массива, размерность и его тип.
Пример:
   int a[20];

В данном случае последний элемент в массиве будет иметь индекс 19, т.к. обязательно нумерация начинается с нуля. Обращение к одному элементу организуется по имени массива и индексу элемента.
Каждая строка в языке Си является символьным массивом, но не всякий символьный массив является строкой. Строкой считается массив, последним значением которого будет нулевой элемент.


назад     содержание     на главную


Rambler's Top100
Hosted by uCoz