===== Основные понятия =====
FIXME
== Структура программы ==
Общая структура программы на языке Паскаль задана жёстко и выглядит так:
Program <правильное имя>;
// Предложение, содержащее **заголовок программы**.
// Данное предложение может отсутствовать, поскольку в
// используемой нами системе Free Pascal
// и большинстве (во всех?) современных версий Паскаля
// никакой роли не играет.
// Оно оставлено для совместимости с другими версиями
// языка, которые его требуют.
// Например:
Program ChoiseSort3v;
// Предложения заканчивается точкой с запятой
Uses <список подключаемых библиотек>;
// **Раздел импорта**,
// который всегда состоит из одного предложения!
// Данное предложение может отсутствовать, если вы не
// используете никаких дополнительных библиотек.
// Например:
Uses CRT, OGLgraph;
// Список разделяется запятыми,
// предложения заканчивается точкой с запятой
<Раздел описаний>
// Раздел глобальных описаний может состоять из нескольких
// подразделов, порядок следования которых - свободный,
// но все они должны быть здесь - перед кодом.
//
// Этот раздел содержит описание всего, что
// не задано изначально,
// не импортируется из библиотек,
// не является локальным объектом внутри процедуры.
// А именно - именованные константы, пользовательские типы,
// переменные и наконец - имена меток.
//
// В принципе, этот раздел тоже может отсутствовать.
Begin // Обязательные операторные скобки Begin-end
<Раздел кода>
// Операторы, составляющие "главную процедуру"
// Чисто теоретически, их тоже может не быть!
// Тогда программа честно ничего не делает.
// Но "скобки" должны быть.
End. // Программа кончается точкой
Текст в **угловых скобках** (символы < и >) требует замены "по смыслу". Не путайте с **операциями** < и >!
Ещё раз обратите внимание на жёсткий порядок следования частей программы на этом уровне детализации её структуры. Все части идут именно в этом порядке и не повторяются. Но некоторые могут отсутствовать совсем.
== Раздел описаний ==
Раздел описаний может состоять из нескольких подразделов, разбитых по категориям описываемых объектов - типов, переменных, меток и констант. Отдельными подразделами считаются каждая функция или процедура.
const // Начался раздел констант
n = 10; // Описание (именованной) константы
var // Начался раздел глобальных переменных,
// значит - закончился раздел констант
i, j : integer; // 1-е описание переменных
r, q : real; // 2-е описание переменных
k, m : integer; // 3-е описание переменных - снова integer.
// Имеем право.
Begin
// Обязательный раздел кода
...
End. // Конец всему (в этой программе)!
Объекты программы могут быть связаны описанием.
const
n = 10; // Константа n определяет длину массива
type
Arr10 = array[1 .. n] of integer; // Используя n, описываем целый тип массивов
var
A,B : Arr10; // Используем описание типа Arr10 для описания переменных A, B
Запомните правило - **если что-то, описываемое вами, ссылается на что-то другое, то это другое должно быть описано заранее**. Например, если вы используете константу для описания массива (как в примере), то она должна быть описана выше по коду. Из этого правила есть единственное исключение, связанное с использованием указателей.
Учтите, что библиотечные объекты, т.е. объекты системные или описанные в библиотеках, подключённых с помощью //uses//, описывать не надо и на них можно ссылаться из любого места. Но, как мы узнаем позже, их имена можно "перекрыть"!
Ниже приведён неправильный код, где ничего не описывается заблаговременно.
var
A,B : Arr10; // А что это?
type
Arr10 = array[1 .. n] of integer; // И сколько же это будет?
const
n = 10;
В раздел описаний может входить несколько "однотипных" подразделов описаний.
var
i, j : integer; // Описали часть переменных
const
n = 10; // Спохватились и описали константу n
var
A,B : array[1 .. n] of integer; // "Дописали" ещё часть переменных
=== Полный пример ===
Подразделы могут следовать в любом порядке и повторяться.
В примере приводится "канонический" порядок следования подразделов - именованные константы, типы, переменные. За ними часто следуют описания одной или нескольких процедур и функций, которых в примере нет. Затем порядок может повториться. Это делается, чтобы разбить все объекты, используемые в программе "по смыслу" - типы, определённые пользователем, процедуры, работающие с этими типами и вспомогательные объекты - константы и служебные переменные.
Метки описываются там, где это удобно.
... // Здесь могли бы быть заголовок и раздел импорта
const // Начался 1-й раздел констант
Pi = 4.0; // Описание (именованной) константы
// Внимание - мы перекрыли системное определение Пи!
var // Начался 1-й раздел глобальных переменных,
// значит - закончился раздел констант
i, j : integer; // 1-е описание переменных
r, q : real; // 2-е описание переменных
k, m : integer; // 3-е описание переменных - снова integer. Имеем право.
const // Начался 2-й раздел констант
n = 10; // Описание (именованной) константы
type // Начался раздел типов
A10 = array[1..n] of integer;
// Это тип, определённый пользователем.
// Обратите внимание - мы использовали
// ранее описанную константу
var // Начался раздел переменных, закончился раздел типов
A,B : A10; // 4-е описание переменных пользовательского типа A10
... // Что-то ещё, возможно - ничего
// Где-то здесь кончается раздел переменных
label // Раздел меток нужен редко
1, endOfAll; // список объявленных меток
// Теперь это "законные" метки
... // Что-то ещё, возможно - ничего
Begin
// Обязательный раздел кода
...
End. // Конец всему (в этой программе)!
== Примеры программ нелепых, но синтаксически грамотных ==
Данная программа содержит только раздел кода, но он - пуст, так что программа самым честным образом ничего не делает. Ибо и не должна.
Begin
// Если убрать этот комментарий, то получится
// минимальная правильная программа на Паскале
// Впрочем, для Паскаля его и нет.
End.
Данная программа действительно работает (стирает с экрана следы работы предыдущих программ), но не содержит ни одного описания. Её реальный аналог есть, например, в операционной системе ДОС.
Uses
CRT; // без CRT не будет работать clrscr ("clearscreen")
Begin
clrscr; // команда очищает экран от результатов предыдущих вводов/выводов
End.
В данной программе есть все разделы (кроме описания функций), но она не выполняет никаких полезных действий.
Program Prog; // К бессмысленному предложению Program - бесполезное, но правильное имя
// Всё есть и никто ничего не делает.
Uses CRT, Graph; // Собираемся работать и с текстом, и с графикой, но так и не собирёмся
Const // Раздел констант
n = 5; // В данном случае n - не переменная, а другое обозначение 5.
m : integer = 6; // Один из ужасов Паскаля. Это - статическая переменная!
// Без понимания, что к чему, лучше не использовать,
// но это - настоящая переменная
Var // Раздел переменных
i:integer; // Запасная переменная - нам не потребуется
Label // Раздел меток.
BeeginProgram, // У меток описывать нечего, но они должны
EndProgram; // быть перечислены.
Type
S100 = string[100];
Procedure Proc(x:integer);
// Данная процедура принимает параметр x
// после чего всегда печатает:
// "Опять - 25. Не мешайте работать!"
Const
S2 = '. Не мешайте работать!';
Var
S1 : S100;
Begin:
x := n; // Для данной процедуры значения параметров не важны
S1 := 'Опять - ';
writeln(S1, x, S2 );
End;
Begin
BeginProgram: // Метка ничего не делает, но место указывает
; // Отсюда собираемся работать
goto EndProgram; // Хватит УЖЕ работать, пошли домой
Proc(n); // Здесь мы к счастью никогда не побываем,
goto BeginProgram; // иначе - никогда не выберемся
EndProgram: // Место у выхода
; // Перекур после честной работы
End. // Теперь - совсем всё
В данной программе есть все разделы (кроме описания функций), но она не выполняет никаких полезных действий.
===== Ввод/вывод =====
var
x, y, z: integer;
a, b, c: real;
var
x: integer;
a: real;
begin
read(x); {Сохранит введенное с клавиатуры в переменную x}
readln(a); {Сохранит введенное с клавиатуры в переменную a и добавит перевод строки}
end.
При вводе данных, они должны соответствовать "принимающим" переменным, т.е. нельзя ввести бессмысленные в языке Pascal значения, значения в формате другого типа (например, ввести значения 1.34 и даже 2.0 в целочисленную переменную) или выходящие за пределы диапазона значений, разрешённого для переменных указанного типа.
Заметьте, что в строковую переменную можно занести и "Мама мыла раму", и "2.0".
var
x: integer;
a: real;
begin
x := 2;
write(x); {Выведет на экран значение переменной x}
write('x= ', x);
writeln(x); {Выведет на экран значение переменной x и перейдет на следующую строку}
writeln('x= ', x);
a := 0.15;
writeln(a);
writeln(a * x);
writeln(a * x:4:1);
end.
Допустимо сразу выводить на экран значения выражений любой сложности без сохранения их в переменной. Частными случаями выражений являются вызовы функций, переменные и константы.
begin
write(0.3);
write( 0.15 * 2.0 );
writeln( sin(3.14) );
end.
Одним оператором (командой) ввода/вывода можно вводить/выводить значения нескольких аргументов, в том числе - разнотипных.
begin
writeln("Полученное значение ", 0.3); // Обратите внимание на пробелы
writeln( 100.0:5:2, '(км/ч)'); //
writeln( 200.0:5:2, '(км/ч)');
writeln( 300.0:5:2, '(км/ч)');
writeln( sin(3.14*1/2):8:4,
sin(3.14*1/4):8:4,
sin(3.14*1/8):8:4 );
end.
== Распространённые ошибки ==
Недопустимо следующее :
const
x=0.3;
var
y : integer;
A : array[1..9] of integer;
F : text;
begin
read (0.3); // чтение "в никуда" - нет переменной, которая примет введённое значение.
read (x); // тоже самое, но константа указана по имени
readln (0.15 * y); // тоже самое, но вместо константы - целое выражение
readln (A); // составной тип данных можно заполнять только по-элементно
readln (F); // "неудачное" чтение из файла F - и файл F не открыт, и не указана
// переменная-приёмник. Считать же саму файловую переменную F - нельзя!
end.
var
A : array[1..9] of integer;
F : text;
begin
writeln (x, 0.15 * y, 0.3); // Вывод - будет, но все выводимые значения сольются в нечто нечитаемое
writeln (A); // составной тип данных можно выводить только по-элементно
writeln (F); // "неудачнае" запись в файл F - и файл F не открыт, и не указано,
// что выводить. Выводить таким образом у файл F - нельзя!
end.