Описание языка «PascalABC.NET».
Операторы.
Операторы: обзор.
В PascalABC.NET определены следующие операторы.
Операторы присваивания.
Составной оператор.
Оператор описания переменной.
Оператор цикла for.
Оператор цикла foreach.
Операторы цикла while и repeat.
Условный оператор if.
Оператор выбора варианта case.
Оператор вызова процедуры.
Оператор try except.
Оператор try finally.
Оператор raise.
Операторы break, continue и exit.
Оператор goto.
Оператор lock.
Оператор with.
Пустой оператор.
Оператор присваивания.
Оператор присваивания имеет вид: Переменная := выражение.В качестве переменной может быть простая переменная, разыменованный указатель, переменная с индексами или компонент переменной типа запись. Символ := называется значком присваивания. Выражение должно быть совместимо по присваиванию с переменной.
Оператор присваивания заменяет текущее значение переменной значением выражения.
Например:
I := i + 1; // увеличивает значение переменной i на 1.В PascalABC.NET определены также операторы присваивания со значками +=, -=, *=, /=. Для числовых типов действие данных операторов описано здесь. Кроме того, использование операторов += и *= для строк описано здесь и операторов +=, -= и *= для множеств - здесь. Их действие для процедурных переменных описано здесь.
Операторы +=, -=, *=, /= имеют следующий смысл: a #= b означает a := a # b, где # - знак операции +, -, *, /.
Например:
A += 3; // увеличить a на 3. B *= 2; // увеличить b в 2 раза.Опертор /= неприменим, если выражение слева - целое.
Операторы +=, -=, *=, /= могут также использоваться со свойствами классов соответствующих типов в левой части.
Составной оператор (блок).
Составной оператор предназначен для объединения нескольких операторов в один. Он имеет вид: Begin. Операторы. End.В PascalABC.NET составной оператор также называется блоком. (традиционно в Паскале блоком называется раздел описаний, после которого идет составной оператор; в PascalABC.NET принято другое решение, поскольку можно описывать переменные непосредственно внутри составного оператора).Операторы отделяются один от другого символом ";". Ключевые слова begin и end, окаймляющие операторы, называются операторными скобками.
Например:
S := 0; P := 1; For var i:=1 to 10 do. Begin. P := p * i; S := s + p. End.Перед end также может ставиться ;. В этом случае считается, что последним оператором перед end является пустой оператор, не выполняющий никаких действий.
Помимо операторов, в блоке могут быть внутриблочные описания переменных:
Begin. var a,b: integer; var r: real; Readln(a,b); X := a/b; Writeln(x);Пустой оператор.
Пустой оператор не включает никаких символов, не выполняет никаких действий и используется в двух случаях:
1. Для использования символа ; после последнего оператора в блоке:
Begin. A := 1; B := a; End.Поскольку в языке Паскаль символ ; разделяет операторы, то в приведенном выше коде считается, что после последней ; находится пустой оператор. Таким образом, ; перед end в блоке можно либо ставить, либо нет. 1. Для пометки места, следующего за последним оператором в блоке::
Label a; Begin. Goto a; X := 1; A: End.Условный оператор.
Условный оператор имеет полную и краткую формы.
Полная форма условного оператора выглядит следующим образом:
If условие then оператор1. Else оператор2.В качестве условия указывается некоторое логическое выражение. Если условие оказывается истинным, то выполняется оператор1, в противном случае выполняется оператор2. Краткая форма условного оператора имеет вид:
If условие then оператор.Если условие оказывается истинным, то выполняется оператор, в противном случае происходит переход к следующему оператору программы.
В случае конструкции вида.
If условие1 then If условие2 then оператор1. Else оператор2.Else всегда относится к ближайшему предыдущему оператору if, для которого ветка else еще не указана. Если в предыдущем примере требуется, чтобы else относилась к первому оператору if, то необходимо использовать составной оператор:
If условие1 then. Begin If условие2 then оператор1. End. Else оператор2.Например:
If a<b then. Min := a. Else min := b;Оператор описания переменной.
В PascalABC.NET можно описывать переменные внутри составного оператора begin-end в специальном операторе описания переменной. Такие описания называются внутриблочными.
Внутриблочное описание имеет одну из форм:
Список имен: тип;
Или.
Имя: тип := выражение;
Или.
Имя: тип = выражение; // Для совместимости с Delphi.
Или.
Имя := выражение;
Имена в списке перечисляются через запятую. Например:
Begin. Var a1,a2,a3: integer; var n: real := 5; var s := ' '; ...В последнем случае тип переменной автовыводится по типу выражения в правой части. Автовыведение типа активно используется при инициализации переменной вызовом конструктора или функции. возвращающей объект:
Begin. Var l := new List<integer>; Var a := Seq(1,3,5); // тип a выводится по типу возвращаемого значения Seq: array of integer.Автовыведение типа при описании невозможно при инициализации переменной лямбда-выражением:
// var f := x -> x*x; // так нельзя! Var f : Func<integer,integer> := x -> x*x;Внутриблочные описания используются чтобы не захламлять раздел описаний описанием вспомогательных переменных. Кроме этого, внутриблочные описания позволяют вводить переменные именно в тот момент когда они впервые потребовались. Оба этих фактора существенно повышают читаемость программы.
Оператор выбора.
Оператор выбора выполняет одно действие из нескольких в зависимости от значения некоторого выражения, называемого переключателем. Он имеет следующий вид:
Case переключатель of. Список выбора 1: оператор1; ... Список выбора N: операторN; Else оператор0. End;Переключатель представляет собой выражение порядкового типа или строкового типа, а списки выбора содержат константы совместимого по присваиванию типа. Как и в операторе if, ветка else может отсутствовать.
Оператор case работает следующим образом. Если в одном из списков выбора найдено текущее значение переключателя, то выполняется оператор, соответствующий данному списку. Если же значение переключателя не найдено ни в одном списке, то выполняется оператор по ветке else или, если ветка else отсутствует, оператор case не выполняет никаких действий.
Список выбора состоит либо из одной константы, либо для перечислимого типа из диапазона значений вида a..b (константа a должна быть меньше константы b); можно также перечислить несколько констант или диапазонов через запятую. Например:
Case Country of. 'Россия': Capital := 'Москва'; 'Франция': Capital := 'Париж'; 'Италия': Capital := 'Рим'; Else Capital := 'Страна отсутствует в базе данных'; End; Case DayOfWeek of. 1..5: writeln('Будний день'); 6,7: writeln('Выходной день'); End;Списки выбора не должны пересекаться. Например, следующий фрагмент.
Case i of. 2,5: write(1); 4..6: write(2); End;Приведет к ошибке компиляции.
Оператор цикла for.
Оператор цикла for имеет одну из двух форм:
For переменная := начальное значение to конечное значение do. Оператор.Или.
For переменная := начальное значение downto конечное значение do. Оператор.Кроме того, переменную можно описать непосредственно в заголовке цикла:
For переменная: тип := начальное значение to или downto конечное значение do. Оператор.Или.
For var переменная := начальное значение to или downto конечное значение do. Оператор.В последнем случае используется автоопределение типа переменной по типу начального значения. В двух последних случаях область действия объявленной переменной распространяется до конца тела цикла, которое в данном случае образует неявный блок. Вне тела цикла такая переменная недоступна, поэтому следующий цикл может использовать переменную с тем же именем:
For var i := 1 to 10 do. Print(i); For var i := 1 to 5 do. Print(i*i);Текст от слова for до слова do включительно называется заголовком цикла, а оператор после do - телом цикла. Переменная после слова for называется параметром цикла. Для первой формы цикла с ключевым словом to параметр цикла меняется от начального значения до конечного значения, увеличиваясь всякий раз на единицу, а для второй формы ключевым словом downto - уменьшаясь на единицу. Для каждого значения переменной-параметра выполняется тело цикла. Однократное повторение тела цикла называется итерацией цикла. Значение параметра цикла после завершения цикла считается неопределенным.
Переменная-параметр цикла может иметь любой порядковый тип. При этом начальное и конечное значения должны быть совместимы по присваиванию с переменной-параметром цикла.
Например:
Var en: (red,green,blue,white); ... For en := red to blue do. Write(Ord(en):2); For var c := 'a' to 'z' do. Write(c);Если для цикла for ... to начальное значение переменной цикла больше конечного значения или для цикла for ... downto начальное значение переменной цикла меньше конечного значения, то тело цикла не выполнится ни разу.
Если цикл используется в подпрограмме, то переменная-параметр цикла должна быть описана как локальная. Наилучшим решением в PascalABC.NET является описание переменной в заголовке цикла.
Изменение переменной-параметра цикла внутри цикла является логической ошибкой. Например, следующий фрагмент со вложенным оператором for является ошибочным:
For i := 1 to 10 do. I -= 1;Оператор цикла foreach.
Оператор цикла foreach имеет одну из следующих форм:
Foreach переменная in контейнер do. Оператор.Или.
Foreach переменная: тип in контейнер do. Оператор.Или.
Foreach var переменная in контейнер do. Оператор.В качестве контейнера может фигурировать динамический массив, строка, множество, а также любой контейнер, удовлетворяющий интерфейсу IEnumerable или IEnumerable<T>(например, List<T>, Dictionary<Key,Value> и т.д.). Переменная цикла должна иметь тип, совпадающий с типом элементов контейнера (если контейнер удовлетворяет интерфейсу IEnumerable, то это тип object). В последней форме foreach тип переменной цикла автовыводится по типу элементов контейнера.
Переменная цикла пробегает все значения элементов контейнера и для каждого значения переменной цикла выполняется тело цикла. Изменение переменной цикла внутри тела цикла не меняет элементы контейнера, т.е. они доступны только на чтение.
Например:
Var. Ss: set of string := ['Иванов','Петров','Сидоров']; A: array of integer := (3,4,5); B: array [1..5] of integer := (1,3,5,7,9); L := new List<real>; Begin. foreach s: string in ss do. Write(s,' '); Writeln; Foreach x: integer in a do. Write(x,' '); Writeln; Foreach var x in b do. Write(x,' '); Writeln; Foreach var r in l do. Write(r,' '); End.Операторы цикла while и repeat.
Оператор цикла while имеет следующую форму: While условие do. Оператор.Условие представляет собой выражение логического типа, а оператор после do называется телом цикла. Перед каждой итерацией цикла условие вычисляется, и если оно истинно, то выполняется тело цикла, в противном случае происходит выход из цикла.
Если условие всегда оказывается истинным, то может произойти зацикливание:
While 2>1 do. Write(1);Оператор цикла repeat имеет следующую форму:
Repeat. Операторы. Until условие.В отличие от цикла while, условие вычисляется после очередной итерации цикла, и если оно истинно, то происходит выход из цикла. Таким образом, операторы, образующие тело цикла оператора repeat, выполняются по крайней мере один раз.
Обычно оператор repeat используют в ситуациях, где условие нельзя проверить, не выполнив тело цикла. Например:
Repeat. Read(x); Until x=0;Если условие всегда оказывается ложным, то может произойти зацикливание:
Repeat. Write(1); Until 2=1;Оператор with.
Оператор with позволяет сократить обращение к полям записи, а также к полям, методам и свойствам объекта. Он имеет вид: With имя записи или объекта do оператор.Или.
With список имен do оператор.Всюду внутри оператора можно опускать имя записи при обращении к полю указанной записи или имя объекта при обращении к полю, методу или свойству указанного объекта. Например, пусть описана переменная.
Var. DateOfBirthday = record. Day: Integer; Month: Integer; Year: Integer; end;Тогда присваивание значений ее полям без использования оператора with имеет вид:
DateOfBirthday.Day := 23; DateOfBirthday.Month := 2; DateOfBirthday.Year := 1965;Использование оператора with позволяет сократить предыдущую запись:
With DateOfBirthday do. Begin. Day := 23; Month := 2; Year := 1965; End;Если внешняя переменная имеет то же имя, что и поле (метод, свойство), то предпочтение отдается полю (методу, свойству). При наличии вложенных операторов with вначале предпринимается попытка рассматривать переменную как поле записи или объекта самого внутреннего оператора with, затем непосредственно объемлющего его оператора with и т.д. Если оператор with содержит список объектов, то они рассматривается справа налево. Например, если имеются описания.
Var. X,y,z: integer; A: record. X,y: integer; end; B: record. X: integer; ;То фрагмент программы.
With a,b do. Begin. X := 1; Y := 2; Z := 3; ;Эквивалентен фрагменту.
With a do. with b do. Begin. X := 1; Y := 2; Z := 3; ;А также фрагменту.
B.x:=1; A.y:=2; Z:=3;Оператор with устарел и сейчас практически не используется.
Оператор безусловного перехода goto.
Оператор безусловного перехода goto имеет следующую форму: Goto метка.Он переносит выполнение программы к оператору, помеченному меткой метка.
Метка представляет собой идентификатор или целое без знака. Чтобы пометить оператор меткой, необходимо перед оператором указать метку с последующим двоеточием:
Label1: оператор.Метки должны быть описаны в разделе меток с использованием служебного слова label:
Label 1,2,3;Например, в результате выполнения программы.
Label 1,2; Begin. var i := 5; 2: if i<0 then goto 1; Write(i); Dec(i); goto 2; 1: End.Будет выведено 543210.
Метка должна помечать оператор в том же блоке, в котором описана. Метка не может помечать несколько операторов.
Переход на метку может осуществляться либо на оператор в том же блоке, либо на оператор в объемлющей конструкции. Так, запрещается извне цикла переходить на метку внутри цикла.
Использование оператора безусловного перехода в программе считается признаком плохого стиля программирования. Для основных вариантов использования goto в язык Паскаль введены специальные процедуры: break - переход на оператор, следующий за циклом, exit - переход за последний оператор процедуры, continue - переход за последний оператор в теле цикла.
Один из немногих примеров уместного использования оператора goto в программе - выход из нескольких вложенных циклов одновременно. Например, при поиске элемента k в двумерном массиве:
Var a: array [1..10,1..10] of integer; ... Var found := False; for var i:=1 to 10 do. for var j:=1 to 10 do. if a[i,j]=k then. begin. Found := True; goto c1; end; C1: writeln(found);Операторы break, continue и exit.
Операторы break и continue используются только внутри циклов.
Оператор break предназначен для досрочного завершения цикла. При его выполнении происходит немедленный выход из текущего цикла и переход к выполнению оператора, следующего за циклом. Оператор continue завершает текущую итерацию цикла, осуществляя переход к концу тела цикла. Например:
Flag := False; For var i:=1 to 10 do. Begin. Read(x); if x<0 then continue; // пропуск текущей итерации цикла. if x=5 then. begin. Flag := True; break; // выход из цикла. end; End;Использование операторов break и continue вне тела цикла ошибочно.
Оператор exit предназначен для досрочного завершения процедуры или функции. Например.
Function Analyze(x: integer): boolean; Begin. if x<0 then. begin. Result := False; exit. end; ... End;Вызов exit в разделе операторов основной программы приводит к ее немедленному завершению.
Следует отметить, что в PascalABC.NET (в отличие от Borland Pascal и Borland Delphi) break, continue и exit являются не процедурами, а именно операторами.
Оператор try ... except.
Оператор try ... except имеет вид:
Try. операторы. Except. блок обработки исключений. End;Блок try называется защищаемым блоком. Если при выполнении программы в нем происходит ошибка, то он завершается и выполнение передается блоку except. Если исключение обрабатывается в блоке except, то после его обработки программа продолжает выполняться с оператора, следующего за try ... except ... end. Если исключение остается необработанным и имеется объемлющий блок try, то выполнение передается его блоку except. Если объемлющего блока try нет, то программа завершается с ошибкой. Наконец, если в блоке try ошибки не произошло, то блок except игнорируется и выполнение программы продолжается дальше.
Если в процессе обработки исключения (в блоке except) произошло другое исключение, то текущий блок except завершается, первое исключение считается необработанным и обработка нового исключения передается объемлющему блоку try. Таким образом, в каждый момент времени существует максимум одно необработанное исключение.
Блок обработки исключений представляет собой либо последовательность операторов, разделенных точкой с запятой, либо последовательность обработчиков исключений вида.
On имя: тип do оператор.Обработчики разделяются символом ';', после последнего обработчика также может следовать символ ';'. Здесь тип - тип исключения (должен быть производным от стандартного типа Exception), имя - имя переменной исключения (имя с последующим двоеточием может быть опущено). В первом случае при обработке исключения выполняются все операторы из блока except. Во втором случае среди обработчиков осуществляется поиск типа текущего исключения (обработчики перебираются последовательно от первого до последнего), и если обработчик найден, то выполняется соответствующий оператор обработки исключения, в противном случае исключение считается необработанным и передается объемлющему блоку try. В последнем случае после всех обработчиков on может идти ветвь else, которая обязательно обработает исключение, если ни один из обработчиков не выполнился.
Следует обратить внимание, что имя переменной исключения в разных обработчиках может быть одинаковым, т.е. оно локально по отношению к обработчику.
Поиск типа исключения в обработчиках производится с учетом наследования: исключение будет обработано, если оно принадлежит к указанному в обработчике типу или производному от него. Поэтому принято записывать вначале обработчики производных классов, а затем - обработчики базовых (в противном случае обработчик исключения производного класса никогда не сработает). Обработчик исключения Exception обрабатывает все возможные исключения и поэтому должен быть записан последним.
Пример.
Var a: array [1..10] of integer; Try. Var i: integer; Readln(i); Writeln(a[i] div i); ... Except. on System.DivideByZeroException do. Writeln('Деление на 0'); on e: System.IndexOutOfRangeException do. Writeln(e.Message); on System.FormatException do. Writeln('Неверный формат ввода'); else writeln('Какое-то другое исключение'); End;Оператор try ... finally.
Оператор try ... finally имеет вид:
Try. операторы. Finally. операторы. End;Операторы в блоке finally выполняются безотносительно к тому, возникло или нет исключение в блоке try. При этом само исключение не обрабатывается.
Блок finally используется для возвращения ранее выделенных ресурсов.
Пример 1. Закрытие открытого файла.
Reset(f); Try. ... Finally. Close(f); End;Файл будет закрыт независимо от того, произошло ли ислючение в блоке try.
Пример 2. Возвращение выделенной динамической памяти.
New(p); Try. ... Finally. Dispose(p); End;Динамическая память, контролируемая указателем p, будет возвращена независимо от того, произошло ли ислючение в блоке try.
Оператор raise.
Оператор raise предназначен для возбуждения исключения и имеет вид:
Raise объект.Здесь объект - объект класса, производного от Exception. Например:
Raise new Exception('Ошибка');При возбуждении специфического исключения желательно определить свой тип исключения.
Для повторной генерации исключения внутри секции except используется также вызов raise без параметров:
Raise;Операторы += и -= для процедурных переменных.
Оператор присваивания += предназначен для присоединения к процедурной переменной процедуры, оператор присваивания -= - для отсоединения. Подпрограммы вызываются в порядке присоединения. Например:
Procedure mult2(var r: real); Begin. R := 2 * r; End; Procedure add3(var r: real); Begin. R := r + 3; End; Var. P: procedure (var x: real); R: real; Begin. R := 1; P := mult2; P += add3; P(r); // r := 2 * r; r := r + 3; P -= mult2; P(r); // r := r + 3; End.Отсоединение не присоединенных подпрограмм не выполняет никаких действий.
Кроме того, к процедурной переменной можно прикреплять/откреплять статические и экземплярные методы классов. Пример см. в теме процедурные переменные.
Операторы += и -= используются также для добавления/удаления обработчиков для событий .NET. Например:
Procedure OnTimer1(sender: object; e: System.Timers.ElapsedEventArgs); Begin. Write(1); End; Begin. var Timer1 := new System.Timers.Timer(1000); Timer1.Elapsed += OnTimer1; Timer1.Start; while True do. Sleep(1000); End.Оператор lock.
Оператор lock имеет вид: Lock объект do. оператор.Объект обязательно принадлежит к ссылочному типу.
Оператор lock гарантирует, что оператор будет выполняться только одним потоком. Объект здесь хранит блокировку, а оператор, представляющий собой тело оператора lock, называется блоком синхронизации. После того как первый поток заходит в блок синхронизации, он блокирует объект, при выходе из блока синхронизации - разблокирует. Если объект заблокирован, то никакой другой поток не может зайти в блок синхронизации и приостанавливается до разблокировки объекта.
Оператор.
Lock obj do. Oper;Полностью эквивалентен следующему участку кода:
Monitor.Enter(obj); Try. Oper; Finally. Monitor.Exit(obj); End;- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
- 118.
- 119.
- 120.
- 121.
- 122.
- 123.
- 124.
- 125.
- 126.
- 127.
- 128.
- 129.
- 130.
- 131.
- 132.
- 133.
- 134.
- 135.
- 136.
- 137.
- 138.
- 139.
- 140.
- 141.
- 142.
- 143.
- 144.
- 145.
- 146.
- 147.
- 148.
- 149.
- 150.
- 151.
- 152.
- 153.
- 154.
- 155.
- 156.
- 157.
- 158.
- 159.
- 160.
- 161.
- 162.
- 163.
- 164.
- 165.
- 166.
- 167.
- 168.
- 169.
- 170.
- 171.
- 172.
- 173.
- 174.
- 175.
- 176.
- 177.
- 178.
- 179.
- 180.
- 181.
- 182.
- 183.
- 184.
- 185.
- 186.
- 187.
- 188.
- 189.
- 190.
- 191.
- 192.
- 193.
- 194.
- 195.
- 196.
- 197.
- 198.
- 199.
- 200.
- 201.
- 202.
- 203.
- 204.
- 205.
- 206.
- 207.
- 208.
- 209.
- 210.
- 211.
- 212.
- 213.
- 214.
- 215.
- 216.
- 217.
- 218.
- 219.
- 220.
- 221.
- 222.
- 223.
- 224.
- 225.
- 226.
- 227.
- 228.
- 229.
- 230.
- 231.
- 232.
- 233.
- 234.
- 235.
- 236.
- 237.
- 238.
- 239.
- 240.
- 241.
- 242.
- 243.
- 244.
- 245.
- 246.
- 247.
- 248.
- 249.
- 250.
- 251.
- 252.
- 253.
- 254.
- 255.
- 256.
- 257.
- 258.
- 259.
- 260.
- 261.
- 262.
- 263.
- 264.
- 265.
- 266.
- 267.
- 268.
- 269.
- 270.
- 271.
- 272.
- 273.
- 274.
- 275.
- 276.
- 277.
- 278.
- 279.
- 280.
- 281.
- 282.
- 283.
- 284.
- 285.
- 286.
- 287.
- 288.
- 289.
- 290.
- 291.
- 292.