Слайд 1ЛЕКЦИЯ №3
ЯЗЫК ПРОГРАММИРОВАНИЯ СИ
(ПРОДОЛЖЕНИЕ)
Представлен материал, который имеет отношение к основам
программирования на алгоритмическом языке СИ (алфавит, операции, операторы, комментарии и
другие элементы). Приводятся примеры программ, иллюстрирующие применение основных операторов СИ.
Операторы языка СИ
Программа на языке СИ представляет собой набор операторов разделенных между собой точкой с запятой (;). Оператор – последовательность символов, имеющая специальный смысл и предназначенная для кодирования команд, которые должна выполнить ЭВМ.
Структура программы. Программа представляет собой совокупность следую-щих элементов: директив препроцессора; указаний компилятору; объявлений и определений.
Директивы препроцессора специфицируют действия препроцессора по преобразованию текста программы перед компиляцией. Указания компилятору – специальные инструкции, которым должен следовать компилятор языка СИ во время компиляции программы.
Слайд 2 Для того, чтобы программа на языке СИ
была скомпилирована и выполнена, должна быть объявлена, по крайней мере,
одна функция и также определена основная функция с именем main. С нее всегда начинается выполнение любой программы.
Основным оператором программы является оператор присваивания, который имеет вид:
<идентификатор><операция присваивания>< выражение >; ,
где <выражение > – последовательность идентификаторов логически связанных операциями, порядок выполнения которых может регламентироваться круглыми скобками.
В качестве операции присваивания может быть использована одна из тех операций "*=", которые приведены в таблице 5. Основная операция присваивания в СИ обозначается символом "=".
Приведем в качестве иллюстрации текст программы, использующей выражения.
Программа 8:
#include
#include
void main (void)
{
int x, y, z, c, d;
clrsrc ();
Слайд 3 printf ("Введите x, y, z: ");
scanf ("%d %d
%d", &x, &y, &z);
c = x < y &&
y < z;
d = x == y || x == z;
printf ("c = %d d = %d\n", c, d);
}
Обращаю внимание на то, что с помощью операторов присваивания и выра-жений в программе вычисляются значения новых как вспомогательных, так и основных объектов (переменных). Фактически, используя их, проводятся расче-ты значений требуемых для определения величин.
В языке СИ определен также пустой оператор, который представляется сим-волом ";". Данный оператор необходим в тех случаях, когда по логике програм-мы должен быть оператор, но в тоже время требуется, чтобы ЭВМ в это время не производила ни каких операций.
Кроме того, при написании программ на СИ зачастую возникает ситуация, ког-да некоторую последовательность операторов необходимо объявить одним оператором. Данная проблема решается с помощью составного (сложного) оператора, под которым понимается некоторая последовательность операторов заключенная в фигурные скобки. При его написании выполняются следующие правила:
Слайд 4после составного оператора опускается точка с запятой, так как фигурная
скобка (}) является разделителем;
внутри составного оператора, каждый оператор заканчивается точкой
с запятой (;);
составной оператор может использоваться везде, где допускается использование любого оператора языка СИ.
С помощью описанных выше операторов присваивания, как правило, модели-руются линейные вычислительные процессы, так как если построить блок-схему алгоритма, использующего только их, то получим, что все операторы выстроятся в линию в порядке их следования в программе.
Операторы управления. Рассмотрим простейшую задачу о вычислении абсолютного значения некоторой вещественной переменной s. По определению абсолютной величины значение переменной s вычисляется по формуле
(18)
Результат вычисления зависит от некоторого условия (в нашем конкретном случае от s < 0). При этом следует отметить, что вычисления могут проводиться по двум формулам. Поэтому в некоторой точке алгоритма процесс вычислений пойдет по одному из двух возможных ветвей в зависимости от выполнения условия s < 0.
Слайд 5 Алгоритмы с подобными ветвлениями относятся к ветвящимся
вычислитель-ным процессам. Для их программирования в алгоритмическом языке программи-рования СИ
предназначена группа операторов управления или иначе их еще назы-вают условными операторами.
Оператор условия. Основным оператором, входящим в данную группу, является оператор условия, который имеет следующий вид:
if (<логическое выражение>) <оператор>; else <оператор>; ,
где <логическое выражение> – выражение, принимающее значение 0 или 1, <оператор> – один из выполняемых операторов языка СИ.
Он работает следующим образом, если логическое выражение неравно 0, то выполняется оператор, следующий за ним, иначе будет выполняться оператор, идущий после ключевого слова else. Его Блок-схема представлена на рис. 3а.
Для иллюстрации работы оператора условия составим программу, которая вычисляет мгновенную скорость и путь, пройденный телом за временя t, если известно, что оно двигается равноускоренно с ускорением a и его начальная скорость равна v0. Из анализа условия задачи, следует, что при проектировании алгоритма необходимо учесть физические ограничения на t (оно не может быть отрицательно) и на величину скорости v0, которая также не может принимать отрицательных значений. С учетом этих ограничений приведем блок-схему алгоритма рис. 9 и соответствующий текст программы.
Слайд 6Рис. 9. Блок-схема алгоритма
Слайд 7 Программа 9:
#include
#include
void main (void)
{
float a, t, v0, v ,s;
clrsrc ();
printf ("Введите
скорость v0 = ");
scanf ("%f", &v0);
if (v0 < 0)
{
printf ("Введите скорость v0 = ");
scanf ("%f", &v0);
}
else
{
printf ("Введите время t = ");
scanf ("%f", &t);
if (t < 0)
Слайд 8 {
printf ("Введите время
t = ");
scanf ("%f", &t);
}
else
{
printf ("Введите ускорение a = ");
scanf ("%f", &a);
v = v0 + a*t;
s = (v0 + 0.5*a*t)*t;
printf ("v = %f s = %f\n", v, s);
}
}
}
В операторе условия альтернативная часть, которая следует за ключевым словом else, может отсутствовать. Такой оператор называют укороченным оператором условия. Он имеет вид:
if (<логическое выражение>) <оператор>; .
На следующем рисунке приведена блок-схема, отражающая его работу на примере вывода только положительных значений вещественного числа b.
Слайд 9Рис. 10. Блок-схема алгоритма
Чтобы продемонстрировать его работу перепишем программу 9,
используя укоро-ченный оператор условия вместо полного.
Программа 10:
#include
#include
void main (void)
{
float a, t, v0, v, s;
clrsrc();
printf ("Введите скорость v0 = ");
scanf ("%f", &v0);
Слайд 10
if (v0 < 0)
{
printf
("Введите скорость v0 = ");
scanf ("%f", &v0);
}
printf ("Введите t = ");
scanf ("%f", &t);
if (t < 0)
{
printf ("Введите скорость t = ");
scanf ("%f", &t);
}
printf ("Введите ускорение a = ");
scanf ("%f", &a);
v = v0 + a*t;
s = (v0 + 0.5*a*t)*t;
printf ("\nv = %f s = %f\n", v,s);
}
Слайд 11 Фактически данная форма оператора условия используется в
тех случаях, когда по смыслу решаемой задачи после ключевого слова
else не требуется производить ни каких операций и естественно по этой причине эту часть оператора условия можно упустить.
Условная операция. В ряде случаев оператор условия может быть записан в форме условной операции, которая имеет следующий вид:
<результат> = (<логическое выражение>) ? < выражение > : <выражение > ,
где <результат> – имя переменной, которой присваивается значение одного из выражений, <логической выражение> – выражение, принимающее значение 0 или 1 и <выражение> – имена переменных логически связанных операциями языка СИ. Из его определения следует, что логическая операция задается симво-лами "?" и ":". Программа, решающая задачу (18), должна содержать условный оператор, который можно представить в форме условной операции.
Программа 11:
#include
#include
void main (void)
{
float s,rez;
clrsrc();
Слайд 12 printf ("\nВведите s = ");
scanf ("%f", s);
/* Переменная
rez вычисляется с помощью условной
операции */
rez =
(s < 0) ? –s : s;
printf ("\nrez = %f", rez);
}
Рассмотрим в качестве примера задачу: требуется найти наименьшее из двух целых чисел i и j. При ее решении, как и в предыдущем случае, удобнее использовать условную операцию (см. программу 12).
Программа 12:
#include
#include
void main (void)
{
int i, j, result;
clrsrc();
printf ("\nВедите целые числа i и j:");
scanf ("%d %d", &i,&j);
Слайд 13 result = (i < j) ? i : j;
printf ("\nrezult = %d", rezult);
}
Условная операция
– это наиболее краткая форма записи условного оператора. Однако начинающим программистам рекомендуется ее не использовать, так как она записывается в форме оператора присваивания и ничем не напоминает условный оператор. При этом также теряется логическая структура программы, что может привести к ошибкам восстановления логики алгоритма по ее тексту.
Оператор ключа. В группу условных операторов входит оператор ключа, который реализует ветвление на множество ветвей в зависимости от значения некоторого выражения. Он имеет следующий вид:
switch (<выражение>)
{
case <конст. выр. 1> :
<оператор>;
[break;]
case <конст. выр. 2> :
<оператор>;
[break;]
⋅
:
;
[break;]
[default:
<оператор>;]
}
Здесь <выражение> – выражение, принимающее некоторый набор значений, <конст. выр. i> – константа, отражающая i-ое значение из набора и являющаяся меткой, break – оператор прерывания, default – метка по умолчанию.
Операторы, заключенные в квадратные скобки как могут присутствовать, так и могут отсутствовать в операторе ключа. Принцип работы оператора ключа проще всего понять при рассмотрении его блок-схемы рис. б.
Оператор ключа работает следующим образом. Вычисляется значение выраже-ния, следующего за словом switch. Затем оно сравнивается с константными выра-жениями, стоящими после слов case. В случае совпадения с одним из них происхо-дит выполнение операторов, следующих за ним, до тех пор, пока не встретиться оператор break, который прерывает цепочку и отправляет к следующему операто-ру за switch. Если не произошло совпадения полученного значения ни с одним из константных выражений, то управление передается на метку default.
Слайд 15 Как видно из сравнения оператор ключа в
отличие от условного оператора позволяет осуществить разветвление алгоритма более чем
на две ветви и в ряде конкретных случаев его использование удобнее, чем условного оператора. Вет-вление более чем на две ветви также можно реализовать и с помощью вложенных друг в друга условных операторов.
Оператор перехода. Еще один оператор, входящий в группу операторов выбо-ра называется оператором перехода, который задается ключевым словом goto и имеет вид:
goto <метка>; .
Данный оператор еще называют "армейским", потому что он осуществляет переход к меченому оператору без всяких причин. Основные рекомендации по его использованию заключаются в том, чтобы как можно меньше употреблять его при написании любой программы. Дело в том, что излишнее его употребление, как правило, запутывает логику программы.
Итак, нами была рассмотрена группа операторов выбора, которые позволяют программировать так называемые ветвящиеся вычислительные процессы.
Операторы цикла. Предположим, что требуется написать программу, вычис-ляющую сумму целых чисел кратных 7 и принадлежащих интервалу [-127, 128]. Основная идея алгоритма решения поставленной задачи состоит в том, что необходимо организовать цикл, который бы позволял изменять значения некоторой целочисленной переменной от -127 до 128 с шагом 1 и при этом
Слайд 16проверялось бы условие, определяющее кратно ли 7 текущее значение данной
переменной, и проводилось бы суммирование только чисел кратных 7. Допустим,
что переменная a хранит текущее значение целочисленной переменной, переменная s будет соответствовать сумме чисел кратных 7.
Оператор цикла с предусловием. Блок-схема алгоритма, решающего постав-ленную задачу может иметь вид рис. 11.
Слайд 17Рис. 11. Блок-схема алгоритма, использующего оператор цикла с предусловием
Слайд 18 Из анализа блок-схемы алгоритма видно, что цикл
по переменной a начинается с проверки условия, а такой цикл
называется циклом с предусловием. Цикл с предусловием в языке программирования СИ задается ключевым словом while и имеет вид
while (<логическое выражение>) <оператор> ;
Оператор в цикле while выполняется до тех пор, пока логическое выражение не станет ложным. При этом следует отметить особенность оператора цикла с предусловием, которая состоит в том, что он всегда начинает выполняться с проверки логического выражения.
В нашем примере при написании программы следует использовать именно данный оператор, так как цикл по переменной a начинается с проверки логического выражения: a <= 128.
Программа 13:
#include
#include
void main (void)
{
int a, s;
clrsrc ();
a = -127;
if ((a % 7) == 0) s += a;
a++;
}
printf ("\nСумма s = %f", s);
}
Оператор цикла с постусловием. Рассмотрим ту же задачу, но при этом видоизменим блок-схему алгоритма рис. 11 так, чтобы цикл начинался с оператора присваивания для переменной s, который накапливает сумму чисел кратных 7. Видоизмененная блок-схема алгоритма будет иметь вид рис. 12
Слайд 20
Рис. 12. Блок-схема алгоритма, использующего оператор цикла с постусловием
Слайд 21Видим, что в отличие от блок-схемы рис. 11 оператор цикла
начинает выполняться с условного оператора, определяющего кратно ли 7 очередное
значение переменной a. Такой оператор цикла называется оператором цикла с постусловием. Он задается ключевыми словами do и while и имеет следующий вид: do
<оператор>
while (<логическое выражение>) ;
Оператор, стоящий между словами do и while будет выполняться до тех пор, пока логическое условие будет истинным. Приведем текст программы, которая будет соответствовать блок-схеме, изображенной на рис. 12, и естественно содержит оператор цикла с постусловием.
Программа 14:
#include
#include
void main (void)
{
int a, s;
clrsrc ();
s = 0;
a = -127;
Слайд 22 do
{
if ((a % 7) ==
0) s += a;
a++;
}
while (a
<= 128);
printf ("\nСумма s = %f", s);
}
Универсальный оператор цикла. В языке СИ имеется универсальный оператор цикла, который задается ключевым словом for
for ([<выражение1>]; <выражение2>; [<выражение3>]) <оператор> ;
Здесь <выражение1> – представляет собой оператор присваивания или группу операторов присваивания, которые задают начальные значения переменным, которые используются при выполнении основного оператора цикла, <выражение2> – единственное выражение, принимающее значение 0 или 1 и определяющее условие прерывания цикла, <выражение3> – одно или несколько операторов, определяющих новые значения переменным, которые используются в основном операторе цикла.
Используем универсальный оператор цикла для решения предыдущей задачи. Измененная блок-схема алгоритма будет иметь вид
Слайд 23Рис. 13. Блок-схема алгоритма, использующего универсальный оператор цикла
Слайд 24 Представим текст программы, использующей универсальный оператор цикла
и соответствующей блок-схеме алгоритма рис. 13.
Программа 15:
#include
#include
void main (void)
{
int a, s;
clrsrc ();
for (s=0, a=-127; a <= 128; a++)
if ((a % 7) == 0) s += a;
printf ("\nСумма s = %f", s);
}
Прокомментируем программу 15. В универсальном операторе цикла в качестве первого выражения используется два оператора присваивания, с помощью кото-рых определяется начальные значения суммы элементов кратных 7 (s = 0) и пере-менной а (a = -127). Они следуют друг за другом и разделены запятой. Фактически в нашем конкретном случае они определяют исходные данные решаемой задачи. Вторым выражением является неравенство a <= 128. Оно задает условие выполне-ния оператора, стоящего в цикле (условного оператора, вычисляющего сумму чисел кратных 7). И третье выражение a++ определяет следующее значение
Слайд 25переменной a, при котором следует выполнить универсальный оператор цикла.
Из всех видов операторов цикла наиболее часто используется универсальный
оператор цикла, чем другие. Сравнив различные версии программ, созданных для решения одной и той же задачи, видим, что программа с использованием универсального оператора цикла получилась наиболее компактной.
Таким образом, группу операторов, с помощью которых моделируются циклические вычислительные процессы, составляют операторы цикла с предусловием, с предусловием и универсальный оператор цикла.