1. Синтаксис, переменные, ввод-вывод, циклы

1.1 Изменения синтаксиса

Шаблон структуры обычной программы на Паскале выглядит следующим образом: описание всех констант, переменных и тело программы со всеми операторами, обрамляемое блоком begin-end.

Однако теперь PascalABC.NET в плане компактности кода приближается к языку Python, так как от глобального блока begin-end можно избавиться, написав в начале программы две решётки – ##, можно перейти к написанию коротких программ. Это позволяет не использовать константы, глобальные переменные, а также убирает объявление типов данных в начале программы. Разрешено подключение модулей и библиотек через uses, использование любых функций и процедур.


Стандартный Паскаль PascalABC.NET

var a,b:integer; c:real; res:boolean;

begin

  a:=2;

  write('b=');

  read(b);

  c:=sqrt(a/b);

  if c>b then

    res:=True

  else

    res:=False;

  writeln(res);

end.

##

var (a,b):=(2,ReadInteger('b ='));

var c:=sqrt(a/b);

var res:=c>b ? True.print : False.print;


Существует модуль, сокращающий названия многих функций при записи программ: uses SF. Его также можно подключить, если вместо двух решёток ## записать три решётки ###. Благодаря этому модулю можно ещё больше сократить код программ, делая их «суперкороткими».


  Обычная запись    

Сокращённая запись

integer       

boolean         

BigInteger       

ReadInteger      

ReadReal2        

ReadString3     

Print           

Println            

        int

        bool

        bi

        RI

        RR2

        RS3

        Pr

        Prln



1.2. Описание переменных

Большое количество изменений произошло с описанием переменных. Раньше все переменные описывались до блока begin-end, а так как теперь его можно не писать, то и необходимости в изначальном описании всех переменных нет. Это означает, что любую переменную можно описать и инициализировать в любом месте нашей программы, когда она нам понадобилась. Это избавляет нас от следующих ситуаций:

1) загромождение описаниями всех переменных в начале программы;

2) изначально описанные переменные так и не используются в течение программы;

3) сначала описываем переменную и тип, а затем присваиваем значение (теперь же описание и присваивание можно делать одновременно в одной строке кода).

Современный PascalABC.NET обладает следующим удобным и полезным свойством: компилятор языка умеет самостоятельно определять тип данных при описании и инициализации переменных. То есть нам, в общем случае, нет необходимости указывать тип данных для переменной – компилятор сам определит, какой тип у переменной: Integer, Real, Char, String или Boolean.


Стандартный Паскаль PascalABC.NET

var a:integer; b:real; c:char; d:string; e:boolean;    

begin

  a:=24;

  b:=2.51;

  c:='c';

  d:='string';

  e:=True;

write(a,' ',b,' ',c,' ',d,' ',e);

end.

##

var a:=24;

var b:=2.51;

var (c,d,e):=('c','string',True);

print(a,b,c,d,e);

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

Автовыведение типов компилятором также позволяет выполнять множественное присваивание значений переменным с помощью распаковки значений кортежа ('c','string',True) в переменные c, d, e. Оба кода делают одинаковую работу, но новые возможности позволяют записать привычный код компактно и более читабельно.



1.3. Тип BigInteger

Помимо стандартных типов данных в язык был интегрирован новый тип данных из библиотеки Microsoft .NET Framework – BigInteger. Его отличительная особенность состоит в том, что, в отличие от остальных целочисленных типов, этот тип данных имеет переменный размер в байтах, а значит диапазон допустимых значений у него практически неограниченный. Это позволяет производить операции с огромными числами, и не беспокоиться о возможности переполнения.

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

Для записи переменной с типом BigInteger нужно после указанного числа написать литерал bi или использовать функцию BigInteger(a), например, 5bi, -18bi, BigInteger(23). Но в случае таких записей значение в записи литерала и внутри функции BigInteger(a) ограничено величиной 18446744073709551615 (также и для отрицательных чисел), ввод большего числа приведёт к ошибке о слишком большом введённом числе.

Если же необходимо работать с ещё большими числами, то приходится использовать строковое представление числа с его последующим преобразованием в тип BigInteger, например:

'1234567891011121314151617181920'.ToBigInteger;

Тип BigInteger очень удобно использовать при работе с целочисленной арифметикой. Проиллюстрируем это на следующем примере: необходимо вычислить выражение m=(2100000000*3) div 5.

Если прямо так записать решение задачи, то возникнет проблема переполнения в арифметической операции. Почему она возникает, если 2100000000, 3 и 5 являются типом данных Integer при автовыведении типов и попадают в диапазон этого типа данных? Дело в том, что промежуточное значение 2100000000*3 уже будет не помещаться в диапазон типа Integer, отсюда возникает переполнение и неправильный результат 401006540.

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


  Стандартный Паскаль     PascalABC.NET

var a,r:integer;

begin

  a:=2100000000;

  r:=a*3 div 5;

  writeln(r);

end.

##

print((2100000000*3) div 5);
Вывод:
401006540
Вывод:
Исключение: переполнение в
арифметической операции

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

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


  Стандартный Паскаль     PascalABC.NET

var a:int64; r:integer;

begin

  a:=2100000000;

  r:=a*3 div 5;

  writeln(r);

end.

##

(Int64(2100000000)*3 div 5).println;

//или

(BigInteger(2100000000)*3 div 5).println;

//или

(2100000000*3bi div 5).println;
Вывод:
1260000000
Вывод:
1260000000
1260000000
1260000000


1.4. Изменение в вводе-выводе

Подвергся изменениям также ввод и вывод значений. Раньше при создании простейшего интерфейса с пользователем использовался следующий шаблон: «введите число A» – ввод числа – «число А равно». Нужно было написать много строчек кода для такой простой операции, лишние строки занимал вывод текста обращения на экран.

PascalABC.NET лишён такого недостатка, появление новых функций ввода значений переменных ReadInteger(), ReadReal(), ReadlChar(), ReadBool(), ReadBigInteger() позволяет сделать короткий ввод переменных всего в одну строку, так как обращение к пользователю можно написать внутри этих функций. Если необходимо ввести сразу несколько однотипных значений, то после функции пишется число переменных, например ReadInteger2, ReadReal4 или ReadString3.

В дополнение к стандартным функциям вывода Write() и Writeln() появились функции Print() и Println(), которые выводят значения на экран сразу с пробелами, описание переменных с их инициализацией и вводом-выводом существенно сокращается, причём понятность кода не уменьшается.


Стандартный Паскаль PascalABC.NET

var

  name: string;

  age: integer;

  height: real;

 

begin

  Write('Ваше имя: '); Read(name);

  Write('Возраст: '); Read(age);

  Write('Ваш рост (м): '); Read(height);

  Write('Здравствуй, ', name, ', твой возраст ', age, ', твой рост ', height, ' м');

end.

##

var name:=ReadString('Ваше имя:');

var age:=ReadInteger('Возраст:');

var height:=ReadReal('Ваш рост (м):');

print($'Здравствуй,  {name}, твой возраст {age}, твой рост {height} м');

Вывод:
Здравствуй, Дима, твой возраст 22, твой рост 1.86 м

Вывод:
Здравствуй, Дима, твой возраст 22, твой рост 1.86 м



1.5. Циклы

Такие управляющие структуры, как циклы, тоже претерпели изменения. Рассмотрим основные нововведения циклов.

Во-первых, были добавлены два новых цикла: foreach и loop.

Цикл foreach используется для «прохода» по элементам какого-либо перечислимого типа данных, например массива или последовательности. То есть можно использовать текущий элемент массива без использования индексации элементов.

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

Во-вторых, в циклах переменную счётчика следует обязательно описывать в заголовке цикла (for var). При данном описании переменной она не доступна нигде в программе, кроме этого цикла.


  Стандартный Паскаль     PascalABC.NET

var

  T: array [1..6] of integer;

  i: integer;

 

begin

  for i := 1 to 6 do

    T[i] := i;

  for i := 1 to 5 do

    writeln(T);

  for i := 1 to 6 do

  begin

    Write(T[i] * T[i], ' ');

  end;

end.

##

var T := |1, 2, 3, 4, 5, 6|;

loop 5 do

  println(T);

foreach var x in T do

  (x ** 2).Print;

Вывод:
[1,2,3,4,5,6]

[1,2,3,4,5,6]

[1,2,3,4,5,6]

[1,2,3,4,5,6]

[1,2,3,4,5,6]

1 4 9 16 25 36

Вывод:
[1,2,3,4,5,6]

[1,2,3,4,5,6]

[1,2,3,4,5,6]

[1,2,3,4,5,6]

[1,2,3,4,5,6]

1 4 9 16 25 36


Modifié le: lundi 22 mai 2023, 19:28