Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции_Информатика.doc
Скачиваний:
6
Добавлен:
16.04.2019
Размер:
738.82 Кб
Скачать

Выражения. Операции.

Выражение представляет собой формальное правило для вычисления некоторого (нового) значения. В самом общем виде можно сказать, что выражение строится из операндов, знаков операций и круглых скобок. Операнды представляют собой "элементарные" значения; ими могут быть переменные, поля записей, элементы массивов, вызовы функций и т.д. Операции определяют действия по вычислению новых значений, исходя из значений операндов. Операции в языке Pascal обозначаются специальными знаками, состоящими из одного или нескольких символов, напр., @, + или <=; некоторые операции задаются с помощью служебных слов, напр., div, mod.

Операции подразделяются на арифметические операции, логические операции, строковые операции, операции над множествами, операции отношения и операцию @ (операция получения адреса).

Большинство операций являются бинарными, т.е. определенными для двух операндов. В этом случае знак операции записывается между операндами, напр. а+с. Кроме того, имеется несколько унарных операций (содержащих один операнд). Здесь знак операции всегда предшествует операнду, напр., @p, -a. Синтаксис выражений предусматривает определенное старшинство операций (приоритеты). Приоритеты задают очередность выполнения операций в выражениях. Круглые скобки предназначены для указания порядка (очередности) вычислений, если необходимо изменить тот порядок действий, который определен приоритетами операций.

Порядок выполнения операций

Операция

Приоритет

Вид операции

@, not

*, /, div, mod, and, shl, shr

+, -, or, xor

=, <>, <, >,<=, >=, in

первый (высший)

второй

третий

четвертый (низший)

унарная операция

операция умножения

операция сложения

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

Для точного определения порядка вычисления выражений необходимо учитывать следующие правила:

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

  2. Операнд, находящийся между двумя операциями с равными приоритетами, связывается с той операцией, которая находится СЛЕВА от него. Иными словами, операции с равными приоритетами выполняются слева направо (хотя иногда Pascal-компилятор может переупорядочить такие операции, если это повлечет большую эффективность объектного кода).

  3. Часть выражения, заключенная в круглые скобки, при вычислении рассматривается как отдельный операнд. Это означает, что все операции внутри подвыражения в круглых скобках будут выполнены перед выполнением операций слева или справа от круглых скобок.

Арифметические операции

Если оба операнда в операциях +, -, *, div или моd являются операндами целого типа, то тип результата будет таким же, как общий тип обоих операндов. Если один или более операндов в операциях +, -, или * имеют вещественный тип, то тип результата будет вещественным. Значение выражения х/у всегда будет вещественного типа или с повышенной точностью, независимо от типов операндов. Если у равно 0, то результат будет ошибочным.

Значение выражение i div j представляет собой математическое частное от i/j, округленное в меньшую сторону до значения целого типа. Если j равно 0, результат будет ошибочным.

Операция mod возвращает остаток, полученный путем деления двух ее операндов, то есть:

i mod j = i - (i div j) * j

Знак результата операции mod будет тем же, что и знак i. Если j равно нулю, то результатом будет ошибка.

Логические операции: not and or xor shl shr

Булевские операции

Таблица истинности

Операции отношения: = <> < > <= >= <= >= in

Операторы

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

Простые операторы

Простым оператором является такой оператор, который не содержит в себе других операторов.

Оператор присваивания

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

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

Приведем некоторые примеры операторов присваивания:

X := Y + Z;

Done := (I>=1) and (I<100);

Huel := [blue,Succ(C)];

I := Sqr(J) - I*K;

Операторы перехода

Оператор перехода вызывает передачу управления оператору, которому предшествует метка, указанная в данном операторе перехода. Синтаксическая схема оператора перехода имеет следующий вид:

Операторы перехода

Goto N;

где N - номер метки.

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

1. Метка, которая указывается в операторе перехода, должна находиться в том же блоке или модуле, что и сам оператор перехода. Другими словами, не допускаются переходы из процедуры или функции или внутрь нее.

2. Переход извне внутрь структурного оператора (то есть переход на более глубокий уровень вложенности) может вызвать непредсказуемые эффекты, хотя компилятор не выдает сообщения об ошибке.

Организация ввода вывода со стандартных устройств

Ввод

Стандартный Паскаль имеет две основные процедуры ввода Read и Readln, которые используются для чтения данных, вводимых с клавиатуры. Общий формат этих операторов следующий:

Read(элемент,элемент,...); или Readln(элемент,элемент,...);

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

Вывод.

Процедура Writeln.

Назначение Writeln - выводить информацию на экран. Ее формат прост и гибок в использовании:

Writeln(элемент,элемент,...);

где каждый элемент - это то, что нужно напечатать на экране. Элементом может быть литеральное значение, например, целое или вещественное число (3,42,-1732.3), символ ('а','Z'), строка ('Hello,world') или булево значение (Тrue). Кроме того, им может быть именованная константа, переменная, разыменованный указатель или обращение к функции, если она возвращает значение, которое имеет целый, вещественный, символьный, строковый или булев тип. Все элементы печатаются в одной строке в заданном порядке. После этого курсор устанавливается в начало следующей строки. Если вы хотите оставить курсор на той же строке после последнего элемента, то используйте оператор:

Write(элемент,элемент,...);

Когда распечатываются элементы по оператору Writeln, между ними автоматически не вставляются пробелы; если Вы хотите разделить элементы пробелами, то Вы должны указать их сами, например:

Writeln(элемент,' ',элемент,' ',...);

Поэтому по следующим операторам будет получен указанный вывод:

A := 1; B := 2; C := 3;

Name := 'Frank';

Writeln(A,B,C); 123

Writeln(A,' ',B,' ',C); 1 2 3

Writeln('Hi',Name); HiFrank

Writeln('Hi, ',Name,'.'); Hi, Frank.

Кроме того, можно использовать спецификаторы для определения ширины поля для данного элемента. В этом случае оператор имеет формат:

Writeln(элемент:ширина,...)

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

A := 10; B := 2; C := 100;

Writeln(A,B,C); 102100

Writeln(a:2,B:2,C:2); 10 2100

Writeln(A:3,B:3,C:3); 10 2100

Writeln(A,B:2,C:4); 10 2 100

Отметим, что элемент дополняется начальными пробелами слева с тем, чтобы соответствовать указанной длине поля. Само значение выравнивается справа. Что если ширина поля меньше, чем необходимо? Во втором операторе Writeln из приведенного выше примера для С, имеющего значение 100, ширина поля указана 2, хотя необходима ширина 3. Как Вы видете в выводе, Паскаль увеличил ширину до минимального необходимого размера.

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

X := 421.53; Writeln(X); 4.2153000000E+02 Writeln(X:8); 4.2E+02

Поэтому Паскаль позволяет добавить второй спецификатор ширины поля: элемент:ширина:цифры. Это второе значение указывает распечатать вещественное число в формате с фиксированной точкой и определяет, сколько цифр поместить после десятичной точки:

X := 421.53;

Writeln(X:6:2); 421.53

Writeln(X:8:2); 421.53

Writeln(X:8:4); 421.5300

Стандартные функции

Abs(x), arctan(x), cos(x), dec(x), exp(x), frас(x), inc(x), int(x), ln(x), pred(x), sin(x), sqr(x), sqrt(x), succ(x)

Далее перечислены некоторые стандартные функции преобразования:

Имя функции

Тип аргумента

Преобразование и тип результата

Odd Trunc Round Ord

Chr

целый

вещественный

вещественный

дискретный целый

0..255

true, если аргумент четный, иначе false

целая часть результата

аргумент округляется до ближайшего целого порядковый номер от 0 значения аргумента в данном дискретном типе

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

ax = exp(xln(a))

Структурные операторы

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

Составные операторы

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

Приведем пример составного оператора:

begin

Z := X; X := Y; Y := Z;

end;

Условные операторы

Иногда бывает необходимо, чтобы некоторая часть программы была выполнена, если некоторое заданное условие имеет значение Тrue или же не имеет, или если некоторое заданное выражение принимает определенное значение. Посмотрим, как это реализуется в Паскале.

В выражении должен получаться результат, имеющий стандартный булевский тип. Если результатом выражения является истинное значение (Тrue), то выполняется оператор, следующий за ключевым словом then. Если результатом выражения является значение False и присутствует ключевое слово else, то выполнятся оператор, следующий за ключевым словом else. Если ключевое слово else отсутствует, то никакой оператор не выполняется.

Необходимо разъяснить два важных момента в использовании операторов if/then/else. Во-первых, оператор else является необязательным; другими словами, является допустимым следующий оператор if:

if выражение then оператор1

В этом случае оператор1 выполняется в том и только в том случае, если выражение имеет значение Тrue. Если выражение имеет значение False, то оператор1 пропускается и продолжается выполнение программы. Во-вторых, как быть, если необходимо выполнить более одного оператора в случае, когда указанное выражение принимает значение Тrue или False. В этом случае следует использовать составной оператор. В примере с вычислением отношения в предложении if используется одиночный оператор:

if B = 0.0 then Writeln('Деление на нуль запрещено.')

а в предложении else - составной оператор:

else begin Ratio = A / B; Writeln('Отношение равно ',Ratio) end;

Оператор варианта (case)

Этот оператор позволяет осуществить в программе выбор между альтернативами, не используя большого числа операторов if.

Оператор варианта (casе) состоит из выражения (переключателя) и списка операторов, каждому из которых предшествует одна или более констант (они называются константами выбора) или ключевое слово else. Переключатель должен иметь перечислимый тип и перечислимые значения верхней и нижней границы этого типа должны лежать в диапазоне от -32768 до 32767. Таким образом, строковый тип и длинный целый тип являются недопустимыми типами переключателя. Поддиапазон записывается в виде двух констант, разделенных ограничителем поддиапазона '..'. Тип константы должен соответствовать типу селектора. Оператор, стоящий после метки case, выполняется в том случае, если значение селектора равно значению констант или если оно попадает в один из поддиапазонов.

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

Приведем некоторые примеры оператора варианта:

case BirdSight of

'C', 'c' : Curlews := Curlews + 1;

'H', 'h' : Herons := Herons + 1;

'E', 'e' : Egrets := Egrets +1;

'Y', 't' : Terns := Terns +1;

end; { case }

Циклы

Имеется три основных вида циклов: цикл while, цикл repeat и цикл for.

Оператор цикла задает повторное выполнение определенных операторов.

Если число повторений заранее известно, то подходящей конструкций является оператор for. В противном случае следует использовать операторы while или repeat.

Операторы цикла с пред-условием (while)

Оператор while используется для проверки некоторого условия в начале цикла.

Выражение, с помощью которого осуществляется управление повторением оператора, должно иметь булевский тип. Вычисление его производится до того, как внутренний оператор будет выполнен. Внутренний оператор выполнятся повторно до тех пор, пока выражение принимает значение Тruе. Если выражение с самого начала принимает значение False, то оператор, содержащийся внутри оператора цикла с пред-условием, не выполняется.

Введем следующую программу:

program Hello;

var

Count : integer;

begin

Count := 1; while Count <= 10 do

begin

Writeln('Здравствуйте и до свидания!'); Inc(Count)

end;

Writeln('Это конец!')

end.

Первое, что произойдет при запуске этой программы, - это присваивание Count значения 1, затем следует цикл while. Здесь сначала проверяется, не является ли значение Count меньшим или равным 10. Если да, то выполняется тело цикла (begin..end). При этом на экране печатается сообщение "Здравствуйте и до свидания!", затем значение Count увеличивается на 1. Count проверяется заново и тело цикла выполняется еще раз. Это продолжается до тех пор, пока значение Count при проверке меньше или равно 10. Как только Count принимает значение 11, цикл завершается, и на экране печатается строка "This is the end!" ("Это конец!").

Оператор цикла с пост-условием (repeat)

В операторе цикла с пост-условием (начинающимся со слова repeat) выражение, которое управляет повторным выполнением последовательности операторов содержится внутри оператора repeat.

Результатом выражения должен быть результат булевского типа. Операторы, заключенные между ключевыми словами repeat и until, выполняются последовательно до тех пор, пока результат выражения не примет значение Тrue. Последовательность операторов выполнится по крайней мере один раз, поскольку вычисление выражения производится после каждого выполнения последовательности операторов.

Приведем примеры оператора цикла с пост-условием:

repeat

K := I mod J; I := J; J := K;

until J = 0;

Имеется три основных различия между циклом while и циклом repeat. Во-первых, операторы в цикле repeat всегда выполняются хотя бы один раз, поскольку проверка выражения осуществляется не сразу после ключевого слова repeat. Наоборот, в цикл while, если выражение изначально имеет значение False, то пропускается все тело цикла. Во-вторых, цикл repeat выполняется до тех пор, пока выражение не примет значение Тrue; в отличие от него цикл while выполняется, пока выражение имеет значение Тrue. Это означает, что следует внимательно заменять один тип цикла на другой. Наконец, цикл repeat может содержать несколько операторов, не образующих составной оператор.

Замечание. В ряде случаев бывает удобно организовывать бесконечные циклы

While true do ……

Repeat

. . .

until false;

для выхода из таких циклов используется оператор break,который появился только в 7-й версии.

Операторы цикла с параметром (for)

Операторы цикла с параметром (которые начинаются со слова for) вызывает повторяющееся выполнение оператора (который может быть составным оператором) пока управляющей переменной присваивается возрастающая последовательность значений.

For параметр цикла:= начальное значение to конечное значение do оператор.

В качестве управляющей переменной должен использоваться идентификатор переменной. Управляющая переменная должна иметь перечислимый тип. Начальное и конечное значения должны иметь тип, совместимый по присваиванию с перечислимым типом. Когда начинает выполняться оператор for, начальное и конечное значения определяются один раз, и эти значения сохраняются на протяжении всего выполнения оператора for. Оператор, который содержится в теле оператора for, выполняется один раз для каждого значения в диапазоне между начальным и конечным значением. Управляющая переменная всегда инициализируется начальным значением. Когда работает оператор for и используется ключевое слово to, значение управляющей переменной увеличивается при каждом повторении на единицу. Если начальное значение превышает конечное значение, то содержащийся в теле оператора for оператор не выполнятся. Когда в операторе цикла используется ключевое слово downto, значение управляющей переменной уменьшается при каждом повторении на единицу. Если начальное значение в таком операторе меньше, чем конечное значение, то содержащийся в теле оператора цикла оператор не выполнятся.

Если оператор, содержащийся в теле оператора for, изменяет значение управляющей переменной, то это является ошибкой. После выполнения оператора for значение управляющей переменной становится неопределенным, если только выполнение оператора for не было прервано с помощью оператора перехода.

На параметр цикла в операторе for накладываются следующие ограничения:

  1. параметр цикла, а также его начальное и конечное значения не могут быть изменены никаким оператором в теле цикла;

  2. вход в цикл ТОЛЬКО через его начало.

Массивы

Массив - это упорядоченная совокупность переменных одного типа, называемых элементами массива. Все элементы имеют одно и то же имя, совпадающее с именем массива. Каждый элемент снабжается индексом (порядковым номером), определяющим его относительную позицию в ряду других элементов, и называется индексированной переменной. Индекс элемента записывается вслед за его именем в квадратных скобках, например, a[3], max[10] и т.д. Характеристиками каждого массива являютnя его имя, размерность и длина. Имя массива выбирается по тем же правилам, что и имя простой (неиндексированной) переменной. Понятие размерности массива аналогично понятию размерности матрицы в математике. Так одномерный массив соответствует вектору - строке, двумерный - матрице такой же размерности и т.д.

Длина массива - это количество составляющих его элементов. Массивы относятся к одной из разновидностей составного типа, а именно к регулярному типу.

Определение регулярного типа имеет вид

array [t2] of t1

где array - массив (ключевоеое слово);

of - из (ключевое слово);

t1 - тип элементов массива (базовый тип);

t2 - тип индексов элементов массива.

В качестве элементов массива могут выступать переменные любого типа, допустимого в языке. Тип индекса задаёт количество элементов в массиве, т.е. его длину; это количество определяется числом возможных значений типа,указанного в описании массива. Для индексации элементов массива чаще всего используется ограниченный тип, который образуется из какого-либо стандартного типа (например, целого) путём наложения ограничений на допустимый диапазон его значений. Эти ограничения задаются минимальным и максимальным значениями индекса, разделёнными двумя стоящими подряд точками и заключёнными в квадратные скобки, например, [1..20], [-5..35] и т.д.

В программе каждый массив должен быть описан. Его описание может быть сделано либо в разделе описания переменных - var, либо в двух разделах: описания типов - type и описания переменных. Но в любом случае в описании массива должно присутствовать определение регулярного типа.

Описание массива в разделе переменных выглядит так:

var

имя массива: array [t2] of t1;

Пример

var

amper: array [0..30] of real;

Описан массив с именем amper, состоящий из 31 элемента типа real; индексация его элементов начинается с нуля и заканчивается целым числом 30; справа от символа ":" находится определение регулярного типа

var

v,w: array [-1..15] of integer;

Описаны два эквивалентных массива v и w целого типа, содержащие по 17 элементов в каждом.

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

type

имя типа = array [t2] of t1;

var

имя массива:имя типа;

Пример

type

vec=array [-5..10] of integer;

var

b: vec;

Обращение к элементу массива

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

а:=b,

если их типы эквивалентны. Для того, чтобы получить доступ к элементу массива, нужно записать обращение к нему, которое выглядит как

имя массива [индекс]

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

Ввод и вывод одномерных массивов

Для ввода и вывода всего массива или его части используют операторы цикла, как правило, оператор for.

Пример

var

z:array [10..100] of integer;

k:integer;

begin

for k:=10 to 100 do read(z[k]);

for k:=21 to 30 do write(z[k]);

Организация циклов с использованием массивов в качестве исходных данных

Задачи такого рода являются весьма распространёнными в вычислительной практике и программировать их можно с использованием любого из трёх описанных выше операторов цикла. Но наилучшиим для этой цели является оператор for. Однако, каким бы оператором мы не пользовались, всегда нужно иметь в виду следующее.

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

Пример

Дан массив c(20), содержащий положительные и отрицательные элементы. Вывести порядковый номер первого отрицательного элемента массива.

program vybor1;

var

c : array [1..20]of real;

n : integer;

begin

for n:=1 to 20 do read(c[n]); readln;

n:=1;

{ поиск первого отрицательного элемента }

while (n<=20) and (c[n]>0) do n:=n+1;

if n<=20

then write('n=',n) { печать номера первого отрицательного

элемента массива }

else write(‘отрицательных элементов нет’);

end.

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

  1. Вход в тело цикла извне, минуя оператор цикла, запрещён.

Ниже приведены примеры организации циклических вычислительных процессов с помощью оператора for.

Пример

Дан вектор a(50). Вычислить сумму его элементов.

program summa;

var

i : integer;

s : real;

a : array [1..50] of real;

begin

write(‘введите массив -‘);

for i:=1 to 50 do read(a[i]);

s:=0; { oбнуление ячейки s, предназначенной

для накопления суммы }

for i:=1 to 50 do s:=s+a[i]; { нaкопление суммы элементов массива }

write('s=',s:10:3)

end.

Если один цикл находится в теле другого, то он называется вложенным (внутренним). Внешний цикл сам может оказаться вложенным по отношению к какому-либо другому циклу. Использование вложенных циклов позволяет компактно описывать довольно сложные алгоритмы.

Пример - работа с двумерным массивом.

В процессе решения многих важных практических задач (например, задач оптимизации, статистики и т.д.) возникает необходимость обработки двумерных массивов данных, которые в математике называются матрицами и представляют собой прямоугольные таблицы, состоящие из m строк и n столбцов, содержащие mn чисел:

а11 а12 . . . а1n

а21 а22 . . . а2n

А = . . . . . .

аm1 аm2 . . . аmn

Числа аij, составляющие матрицу А, называются её элементами. Индексы i и j элемента аij указывают соответственно номера строки и столбца, на пересечении которых расположен элемент.

Обработка матрицы сводится, в большинстве случаев, к перебору ее элементов в определенной последовательности и выполнению над ними арифметических операций.

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

Алгоритм сложного цикла следующий:

  1. параметру i внешнего цикла присваивается его начальное значение m1, после чего следует вход во внутренний цикл;

2) вычисления, составляющие тело внутреннего цикла, повторяются заданное число раз с параметром j, меняющимся от начального значения n1 до конечного n2 с шагом n3;

3) далее происходит возврат во внешний цикл, его параметр i изменяется на шаг m3, после чего полученное текущее значение параметра (i) сравнивается с его конечным значением m2; если i<m2, выполняется переход к пункту 2), в противном случае осуществляется выход из внешнего цикла.

Рис.1. Структура сложного цикла: а) детализированный вариант; б) упрощённый вариант