Turbo-Pascal.7
.0.pdf141
Заголовок |
PROGRAM |
Имя программы |
; |
|
программы |
||||
|
|
|
||
Упрощенно |
|
|
|
|
Обращение |
USES |
Имя модуля |
; |
|
к модулям |
||||
|
|
|
||
|
|
, |
|
Описание констант |
|
|
Описание типов |
|
|
Описание меток |
|
|
|
; |
|
Описание переменных |
|
|
Описание процедуры |
Раздел |
|
описаний |
||
|
||
Описание функции |
|
Оператор присваивания
|
|
Оператор процедуры |
|
|
Оператор goto |
|
|
Оператор if |
Имя |
: |
|
метки |
Оператор case |
|
|
|
Оператор repeat |
|
|
Оператор while |
|
|
Оператор for |
|
|
Составной оператор |
|
|
Пустой оператор |
|
|
Оператор with |
Раздел
операторов
Комментарий:
Пустой опера-
тор – просто пустое место. Нужен для синтаксической завершенности Паскаля. Вот программа с несколькими пустыми операторами: LABEL 1; BEGIN ; ; 1: ; ; END.
Оператор with
мы не проходили. Он употребляется вместе с записями
(record). Нужен для сокращения текста программы.
;
|
|
|
142 |
|
|
|
|
|
|
Эта ветка – |
|
Описание |
|
|
Выражение |
определение |
|
констант |
Имя |
|
для |
обычной |
|
= |
константы |
||||
|
константы |
константы |
|||
|
|
|
CONST
Имя |
|
|
|
Начальное |
Эта ветка – |
|
: |
Тип |
= |
определение |
|||
константы |
значение |
|||||
|
|
|
типизированной |
|||
|
|
|
|
|
константы |
;
Комментарий: Начальное значение – примеры начальных значений см. в 12.5
Описание |
|
TYPE |
Имя типа |
= |
тип |
|
|
типов |
|
|
|
|
|
|
|
|
|
|
|
|
; |
|
|
|
Порядковый тип |
|
Комментарии: |
|
|||
Тип |
|
|
|
|
|||
|
|
|
*) кроме файлового типа |
|
|||
|
Вещественный тип |
|
|
||||
|
|
Вещественный тип – это Real или |
|||||
|
|
|
|
||||
|
|
|
|
Single или Double или Extended или |
|||
Структурированный тип |
|
Comp. |
|
|
|||
Упро- |
|
|
|
Порядковый и вещественный типы вме- |
|||
щенно |
^ |
Тип* |
|
сте образуют простой тип. |
|
||
|
|
|
|
|
|
||
|
Pointer |
|
|
Эта двойная ветка – |
|
||
|
|
|
ссылочный тип |
|
|||
|
|
|
|
|
|
||
|
|
Целый тип |
|
|
Коммента- |
||
|
|
|
|
|
|
||
|
|
|
|
|
|
рий: |
|
Порядковый |
|
|
Char |
|
|
Целый тип – |
|
|
|
|
|
|
это |
Integer |
|
тип |
|
|
|
|
|
||
|
|
|
|
|
или |
LongInt |
|
|
|
|
Boolean |
|
|
или Word или |
|
|
|
|
|
|
|
Byte |
или |
|
|
Выражение |
|
Выражение |
ShortInt. |
||
|
|
|
|
|
|||
Диапазон |
|
для |
.. |
|
для |
|
|
|
константы |
константы |
|
|
|||
|
|
|
|
|
|||
Перечислимый |
|
( |
Имя |
|
) |
|
|
тип |
|
|
|
|
,
143
|
|
Порядковый |
|
of |
Тип |
array |
[ |
тип |
] |
||
|
|
, |
|
Тип record |
|
|
|
|
|
|
|
|
|
|
|
показан |
|
|
|
, |
|
упрощенно |
|
record |
|
Имя поля |
: |
Тип |
end |
|
|
; |
|
|
|
set of |
|
Порядковый |
|
|
|
|
тип |
|
|
|
|
|
|
|
|
|
|
|
|
[ |
Выражение |
] |
|
|
|
для константы |
|||
|
|
|
|
||
string |
|
|
|
|
|
Файловый тип
Объектный тип
Структурированный тип
Комментарии:
В этой диаграмме вы видите, что структурированный тип определяется через тип. Это – рекурсивное определение. Выход очевиден – вместо любого из элементов тип, встречающихся
вдиаграмме, вы можете мысленно подставить диаграмму типа целиком.
Файловый и объектный типы расшифрованы не будут.
Описание
меток
Описание
переменных
Целое число
LABEL Имя метки
,
,
VAR Имя переменной : Тип
;
144
Описание |
|
|
Описание |
процедуры |
|
|
функции |
PROCEDURE |
|
FUNCTION |
|
Имя процедуры |
|
Имя функции |
|
Список формальных параметров |
Список формальных параметров |
||
; |
: |
Имя типа |
; |
Раздел описаний |
|
Раздел описаний |
|
BEGIN |
|
BEGIN |
|
Раздел операторов |
|
Раздел операторов |
|
END |
|
END |
|
Опережающее описание процедуры или функции см. в 10.6
|
|
|
, |
|
|
|
Список |
|
|
|
|
|
|
формальных |
( |
VAR |
Имя параметра |
: |
Имя типа |
) |
параметров |
|
|
|
|
|
|
Упрощенно |
|
|
|
; |
|
|
|
|
|
|
|
|
Имя функции |
. |
Имя поля |
|
|
Имя переменной |
|
:= |
Выражение |
|
|
||
[ |
Выражение |
] |
|
Оператор |
, |
|
|
присваивания |
|
|
|
|
|
|
|
Упрощенно |
^ |
|
|
145
Оператор
процедуры
Оператор goto
Оператор if
Имя процедуры ( Выражение )
,
goto Имя метки
if Выражение then Оператор else Оператор
case |
Выражение |
of |
|
Оператор |
|
|
|
|
|
||
|
|
|
|
case |
|
|
; |
|
|
|
|
|
Выражение |
|
|
||
|
для |
|
|
|
|
|
константы |
|
|
||
Выражение |
|
Выражение |
: |
Оператор |
|
для |
.. |
для |
|||
|
|
||||
константы |
|
константы |
|
|
|
|
, |
|
|
|
|
|
; |
|
|
; |
|
|
|
|
|
else |
Оператор |
end |
;
Оператор repeat |
Оператор |
|
Выражение |
repeat |
until |
146
Оператор while |
while |
Выражение |
do |
Оператор |
|
|
|
|
|
Оператор for |
||
|
|
|
|
to |
|
|
|
for |
Имя |
:= |
Выражение |
Выражение |
do |
Оператор |
|
переменной |
|||||||
|
|
|
|
|
|
||
|
|
|
|
downto |
|
|
Составной
оператор
Выражение
Выражение
для
константы
;
begin Оператор end
Что такое выражение и примеры выражений см. в 14.3. Я бы мог дать точную синтаксическую диаграмму выражения, но она слишком длинна и запутана. Выражения, приведенные в синтаксических диаграммах, часто не могут быть любыми. Так, выражение в операторе if обязано быть логическим, а в операторе for - порядковым.
Выражение для константы чаще всего
– обычная константа (например, const k=-2; l=‘кю’). В общем случае это обычное выражение, состоящее из констант, некоторых стандартных функций, знаков операций и круглых скобок (например, const k=-5; m=(1+k)*abs(k))
Оператор |
Это любой из операторов, упомянутых в синтаксической |
|
диаграмме Раздел операторов. |
||
|
Имя переменной, имя константы и все прочие имена, упомянутые в синтаксических диаграммах, образуются согласно синтаксической диаграмме Имя.
147
Глава 15. Другие возможности Паскаля
На этом со строгостями покончили. Нам осталось рассмотреть несколько дополнительных возможностей Паскаля.
15.1. Работа с файлами данных
Мы пока знакомы с выводом данных только на экран, а со вводом - только с клавиатуры. Сейчас мы познакомимся с выводом данных в файл и со вводом из файла. Если вы еще не знакомы с понятием файла или каталога, прочтите приложение. Для определенности мы будем считать, что файл расположен на магнитном диске, хотя файл - достаточно общее понятие, которое может применяться к различным устройствам ввода, вывода и хранения информации.
В Паскале существует три типа файлов. Мы познакомимся с самым распространенным из них - текстовым файлом. Вам совершенно не обязательно знать, как физически устроен носитель, на который файл будет записываться. При работе с текстовым файлом удобно представлять, что носитель - не диск, состоящий из дорожек, а подобен листу бумаги или экрану монитора, файл же - это строки информации на этом листе или экране. Данные в текстовых файлах могут быть целыми или вещественными числами, символами, строками.
Задача: Записать слово ‘Азия’ и число 1998 на магнитный диск c: в текстовый файл с именем fedos, располагающийся в каталоге PASCAL.
Начнем с того, что придумаем файлу fedos псевдоним, которым мы будем пользоваться в программе. Пусть это будет fepas. Затем нам нужно объяснить Паскалю, что fepas - это текстовый файл, для чего мы начнем программу со строчки
VAR fepas :Text;
Раздел операторов начинаем с того, что объясняем Паскалю, какое настоящее имя соответствует псевдо-
ниму fepas:
Assign(fepas, 'c:\PASCAL\fedos');
Затем переместим магнитную головку в начало файла для записи информации в файл (откроем файл для записи):
Rewrite(fepas);
Теперь запишем в файл нужную информацию:
WriteLn(fepas, ‘Азия’);
WriteLn(fepas, 1998);
Поскольку мы не собираемся ничего больше писать в файл, то закрываем его для записи:
Close(fepas);
Вот программа целиком:
VAR fepas :Text;
BEGIN
Assign(fepas, 'c:\PASCAL\fedos');
Rewrite(fepas);
WriteLn(fepas, ‘Азия’);
WriteLn(fepas, 1998);
Close(fepas);
END.
После выполнения программы вы обнаружите в файле fedos две строки:
Азия
1998
Если бы вы вместо WriteLn использовали Write, то строка была бы одна:
Азия1998
Если к моменту выполнения программы файл fedos не существовал, то процедура Rewrite создаст пустой файл с таким именем в указанном каталоге. Если существовал, то стирает его содержимое.
148
Если вы не хотите стирать содержимое файла, а просто хотите дописать что-нибудь в его конец, то процедура Rewrite вам не подойдет. Вам вместо нее нужно будет употребить процедуру Append. Вот ее вызов -
Append(fepas).
Если вы знаете, какой каталог во время выполнения программы является текущим, и хотите, чтобы файл fedos был создан в текущем каталоге, вы можете записать просто
Assign(fepas, 'fedos')
Информация в наш файл может записываться только по порядку, последовательно. Мы не можем записать что-то сперва в начало файла, потом в конец, потом в середину. То же самое относится и к считыванию, о котором сейчас пойдет речь.
А теперь решим обратную задачу: В некоем файле fedos записаны строки. Вывести первую и третью из них на экран монитора.
VAR fepas :Text; |
|
|
|
|
|
a,b,c :String; |
{Три переменные в оперативной памяти, в которые будут |
|
|
записаны первые три строки из файла} |
|
BEGIN |
|
|
Assign(fepas, 'c:\PASCAL\fedos'); |
|
|
Reset(fepas); |
{Переместим магнитную головку в начало файла для считывания |
|
|
информации из файла (откроем файл для считывания) } |
|
ReadLn (fepas, a); |
{Читаем первую строку из файла} |
|
ReadLn (fepas, b); |
{Читаем вторую строку из файла} |
|
ReadLn (fepas, c); |
{Читаем третью строку из файла} |
|
Close(fepas); |
|
|
WriteLn(a); |
{Печатаем первую строку из файла} |
|
WriteLn(c); |
{Печатаем третью строку из файла} |
|
END.
Как видите, для того, чтобы добраться до третьей строки, нам пришлось прочитать вторую.
Если третья строка числовая, то можно было бы описать переменную c, как числовую, а не строковую.
А теперь напишем программу, которая в цикле записывает в файл 10 строк, а затем для проверки их считы-
вает.
VAR f |
:Text; |
|
|
||
a,b |
:String; |
|
i |
:Byte; |
|
BEGIN
Assign(f,'c:\PASCAL\textik.txt'); {Обозначим файл textik.txt из каталога PASCAL именем f} Rewrite(f); {Переместим магнитную головку в начало файла для
|
записи информации в файл (откроем файл)} |
|
WriteLn('Введите с клавиатуры 10 произвольных строк'); |
|
|
for i:=1 to 10 do begin |
|
|
ReadLn(a); |
{Ввести с клавиатуры в оперативную память произвольную строку текста} |
|
WriteLn(f,a) |
{Записать эту строку из оперативной памяти в файл} |
|
end; |
|
|
Close(f); |
{Закрываем файл для записи} |
|
WriteLn('А теперь посмотрим, что мы записали в файл:'); |
|
|
Reset(f); |
{Переместим магнитную головку в начало файла для |
|
|
считывания информации из файла (откроем файл)} |
|
for i:=1 to 10 do begin |
|
|
ReadLn(f,b); |
{Переслать из файла в оперативную память строку текста} |
|
WriteLn(b) |
{Послать эту строку из оперативн.памяти на монитор} |
|
end; |
|
|
Close(f); |
{Закрываем файл для чтения} |
|
END.
Если вы хотите прочесть текстовый файл, но не знаете, сколько там строк, то вам нужно какое-то средство, чтобы компьютер определил, когда заканчивается файл. Это средство - функция EOF (сокращение от end of file
– «конец файла»). Вот фрагмент, решающий дело: |
|
|
|||
|
while |
NOT |
EOF(fepas) |
do |
... ReadLn(fepas, ....) |
|
пока |
нет |
конца файла fepas |
делай |
… |
|
Задание 126: |
“База данных ваших школьных оценок”. Вы завели файл, в который записываете свои |
школьные оценки. Каждый раз, получив оценку, вы дописываете в файл оценку и предмет, по которому оценка получена. Создайте 4 программы:
149
1)Для дозаписи в конец файла очередной оценки и предмета.
2)Для вывода на экран всего файла.
3)Для вывода на экран всех отметок по заданному предмету. (Для определенности договоримся, что больше 1000 оценок в год вы не получите.)
4)Для определения, сколько было по заданному предмету таких-то оценок (скажем, троек).
Оформите каждую из четырех программ, как процедуру, и создайте единую программу - “Систему управления базой данных”, которая начинает работу с вопроса: “Чем будем заниматься - дозаписывать, выводить весь файл ...?” и в зависимости от ответа запускает одну из четырех процедур.
Задание 127: Вы можете помочь адмиралу из 12.13 и организовать чтение из файла всей нужной информации о подлодках.
Задание 128: Многие компьютерные игры позволяют “сохраняться”, то есть в любой момент игры при
нажатии определенной клавиши записывать в файл все данные об этом моменте, чтобы в следующий раз, когда вы сядете играть, начинать не сначала, а с того момента, в который вы записались. В игре “Торпедная атака” ор-
ганизуйте при нажатии на клавишу S сохранение, то есть запись в файл имени игрока, уровня игры, количества выстрелов и количества попаданий. А при запуске игра должна спрашивать, будем ли возобновлять сохраненную игру или начинать новую.
15.2. Вставка в программу фрагментов из других программных файлов
Теперь рассмотрим совсем другие файлы – те, в которых вы храните свою программу. Предположим, вы с другом решили создать программу из 7 процедур. Вы делаете 3 процедуры и тело программы, а ваш друг - 4 процедуры. Друг записал все 4 процедуры в файл VSTAVKA.pas на вашем компьютере. Вот он:
PROCEDURE fa ; BEGIN Sound(698); Delay(300); NoSound END;
PROCEDURE sol; BEGIN Sound(784); Delay(300); NoSound END;
PROCEDURE la ; BEGIN Sound(880); Delay(300); NoSound END;
PROCEDURE si ; BEGIN Sound(988); Delay(300); NoSound END;
Конечно, файл вашего друга не является законченной программой и сам по себе не запускается. А вот ваша программа:
USES CRT;
PROCEDURE doo; BEGIN Sound(523); Delay(300); NoSound END; PROCEDURE re ; BEGIN Sound(587); Delay(300); NoSound END; PROCEDURE mi ; BEGIN Sound(659); Delay(300); NoSound END;
BEGIN doo;re;mi;fa;sol;la;si;la;sol;fa;mi;re;doo
END.
Теперь вам нужно собрать оба куска в единую программу. Для этого вы можете скопировать текст из файла вашего друга в свой файл (как это делается, расказано в части IV). Но если вы не хотите этого делать, чтобы,
скажем, не увеличивать свой файл, вы можете воспользоваться директивой компилятора $I. Директива компилятора - это специальная инструкция, вставленная в текст вашей программы на Паскале и предназначенная для управления компьютером на этапе компиляции вашей программы. Директива компиляции имеет вид {$....} и Паскаль не путает ее с обычным комментарием только из-за наличия значка доллара. Символы, стоящие после значка доллара, и являются управляющей информацией для компилятора. Директива {$I c:\PASC\F25} является приказом компилятору подставить в это место текст, находящийся в файле F25 из каталога PASC диска c. Если файл находится в текущем каталоге, то достаточно указать его имя. Вот ваша готовая к работе программа с директивой:
USES CRT;
PROCEDURE doo; BEGIN Sound(523); Delay(300); NoSound END;
PROCEDURE re ; BEGIN Sound(587); Delay(300); NoSound END;
PROCEDURE mi ; BEGIN Sound(659); Delay(300); NoSound END;
{$I VSTAVKA} {Директива компилятору на вставку текста из файла VSTAVKA}
BEGIN doo;re;mi;fa;sol;la;si;la;sol;fa;mi;re;doo
150
END.
15.3. Модули программиста
Известно, что в Паскале нет стандартной функции, возводящей число в целую неотрицательную степень. В целую степень, большую двух. Предположим, что вы математик, и вам нужна функция, возводящая число в любую целую неотрицательную степень. Напишем эту функцию:
FUNCTION st(a:Real; |
n:Word) :Real; |
|
|
|
|||
VAR step |
:Real; |
|
|
i |
:Word; |
|
|
BEGIN |
|
|
|
step:=1;
for i:=1 to n do step:=step*a; st:=step
END;
BEGIN
WriteLn(st(2,3))
END.
Пусть вы часто пишете программы, использующие возведение в степень. Но вам лень в каждую такую программу вставлять описание функции st. Вы можете пойти двумя путями:
Описать st и другие часто встречающиеся процедуры и функции в другом файле и использовать директиву $I.
Описать st и другие часто встречающиеся процедуры и функции в другом файле и оформить этот файл, как новый модуль.
Второй способ немного сложнее, но намного лучше первого. Вот как будет выглядеть ваш модуль:
UNIT Mathemat; |
{Заголовок модуля с придуманным вами именем} |
|
|
||
INTERFACE |
{Раздел ИНТЕРФЕЙСА} |
|
FUNCTION st(a:Real; n:Word) :Real; |
|
|
IMPLEMENTATION {Раздел РЕАЛИЗАЦИИ} |
|
|
FUNCTION st; |
|
|
VAR step |
:Real; |
|
i |
:Word; |
|
BEGIN |
|
|
step:=1;
for i:=1 to n do step:=step*a;
st:=step |
|
END; |
|
BEGIN |
{Раздел ИНИЦИАЛИЗАЦИИ, у нас он пуст} |
END. |
|
Вам нужно просто ввести этот текст, как обычную программу, в новое окно текстового редактора и сохранить на диске под именем Mathemat.pas, так как имя файла, в котором расположен модуль, должно совпадать с именем модуля. Однако, модуль не является программой и не может быть запущен на выполнение сам по себе. Пользоваться вашим новым модулем вы можете так же, как обычным стандартным. Вот ваша программа, вызывающая модуль:
|
|
|
|
|
|
USES Mathemat; |
|
|
|
|
BEGIN |
|
|
|
|
WriteLn(st(10,6) :20:4); |
{Это 10 в шестой степени} |
|
|
|
WriteLn(st(5, 3) :20:4); |
{Это 5 в кубе} |
|
|
|
END. |
|
|
|
|
|
|
|
|
|
|
|
|
|
Файл-модуль на первых порах сохраняйте в том же каталоге, что и файл вызывающей его программы.
Вразделе интерфейса вы приводите заголовки предназначенных для использования процедур, функций,
атакже описания типов, переменных и констант, которые вы также не хотите каждый раз описывать в вызывающей программе. В общем, все то, чем могут пользоваться другие программы.