Описания переменных внутри блока и автовывод типов
В большинстве случаев переменные описываются в блоке begin-end и описание совмещается с инициализацией:
begin
var a := 5;
var r := 3.14;
var s := 'ABC';
end.
Это решает сразу несколько проблем:
- можно не говорить о типах в первых программах или лишь упоминать их
- невозможно забыть инициализировать переменную
- переменные описываются по мере необходимости близко к месту их использования. Это улучшает читаемость. Проблема старого Паскаля, когда груда переменных описывалась до beginа, отсутствует
При таком способе возникает одна проблема: если надо накопить сумму вещественных, то такой код приведет к ошибке типов:
begin
var sum := 0;
loop 10 do
sum += ReadReal;
end.
Для исправления этой ошибки всё равно придётся говорить о типах и инициализировать sum одним из двух способов:
var sum := 0.0;
или
var sum : real := 0;
Цикл for var
Переменная - счётчик цикла for всегда должна описываться в заголовке цикла:
for var i:=1 to 9 do
Print(i);
for var i:=21 to 29 do
Print(i);
Это делает невозможным использование счётчика цикла вне цикла
Цикл loop
Если количество повторений цикла заранее известно, но неважен номер повторения, то используется цикл loop:
loop 9 do
Write('*');
Множественное описание переменных с инициализацией
Можно инициализировать сразу несколько переменных в момент описания:
var (a,b) := (1,2);
var (Имя,Возраст) := ('Иванов',15);
Вывод
Для вывода вместо процедуры Write предпочтительно использовать процедуру Print. В отличие от Write она разделяет элементы вывода пробелами. Например:
begin
var (a,b,c) := (1,2,3);
Println(a,b,c);
for var i:=1 to 9 do
Print(i);
end.
Для вывода нескольких значений с пояснениями рекомендуется использовать интерполированные строки:
begin
var (a,b) := ReadInteger2;
Println($'Сумма {a} и {b} равна {a + b}');
end.
вместо режущего глаз
Writeln('Сумма ', a ' и ', b, ' равна ', a + b);
Ввод
Ввод принято осуществлять, используя функции вида ReadInteger, ReadReal и т.д.:
begin
var a := ReadInteger;
end.
Это позволяет совмещать описание переменной с инициализацией и автовыводом типа. В качестве дополнительных бонусов: можно делать приглашение к вводу как параметр функции ввода и вводить сразу несколько переменных одного типа:
begin
var a := ReadReal('Введите a: ');
var (m,n,p) := ReadInteger3;
var (x,y) := ReadReal2('Введите координаты точки: ');
end.
Для ввода с контролем ошибок используется функция TryRead. Она возвращает False если ввод осуществлён неверно (введено не число или число выходит за границы диапазона). Типичный пример её использования:
begin
var i: integer;
while not TryRead(i,'Введите i:') do
Println('Повторите ввод!');
end.
Тип BigInteger
Для работы с длинными целыми используется тип BigInteger. Например, чтобы вычислить 100!, достаточно написать следующий код:
begin
var p: BigInteger := 1;
for var i := 2 to 100 do
p *= i;
Println(p);
end.
Константу BigInteger можно также создать, используя суффикс bi - тогда предыдущий код изменится следующим образом:
begin
var p := 1bi;
for var i := 2 to 100 do
p *= i;
Println(p);
end.
Некоторые полезные стандартные процедуры, функции и операции
Для обмена значений двух переменных a
и b
используйте стандартную функцию Swap(a,b)
:
begin
var (a,b) := ReadReal2;
Println(a,b);
Swap(a,b);
Println(a,b);
end.
Разумеется, первый раз необходимо показать, что обмен значений осуществляется через третью переменную:
begin
var a,b := ReadReal2;
Println(a,b);
var t := a;
a := b;
b := t;
Println(a,b);
end.
Но далее следует использовать Swap.
Минимальное и максимальное среди множества значений можно вычислить, используя стандартные функции Min и Max:
begin
var a,b,c,d := ReadReal4;
Println(Min(a,b),Max(c,d));
Println(Min(a,b,c,d)); // произвольное количество значений
end.
Для возведения в степень используется операция **
:
begin
Println(2 ** 10);
Println(2 ** 0.5);
end.
Возведение в целую степень оптимизировано и работает быстрее стандартной функции Power(a,n)
.
Для проверки принадлежности диапазону используется конструкция x in a..b
:
begin
var x := ReadInteger;
if x in 10..99 then
Print('Двузначное число');
end.
Эта операция эффективна и переводится в
begin
var x := ReadInteger;
if (x >= 10) and (x <= 99) then
Print('Двузначное число');
end.
Диапазоны также можно использовать для вещественных значений и для символов:
r in 2.5..3.8
c in 'a'..'z'
Для проверки принадлежности множеству значений используется либо множество:
x in [2,3,5,7,11]
либо массив:
x in |2,3,5,7,11|
Мы рекомендуем второй способ - он существенно более эффективен по скорости и по памяти.
Условная операция
Если переменной необходимо присвоить значение в зависимости от условия, то вместо условного оператора иногда нагляднее использовать условную операцию:
begin
var (a,b) := ReadInteger2;
var min := if a<b then a else b;
Print(min);
end.
Методы в стандартных типах
В PascalABC.NET внутри каждого типа имеется ряд полезных методов. В отличие от внешних процедур и функций, они “вшиты” в тип - переменная знает все свои методы и может вызывать их, используя точечную нотацию.
Например, чтобы вывести значение переменной базового типа, можно использовать метод Print:
begin
var i: integer := 5;
i.Print;
end.
Из других интересных методов для начинающих для целых типов отметим:
i.IsEven - является ли i чётным
i.IsOdd - является ли i нечётным
i.InRange(a,b) - находится ли значение i между a и b (включительно)
i.Sqrt - квадратный корень
Например, в следующей программе вычисляется количество четных двузначных из 10 введённых:
begin
var count := 0;
loop 10 do
begin
var x := ReadInteger;
if i.IsEven and i.InRange(10,99) then // не требует написания скобок
count += 1;
end;
count.Print
end.
Для вещественных значений полезными являются методы
r.Sqrt
r.Round
r.Trunc
r.InRange(a,b) - находится ли значение r между a и b (включительно)
В частности, удобно использовать цепочечную точечную нотацию:
begin
var x := 17;
var IsPrime := True;
for var i:=2 to x.Sqrt.Round do
if x mod i = 0 then
begin
IsPrime := False;
break
end;
IsPrime.Print;
end.
Для всех числовых типов также определены константы MinValue и MaxValue. Чтобы обратиться к ним, следует использовать имя типа:
integer.MinValue
real.MaxValue
Кортежи
Кортежи представляют собой способ объединить несколько значений в одно целое. Значения типа Кортеж записываются в круглых скобках: (1,2,3)
или ('Иванов',15)
. с помощью кортежей можно выполнять одновременные присваивания нескольким переменным:
begin
var a,b: integer;
(a,b) := (3,5);
(a,b) := (b,a);
end.
Присваивание (a,b) := (b,a)
позволяет поменять значения двух переменных.
Использование кортежей даже в начальных задачах крайне многообразно.
Пример 1. Нахождение наибольшего общего делителя
begin
var (a,b) := ReadInteger2;
while b>0 do
(a,b) := (b, a mod b);
Print('НОД = ', a);
end.
Пример 2. Числа Фибоначчи
begin
var (a,b) := (1,1);
loop 20 do
begin
Print(a);
(a,b) := (b, a + b);
end;
end.