файлами - Южный федеральный университет

advertisement
ФЕДЕРАЛЬНОЕ ГОСУДАРСТВЕННОЕ ОБРАЗОВАТЕЛЬНОЕ
УЧРЕЖДЕНИЕ ВЫСШЕГО ПРОФЕССИОНАЛЬНОГО ОБРАЗОВАНИЯ
«ЮЖНЫЙ ФЕДЕРАЛЬНЫЙ УНИВЕРСИТЕТ»
Т. П. ШЕСТАКОВА
ПРОГРАММИРОВАНИЕ ПРОСТЫХ ТИПОВ ДАННЫХ
И РАБОТА С ФАЙЛАМИ В СИСТЕМЕ PASCAL
(учебное пособие)
Ростов-на-Дону
2008
Рецензенты:
профессор кафедры физики полупроводников ЮФУ
доктор физико-математических наук Тополов В. Ю.
профессор кафедры "Физика" РГУПС
доктор физико-математических наук Лагутин Б. М.
Шестакова Т.П.
Программирование простых типов данных и работа с файлами в
системе Pascal: Учебное пособие.  Ростов-на-Дону, 2008.  82 с.
Учебное пособие содержит вводные сведения о языке программирования
Pascal. В нем описываются структура программы на языке Pascal, операторы ввода-вывода данных, стандартные математические функции языка Pascal, условный
оператор и оператор выбора, различные формы операторов циклов, простые типы
данных (целочисленные, вещественные, перечисляемые, тип-диапазон), сведения
о работе с файлами (типизированными, текстовыми, нетипизированными) и строками (которые представляют собой основной тип данных, используемых в текстовых файлах). В каждом разделе приводятся варианты заданий для самостоятельной работы. Учебное пособие предназначено для студентов физического факультета, изучающих курс "Программирование и вычислительная физика".
2
Содержание
Введение ………………………………………………………………………………..6
1. Структура программы на языке Pascal …………………………………………….7
1.1. Заголовок программы ………………………………………………………7
1.2. Раздел описаний ……………………………………………………………8
1.2.1. Описание констант ………………………………………………...8
1.2.2. Описание переменных и простейшие типы данных …………….9
1.3.
Раздел
операторов.
Операторы
ввода-вывода
и
оператор
присваивания……………………………………………………………..11
1.4. Задания по теме 1………………………………………………………….15
2. Арифметические и логические операции и стандартные функции…………….15
2.1. Арифметические операции в языке Pascal……………………………….15
2.2. Операции сравнения и логические операции……………………………16
2.3. Стандартные математические функции языка Pascal…………………...16
2.4. Приоритет операций в языке Pascal………………………………………17
2.5. Функции преобразования типов………………………………………….18
2.6. Задания по теме 2………………………………………………………….19
3. Условный оператор………………………………………………………………...20
3.1. Полный вариант условного оператора………………………...…………20
3.2. Краткий вариант условного оператора………………………...…………21
3.3. Операторные скобки begin ... end…………………………………..22
3.4. Задания по теме 3………………………………………………………….23
4. Операторы циклов………………………………………………………………….24
4.1. Оператор цикла for .. do……………………………………………..24
4.2. Оператор цикла while .. do………………………………………….27
4.3. Оператор цикла repeat .. until……………………………………28
4.4. Задания по теме 4………………………………………………………….29
5. Целочисленные типы данных……………………………………………………..30
3
5.1. Типы данных и диапазон значений………………………………………30
5.2. Ошибки, связанные с неправильным выбором типа данных…………...32
5.3. Стандартные функции, применимые к целочисленным типам данных.32
5.4. Пример: вычисление суммы цифр числа……………………...…………33
5.5. Задания по теме 5………………………………………………………….34
6. Вещественные типы данных……………………………………………………….36
6.1. Типы данных и диапазон значений………………………………………36
6.2. Пример вычислений с заданной точностью……………………………..37
6.3 Задания по теме 6………………………………………………………..…42
7. Перечисляемый тип, тип-диапазон и оператор case……………………………43
7.1. Оператор выбора…………………………………………………………..43
7.2. Перечисляемый тип………………………………………………………..45
7.3. Тип-диапазон……………………………………………………………....45
7.4. Пример использования перечисляемого типа данных и оператора
выбора case..............................................................................................46
7.5 Задания по теме 7…………………………………………………………..50
8. Файлы……………..………………………………………………………………...52
8.1. Общие сведения о работе с файлами……………………………………..52
8.1.1. Открытие файла…………...………………………………………53
8.1.2. Стандартные имена логических устройств…………...…………54
8.1.3. Открытие файла для чтения……………...……………………....54
8.1.4. Открытие файла для записи………………...…………………....55
8.1.5. Стандартные процедуры для работы с файлами любого типа...56
8.1.6. Стандартные функции для работы с файлами любого типа…...57
8.2. Типизированные файлы…………………………………………………...58
8.2.1. Стандартные процедуры для работы с типизированными
файлами……………………………………………………………58
8.2.2. Стандартные функции для работы с типизированными
4
файлами……………………………………………………………60
8.2.3. Пример работы с типизированным файлом…...………………...60
8.3. Текстовые файлы…………………………………………………………..62
8.3.1. Стандартные процедуры для работы с текстовыми файлами.63
8.3.2. Стандартные функции для работы с текстовыми файлами…65
8.3.3. Пример работы с текстовым файлом………………………….66
8.4. Нетипизированные файлы………………………………………………68
8.5 Задания по теме 8………………………………………………………...68
9. Строки (тип данных string)………………………………………………….…69
9.1. Описание строкового типа данных………………………………………69
9.2. Операции над строками в языке Pascal………………………………..71
9.3. Стандартные процедуры для работы со строками………………………72
9.4. Стандартные функции для работы со строками………………………..73
9.5. Пример: редактирование текстового файла……………………………...75
9.6 Задания по теме 9…………………………………………………………..81
Литература…………………………………………………………………………….82
5
Введение
Настоящее учебное пособие имеет целью познакомить студентов с простейшими типами данных, используемых в системе программирования Pascal,
структурой программы и основными операторами языка Pascal, что включает
операторы ввода-вывода, условный оператор и оператор выбора, операторы циклов. Поскольку ввод-вывод данных может осуществляться не только с клавиатуры
и на экран компьютера, но и в файлы, сохраняемые на различных носителях информации, значительная часть данного учебного пособия посвящена работе с
файлами в системе программирования Pascal. Описываются текстовые, типизированные и нетипизированные файлы, а также операторы, необходимые для работы
с ними, и строковый тип данных, используемый в текстовых файлах.
В настоящее время имеется большое количество книг по программированию на языке Pascal. В качестве примера можно привести книги [1  6], содержащие исчерпывающие сведения о структурах этого языка программирования. При
подготовке учебного пособия ставилась цель дать краткое изложение, которое
может быть использовано студентами как при овладении основными приемами
программирования на языке Pascal, так и в дальнейшей работе в качестве справочного материала. В каждом разделе приводятся небольшие учебные программы, демонстрирующие использование конструкций языка, а также варианты заданий по программированию для самостоятельной работы студентов, направленные
на закрепление материала по каждой теме.
Предполагается, что читатели имеют некоторые навыки работы на компьютере, знакомы с системой Windows и различными типами файлов, имеют представление о принципах функционирования компьютера, алгоритмах и программах, системах счисления и хранении информации в памяти компьютера.
6
1. Структура программы на языке Pascal
Отличительной особенностью языка Pascal по сравнению с языками более
низкого уровня является необходимость описания всех используемых в программе констант и переменных. В связи с этим каждая программа, помимо исполняемой части, которая называется разделом операторов, или телом программы, содержит также раздел описаний. Этот раздел, помимо перечисления всех констант
и переменных с указанием их типов, может включать описание введенных программистом типов данных, процедур и функций. Таким образом, структуру программы на языке Pascal можно представить следующей схемой:
Заголовок программы
Program <имя программы>;
Раздел описаний
 Описание констант
 Описание типов данных
 Описание переменных
 Описание функций
 Описание процедур
Раздел операторов
begin
<операторы>
end.
Рис. 1. Структура программы на языке Pascal
1.1. Заголовок программы.
Заголовок программы содержит зарезервированное, служебное слово program, которое используется только для объявления имени программы:
Program <имя программы>;
7
Имя программы, так же как имена используемых в программе констант, переменных, процедур, функций и т. д., называется идентификатором (поанглийски  identifier). Идентификаторы задаются программистом, при этом используются следующие правила:
 идентификатор может состоять из букв латинского алфавита, цифр, знака
подчеркивания; никакие другие символы в идентификаторе недопустимы;
 идентификатор не может начинаться с цифры;
 идентификатор не может совпадать ни с одним из зарезервированных слов;
 длина идентификатора может быть произвольной, но значащими считаются
первые 63 символа.
Заметим, что в языке Pascal нет различия между прописными и строчными
(большими и маленькими) буквами при написании служебных слов, операторов и
идентификаторов.
Как и любой оператор в языке Pascal, заголовок оканчивается точкой с запятой. Заметим, что заголовок программы является необязательным, и его можно
опускать. Примеры:
Program First;
Program P12_v3;
1.2. Раздел описаний.
В рамках данного учебном пособии нас будут интересовать в основном
описание констант и переменных; при рассмотрении оператора выбора мы познакомимся с описанием перечисляемого типа данных и типа-диапазона. Процедуры
и функции относятся к более сложным конструкциям языка Pascal и в данном пособии не рассматриваются.
1.2.1. Описание констант:
const <имя константы> = <значение константы>;
Здесь используется служебное слово const – сокращение от английского
constant – постоянная. Примеры описания констант:
8
const
c=300000000;
{скорость света}
e=1.6021892E-19;
(*заряд электрона*)
В последнем случае использован стандартный формат представления действительных чисел, при котором вместо десятичной запятой ставится точка, а символ
“E” отделяет порядок числа (степень десяти), соответственно, заряд электрона равен 1,6021892·10-19 Кл.
В данном примере были использованы комментарии – это часть программы, заключенная в фигурные скобки. Она игнорируется компилятором и никак не
отражается на работе программы. Альтернативно, комментарий можно ограничивать парой символов круглая скобка + звездочка.
1.2.2. Описание переменных и простейшие типы данных.
var <имя переменной>: <тип переменной>;
Служебное слово var – сокращение от английского variable – переменная.
Для того, чтобы описывать переменные, нам необходимо получить представление
о типах данных в языке Pascal.
Выделим наиболее часто употребляемые из простейших типов данных.
integer целочисленные данные от 32768 до +32767; занимают 2 байта;
real
действительные данные, диапазон значений модуля от 2.9E39 до
1.7E+38; точность представления данных  11..12 значащих цифр;
char
символ, занимает 1 байт;
string
строка символов;
boolean логический тип, занимает 1 байт и имеет два значения:
false  ложь; true  истина.
Все пять целочисленных типов данных будут рассмотрены в разделе 6, пять
действительных типов данных – в разделе 7, в разделе 8 – перечисляемый тип и
тип-диапазон. Примеры описания переменных:
9
var
a1,a2,a3:integer;
b1,b2,b3:real;
c1:char;
s1:string;
Переменные одного типа могут быть перечислены через запятую.



 byte



shortint






целые word



integer





 порядковые 
longint


 логические





 символьные
 простейшие 




 перечисляемые


 тип-диапазон



single


real




Типы данных 
действительные

double


extended





comp



 массивы

 файлы


 структурированные 
 записи

множества


 указатели
 строки

 процедурные
 объекты

Рис. 2. Типы данных в языке Pascal
10
1.3. Раздел операторов. Операторы ввода-вывода и оператор присваивания.
Раздел операторов – это основная часть программы, она ограничивается
служебными словами begin и end. В конце программы ставится точка. Все, что
вы напишете после точки, будет проигнорировано компилятором.
Любая программа предназначена для обработки данных, вводимых пользователем, и вывода результатов этой обработки. Работу пользователя с программой
облегчает вывод на экран сообщений о том, для чего предназначена данная программа, какие действия в данный момент она выполняет или ожидает от пользователя. Появление таких сообщений свидетельствует о культуре программирования.
Вывод
сообщений
можно
организовать
с
помощью
оператора
write/writeln, который, кроме того, позволяет вывести на экран значение
констант, переменных или выражений. Действие оператора writeln отличается
от оператора write тем, что оператор writeln после вывода информации переводит курсор на следующую строку. Оператор writeln без аргументов просто переводит курсор на следующую строку.
Предположим, что начинающий программист решил вывести на экран радостное сообщение: “Это моя первая программа!”. Для этого можно использовать
оператор
writeln('Это моя первая программа!');
Здесь в скобках стоит строковая константа (она заключается в апострофы).
Этот оператор выведет на экран строку “Это моя первая программа!”, уже без
апострофов, после чего курсор будет установлен в строке, следующей за текстом
сообщения. Той же цели можно достичь иначе, определив строковую константу
const
s='Это моя первая программа!';
begin
writeln(s);
11
. . .
end.
Также можно определить строковую переменную. Для этой цели нам понадобится оператор присваивания, который имеет вид:
<имя переменной> := <значение переменной /
результат вычисления выражения>;
В данном случае мы можем использовать операторы
s1:='Это моя первая программа!';
writeln(s1);
Другие примеры оператора присваивания:
a1:=5;
b1:=2.1;
c1:='A';
Выведем на экран значения этих переменных.
write(a1,b1,c1);
На экране увидим
5 2.1000000000E+00A
Значение переменной b1 выведено в стандартном формате с плавающей
точкой, принятом по умолчанию. Численные значения отделяются друг от друга
пробелом, однако значение символьной переменной c1 не отделяется от значения переменной b1. Для того, чтобы значения переменных было легче воспринимать, можно задать формат вывода действительных чисел:
<имя переменной>:<общее количество позиций>:<количество десятичных знаков после запятой>
Иными словами, после имени действительной переменной ставится двоеточие, после которого указывается общее количество позиций для вывода числа,
включая десятичную точку и знак числа, затем снова ставится двоеточие, после
которого указывается количество десятичных знаков после запятой. После имени
12
целой или символьной переменной также можно указать количество позиций для
вывода их значений:
<имя переменной>:<количество позиций>
Полезно также использовать строковые константы для сообщений о том,
значения каких переменных выводятся на экран. Оператор
write(‘a1=’,a1:2,‘ b1=’,b1:5:2,‘ c1=’,c1:3);
выведет на экран сообщение “a1=”, затем значение переменной a1, на которое
будет отведено 2 позиции, сообщение “ b1=”, затем значение переменной b1, на
которое будет отведено 5 позиций, в том числе две – на десятичные знаки после
запятой, наконец, сообщение “ c1=” и значение переменной c1, на которое будет
отведено 3 позиции. Знаки пробелов перед “b1=” и “c1=” отделяют эти сообщения
от предшествующих численных значений:
a1= 5 b1= 2.10 c1=
Для
ввода
A
информации
с
клавиатуры
используется
оператор
read/readln. Когда в программе встречается этот оператор, ее работа прерывается, и компьютер переходит в режим ожидания до тех пор, пока пользователь не
введет
на
клавиатуре
значения
переменных,
указанных
в
операторе
read/readln, и не нажмет клавишу ENTER. Например, оператор
read(a2,a3);
считывает значения переменных a2 и a3 (значения должны вводиться через пробел), оператор
readln(s1);
считывает строку символов s1. Как и в случае оператора writeln, оператор
readln после ввода информации переводит курсор на следующую строку. Разница между операторами read и readln проявляется при работе с файлами (заметим, что ввод-вывод данных можно осуществлять не только с клавиатуры и на
экран, но также их файла и в файл, при этом используются те же самые операторы
ввода-вывода). Оператор readln без аргументов переводит систему в состояние
13
ожидания,  работа программы прерывается и компьютер ждет нажатия клавиши
ENTER. После этого программа продолжает работу.
Далее следует пример программы, которая осуществляет ввод двух чисел с
клавиатуры с последующим вычислением их суммы и выводом суммы на экран.
Program First;
{Комментарий: это заголовок программы}
(* Далее начинается раздел описаний *)
var
a1,a2,a3: integer;
{Конец раздела описаний}
{Начало раздела операторов}
begin
writeln('Введите два числа: a1 и a2');
write('a1 = ');
readln(a1);
write('a2 = ');
readln(a2);
a3:= a1+a2;
writeln('Сумма чисел a1 и a2: ',a3);
readln;
end.
1.4. Задания по теме 1: Структура программы на языке Pascal. Простейшие типы данных. Операторы ввода-вывода.
Написать простейшую программу на языке Pascal, которая программа должна выполнять следующие действия:
a) выводить на экран сообщение о том, для чего предназначена данная программа, например, "Программа находит сумму двух целых чисел";
b) считать данные с клавиатуры;
14
c) по заданным значениям переменных произвести вычисления и вывести результат на экран.
В программе необходимо вычислить:
1) сумму двух действительных чисел;
2) сумму целого и действительного чисел;
3) произведение двух целых чисел;
4) произведение целого и действительного чисел;
5) разность двух целых чисел;
6) разность двух действительных чисел;
7) разность целого и действительного чисел;
8) частное от деления двух целых чисел;
9) частное от деления двух действительных чисел;
10) частное от деления целого и действительного чисел.
2. Арифметические и логические операции
и стандартные функции
2.1. Арифметические операции в языке Pascal:
+
сложение;

вычитание;
*
умножение;
/
деление;
div
целочисленное деление;
mod
получение остатка от целочисленного деления.
Подчеркнем, что div и mod являются операциями (а не функциями) языка
Pascal, такими же, как умножение или вычитание. В тексте программы они с обе-
15
их сторон отделяются пробелами. Проиллюстрируем их использование несколькими примерами.
x:=22/5;
writeln(x:4:2);
(На экране появится результат 4.40.)
a:=22 div 5;
writeln(a:1);
(На экран будет выведено 4 – целая часть числа 4.40.)
x:=22 mod 5;
writeln(x:4:2);
(На экран выводится 2.00 – остаток от деления 22 на 5.)
2.2. Операции сравнения и логические операции. Помимо арифметических операции, в языке Pascal имеются операции сравнения:
=
равно;
<>
не равно;
<
меньше;
>
больше;
<=
меньше или равно;
>=
больше или равно.
Используются следующие логические операции:
not
логическое не;
and
логическое и;
or
логическое или;
xor
исключающее или.
2.3. Стандартные математические функции языка Pascal:
abs(x)
абсолютное значение (модуль) числа;
arctan(x)
арктангенс;
cos(x)
косинус;
16
exp(x)
экспонента;
frac(x)
дробная часть аргумента;
int(x)
целая часть аргумента;
ln(x)
натуральный логарифм;
pi
значение числа  = 3,1415926...;
sin(x)
синус;
sqr(x)
квадрат аргумента;
sqrt(x)
квадратный корень.
Аргументами всех функций (кроме функции pi, не имеющей аргумента)
могут быть действительные и целые числа. Значениями всех перечисленных
функций являются действительные числа. Заметим, что в языке Pascal не сущеn
ствует операции возведения в степень. Выражение типа x в общем случае может
n
быть вычислено по формуле x n  e ln x  e n ln x , используя экспоненциальную
функцию и логарифм. В частных случаях, когда n =2, 3, 4, можно использовать
функцию sqr(x) и операцию умножения. Подобным образом, в языке Pascal отсутствует стандартная функция tg  x  , и ее следует вычислять как отношение синуса к косинусу.
Следующий фрагмент программы иллюстрирует тот факт, что сумма квадратов синуса и косинуса любого аргумента равна 1.
write('Введите любое действительное число: ');
readln(x);
x:=sqr(sin(x))+sqr(cos(x));
writeln('Сумма квадратов синуса и косинуса равна ', x:4:2);
2.4. Приоритет операций в языке Pascal. При написании математических
выражений в языке Pascal необходимо соблюдать приоритет операций: в первую
очередь выполняются действия в скобках, затем – умножение и деление, в том
числе – целочисленное, и, наконец, сложение и вычитание. При записи сложных
17
выражений очень важно следить за правильной расстановкой скобок. Приоритет
операций всех типов представлен в следующей таблице:
1
not;
2
*, /, div, mod, and;
3
+, -, or, xor;
4
=, <>, <, >, <=, >=.
2.5. Функции преобразования типов:
round(x)
округляет действительное число до ближайшего целого;
trunc(x)
преобразует действительное число в целое путем отбрасывания
дробной части.
Аргументами этих функций являются действительные числа, значениями  целые.
Различие в этих функциях демонстрируется следующим примером: оператор
writeln(round(7.5):3,trunc(7.5):3);
выведет на экран значения “ 8 7”.
ord(x)
возвращает код символа; аргументом является любой символ,
значением  целое.
chr(x)
возвращает символ по заданному коду; аргументом является целое число от 0 до 255, значением  символ.
Прописные буквы латинского алфавита (A – Z) имеют коды 65 – 90 (26
букв), строчные буквы латинского алфавита (a – z) – 97 – 122. Коды букв русского
алфавита зависят от того, какая система кодировки символов используется. В кодировке Windows большие буквы русского алфавита (А – Я) имеют коды 192 –
223 (32 буквы, кроме буквы Ё, которая имеет код 168), а маленькие буквы (а – я) –
224 – 255 (буква ё имеет код 184). В кодировке DOS большие буквы русского алфавита (А – Я) имеют коды 128 – 159, а маленькие буквы – 160 – 175 (а – п) и 224
– 239 (р – я), буквы Ё и ё в этой кодировке отсутствуют.
Операторы
writeln(ord('A'));
18
writeln(ord('b'));
выведут на экран коды латинских букв A и b, соответственно, 65 и 98. Функции
ord(x) и chr(x) являются обратными друг другу; оператор
writeln(chr(ord('A')));
выведет на экран латинскую букву A.
2.6. Задания по теме 2: Стандартные математические функции языка
Pascal.
В следующих заданиях x, y, z  заданные действительные числа. Написать программу, которая вычисляет a, b, если
1) a 
2) a 
x 1  3 y
2
2
y
x
1

2
4
3  e y 1
1  x 2 y  tgz 
3) a  1  y 
x
e  x2

; b 1 y  x 
y 
2
 y  x 2
2

y
x 2  4 ; b  1  cos y  2  ;
1
x4
 2
 sin 2  z 
x 4
2
z
; b  1  tg 2   ;
2
x
4) a  y 

; b  x arctg z   e  x 3 ;
x2
y  x3 3


2 cos x  
z2
6

5) a 
;
; b 1
2
1
z
2
 sin  y 
3
2
5
6) a 
1  sin 2  x  y 
2 x
2x

 1 
 x; b  cos2  arctg   ;
 z 

1 x2 y2
19
yx
3
3
;


y
x x 

x2
z



4


7) a  ln y 
8) a 
9) a 
x y
1  xy
x 
; b
x
tg 2  z 


3
5
; b  x  x  x ;

3
5


;
  z 
; b  sin  ln 2    ;
2 y
  8 
1
3
 x 2  3y  2 
; b  3  x  12  5  z  13 .
10) a  ln 

z  1 

3. Условный оператор
3.1. Полный вариант условного оператора. Условный оператор в языке
Pascal имеет следующий вид:
if <условие>
then <оператор 1, который нужно выполнить
в случае, если условие справедливо>
else <оператор 2, который нужно выполнить
в случае, если условие нарушено>;
В следующей небольшой программе использование условного оператора
иллюстрируется на примере нахождения максимального из двух чисел.
Program If_operator_1;
var
a,b,max:real;
begin
write('Эта программа находит максимальное ');
writeln('из двух действительных чисел.');
20
writeln('Введите два числа:');
write('a= ');
readln(a);
write('b= ');
readln(b);
if a>b
then max:=a
else max:=b;
writeln('max= ', max);
writeln;
end.
3.2. Краткий вариант условного оператора. В условном операторе может
отсутствовать ветвь else. В этом случае оператор выглядит следующим образом:
if <условие>
then <оператор, который нужно выполнить,
если условие справедливо>;
Найдем максимальное из двух чисел, используя краткий вариант условного
оператора:
Program If_operator_2;
var
a,b,max:real;
begin
write('Эта программа находит максимальное ');
writeln('из двух действительных чисел.');
writeln('Введите два числа:');
write('a= ');
readln(a);
write('b= ');
readln(b);
21
max:=a;
if a<b
then max:=b;
writeln('max= ', max);
writeln;
end.
3.3. Операторные скобки begin ... end. Если ветви then или else
должны содержать более одного оператора, в качестве <оператор 1> и/или
<оператор 2> следует использовать составной оператор
begin
<операторы>
end
Служебные слова begin и end выполняют функцию операторных скобок, ограничивающих группу операторов.
Немного усложним задачу: найдем максимальное из двух чисел a и b, при
этом, если максимальным окажется число a, его следует возвести в квадрат, если
же максимальным окажется число b, его следует возвести в куб.
Program If_operator_1;
var
a,b,max:real;
begin
write('Эта программа находит максимальное ');
writeln('из двух действительных чисел.');
writeln('Введите два числа:');
write('a= ');
readln(a);
write('b= ');
readln(b);
22
if a>b
then begin
writeln('Максимальное число: ',a:5:2);
writeln('Результат: ',sqr(a):5:2);
end
else begin
writeln('Максимальное число: ',b:5:2);
writeln('Результат: ',b*sqr(b):5:2);
end
writeln;
end.
3.4. Задания по теме 3: Условный оператор.
В следующих заданиях x, y, z заданные действительные числа. Написать программу, которая вычисляет f, если
1) f x, y, z   max  x, y, z  ;
2) f  x, y, z   min  x, y, z  ;
3) f  x, y, z   max  x  y  z, xyz  ;
z


4) f x, y, z   min 2  x  y  , xyz   1 ;
2


 x  y, если x  y;
5) f x, y   
 y  x  1, если x  y;
 x 2 , если  2  x  2;
6) f x   
4, если x  2 и x  2;
 x 2  4 x  5, если x  2;

7) f  x   
1
 x 2  4 x  5 , если x  2;
23
 0, если x  0;

8) f  x    x, если 0  x  1;
 x 4 , если x  1;

0, если x  0;


9) f  x    x 2  x, если 0  x  1;
 x 2  sin x 2 , если x  1;

 
0, если
10) f x, y   
 x, если
x  y   0;
x  y   0.
4. Операторы циклов
4.1. Оператор цикла for .. do. Общий вид оператора:
for <параметр цикла> := <начальное значение> to
<конечное значение> do <оператор>;
Здесь <параметр цикла>  переменная целого или порядкового типа;
<оператор>  любой оператор, в том числе составной, т. е. группа операторов,
заключенных в "операторные скобки" begin .. end. Начальное и конечное
значения могут быть вычисляемыми выражениями.
При выполнении оператора for .. do переменной  параметру цикла 
присваивается указанное начальное значение, затем проверяется условие, не превосходит ли параметр цикла указанное конечное значение. Если условие не выполняется, оператор for .. do завершает свою работу. В противном случае
выполняются указанный оператор, после чего значение параметра цикла увеличивается на единицу, и цикл повторяется. Если начальное значение больше конечного, цикл не выполняется ни разу.
Возможна другая форма оператора for .. do, когда при каждом исполнении цикла параметр цикла уменьшается на единицу:
for <параметр цикла> := <начальное значение> downto
24
<конечное значение> do <оператор>;
Теперь начальное значение должно быть больше конечного или равно ему,
иначе цикл выполняться не будет.
Чтобы проиллюстрировать использование операторов цикла, рассмотрим
следующую задачу: нужно вычислить выражение
3 5 7
 2n  1
2 4 6
В числителе имеется n слагаемых вида
2n
.
2k  1 , причем k пробегает значение от 1
до n. В знаменателе имеется n слагаемых вида 2k , k также пробегает значение от
1 до n. Выражение можно переписать следующим образом:
n
3 5 7
 2n  1
2 4 6
2n


2k  1
k 1
.
n

2k
k 1
Для вычисления этого выражения можно организовать цикл, в качестве параметра которого выберем переменную k, она будет изменяться от начального
значения 1 до конечного значения n. Внутри цикла последовательно вычислим
числитель и знаменатель дроби, для чего нам понадобятся еще две переменные,
скажем, p (числитель) и q (знаменатель). До входа в цикл присвоим этим переменным начальные (нулевые) значения. Вообще говоря, при запуске программы в
системе программирования Pascal значения всех переменных зануляются (происходит инициализация), так что, казалось бы, присваивание нулевых значений
можно было бы опустить, но с точки зрения логики программирования значения
всех переменных, используемых внутри цикла, должны быть определены перед
входом в цикл, ведь эти значения могут быть ненулевыми, или эти переменные
могли быть использованы ранее в программе и получить другие (ненулевые) значения.
25
Внутри цикла будем последовательно прибавлять к значениям переменных
p и q выражения
2k  1 и
2k , соответственно. После выхода из цикла найдем
окончательный результат как отношение p и q.
Внимание! Перед запуском программы, которая содержит циклы, настоятельно рекомендуется ее сохранить! Если в программе есть ошибки, она может
"зациклиться" (выполнение цикла никогда не прекратится), и выполнение программы придется завершить средствами Windows, при этом программа не будет
сохранен в памяти компьютера, и ее придется набирать заново.
Program Cycles_1;
var
n,k:integer;
p,q,r:real;
begin
writeln('Программа находит значение выражения.');
write('Задайте целое число n:
');
readln(n);
p:=0;
q:=0;
for k:=1 to n
do begin
p:=p+sqrt(2*k+1);
q:=q+sqrt(2*k)
end;
r:=p/q;
writeln('Значение выражения равно ',r:7:4);
end.
Ту же самую программу можно написать, используя вторую форму цикла
(for .. do .. downto):
26
Program Cycles_2;
var
n,k:integer;
p,q,r:real;
begin
writeln('Программа находит значение выражения.');
write('Задайте целое число n:
');
readln(n);
p:=0;
q:=0;
for k:=n downto 1
do begin
p:=p+sqrt(2*k+1);
q:=q+sqrt(2*k)
end;
r:=p/q;
writeln('Значение выражения равно ',r:7:4);
end.
4.2. Оператор цикла while .. do. Общий вид оператора:
while <условие> do <оператор>;
Указанный здесь оператор (в том числе составной) циклически выполняется, пока справедливо указанное условие. Условие проверяется до выполнения
оператора. Внутри цикла необходимо предусмотреть оператор, изменяющий значение переменной цикла, так как, в отличие от цикла for .. do, в данном случае параметр цикла не меняется автоматически. Шаг изменения параметра цикла
не обязательно равен 1. До входа в цикл переменной цикла необходимо присвоить
начальное значение.
27
Приведем вариант рассмотренной выше программы с использованием оператора цикла while .. do:
Program Cycles_3;
var
n,k:integer;
p,q,r:real;
begin
writeln('Программа находит значение выражения.');
write('Задайте целое число n:
');
readln(n);
p:=0;
q:=0;
k:=1;
while k<=n
do begin
p:=p+sqrt(2*k+1);
q:=q+sqrt(2*k);
k:=k+1
end;
r:=p/q;
writeln('Значение выражения равно ',r:7:4);
end.
4.3. Оператор цикла repeat .. until. Общий вид оператора:
repeat <операторы> until <условие>;
Указанные здесь операторы выполняются, после чего проверяется указанное условие. Операторы повторяются до тех пор, пока не выполнено условие. При
необходимости циклического повторения нескольких операторов, оператор repeat .. until не требует использования составного оператора (т. е. "опера-
28
торные скобки" begin .. end можно не писать). Так же, как и в случае цикла
while .. do, внутри цикла необходимо предусмотреть оператор, изменяющий
значение переменной цикла, а до входа в цикл – присвоить переменной цикла
начальное значение.
Приведем вариант рассмотренной выше программы с использованием оператора цикла repeat .. until:
Program Cycles_3;
var
n,k:integer;
p,q,r:real;
begin
writeln('Программа находит значение выражения.');
write('Задайте целое число n:
');
readln(n);
p:=0;
q:=0;
k:=1;
repeat
p:=p+sqrt(2*k+1);
q:=q+sqrt(2*k);
k:=k+1
until k>n;
r:=p/q;
writeln('Значение выражения равно ',r:7:4);
end.
4.4. Задания по теме 4: Операторы циклов.
В следующих заданиях n  заданное натуральное число, x  заданное действительное число. Написать три различных варианта программы, используя, соот-
29
ветственно, операторы циклов for .. do, while .. do, repeat .. until. В программе необходимо вычислить:
1 
1  
1 

1) 1  2 1  2   1  2  ;
2  
n 
 1 
2)
1
1
1
;


sin 1 sin 1  sin 2
sin 1    sin n 
3)
2  2  2 ;


n корней
4)
5)
cos1 cos1  cos2
cos1    cosn 
;

 
sin 1 sin 1  sin 2
sin 1    sin n 
3  6    3n  1  3n ;
6) xx  1 x  n  1 ;
7)
1
1
1
;


x xx  1
xx  1 x  n 
8)
1 1
1
1
 2  4  n ;
x x
x
x2

9) x x  n  x  2n  x  n
10) sin x   sin
2
2
;
x     sin n x  .
5. Целочисленные типы данных
5.1. Типы данных и диапазон значений. В языке Pascal имеется 5 целочисленных типов данных. В зависимости от типа переменная может принимать
тот или иной диапазон значений.
byte
байт длина 8 бит (без знака), диапазон значений 
0 .. +255;
shortint
короткое целое длина 8 бит (1 бит  знак числа + 7 бит 
30
двоичные цифры), диапазон значений  128 .. +127;
word
слово длина 16 бит (без знака), диапазон значений 
0 .. +65 535;
integer
целое длина 16 бит (1 бит  знак числа + 15 бит  двоичные
цифры), диапазон значений  32 768 .. +32 767;
longint
длинное целое  длина 16 бит (1 бит  знак числа + 31 бит 
двоичные
цифры),
диапазон
значений

2 147 483 648 .. +2 147 483 647.
5.2. Ошибки, связанные с неправильным выбором типа данных. В зависимости от того, какой тип данных имеет переменная, ей будет отведена соответствующая область памяти при работе программы. Например, если известно, что
целая положительная переменная при работе программы будет принимать значения, не превосходящие 255, нет смысла описывать эту переменную, как имеющею
тип integer, более правильно использовать тип byte.
Ошибки такого рода, хотя и влекут за собой нерациональное распределение
памяти при работе программы, не должны приводить к неправильным результатам вычислений. Более опасны ситуации, когда значение переменной может выйти за пределы допустимого диапазона значений указанного типа. Например, рассмотрим следующий фрагмент программы:
var
b:integer;
begin
b:=1000;
(* Это значение не превосходит 32767 *)
b:=50*b;
(* b=50000, что больше 32767 *)
writeln('b=',b:5)
end.
В результате получим неправильное значение b=–15536. Для того, чтобы
объяснить такой результат, нужно вспомнить, что компьютер работает с числами
31
в двоичном представлении. Число 50000 в двоичной системе счисления есть 1100
0011 0101 0000. Поскольку это число типа integer, первый бит  1  указывает
на знак числа, это число воспринимается как отрицательное. Отрицательные числа записываются в так называемом дополнительном двоичном коде, в котором
1100 0011 0101 0000 соответствует числу 15536.
Иногда ошибки, вызванные тем, что значение числа превосходит допустимый диапазон, приводят к прерыванию работы программы и сообщению о переполнении, например, в случае вычисления факториала числа n (факториал числа –
произведение всех целых чисел от 1 до n), если соответствующая переменная не
описана как longint.
5.3. Стандартные функции, применимые к целочисленным типам данных. К данным целых типов применимы все арифметические операции, в частности, целочисленное деление div, получение остатка от деления mod, а также
стандартные функции:
abs(i)
вычисляет модуль i, i  выражение любого целого типа;
chr(i)
возвращает символ, соответствующий коду i, i  выражение
типа byte (имеет значение от 0 до 255), результат имеет тип
char;
dec(i)
уменьшает значение переменной i на 1, i  переменная любого
целого типа;
dec(i,j)
уменьшает значение переменной i на целое число j, i  переменная любого целого типа;
inc(i)
увеличивает значение переменной i на 1, i  переменная любого
целого типа;
inc(i,j)
увеличивает значение переменной i на целое число j, i  переменная любого целого типа;
hi(i)
возвращает старший байт аргумента, i  выражение типа in-
32
teger или word, результат имеет тип byte;
lo(i)
возвращает младший байт аргумента, i  выражение типа integer или word, результат имеет тип byte;
odd(i)
принимает значение true (типа boolean), если i  нечетное
число, и false  в противном случае;
pred(i)
возвращает предшествующее значение (i-1), i  выражение любого целого типа;
random(i)
возвращает
псевдослучайное
число
из
диапазона
0 .. (i-1), i  выражение типа byte;
sqr(i)
возводит в квадрат выражение i любого целого типа;
swap(i)
меняет местами байты в значении выражения i, i  выражение
типа integer или word;
succ(i)
возвращает следующее значение (i+1), i  выражение любого
целого типа.
5.4. Пример: вычисление суммы цифр числа. Как пример работы с данными целого типа, приведем короткую программу, которая вычисляет сумму чисел целого числа n. Чтобы программа могла работать с числами, состоящими из 1
 10 цифр, используется тип longint. Сумма цифр числа накапливается в переменной s. Она наверняка не превосходит 255, поэтому используется тип byte.
При нахождении суммы чисел используются операции целочисленного деления
div и получения остатка от целочисленного деления mod (см. раздел 2). Нахождение остатка от деления целого числа на 10 с помощью операции mod позволяет
определить последнюю цифру числа, например,
1234 mod 10 = 4.
Эта последняя цифра добавляется к сумме s. Целочисленное деление числа на 10 с
помощью операции div позволяет отбросить последнюю цифру числа, например,
1234 div 10 = 123,
33
после чего цикл повторяется, пока вспомогательная переменная i не станет равной
нулю.
Program Integer_types;
var
n,i:longint;
s:byte;
begin
write('Введите любое целое число, которое ');
writeln('по модулю не превосходит 2 147 483 647');
readln(n);
i:=n;
s:=0;
while i<>0
do begin
s:=s+abs(i mod 10);
i:=i div 10
end;
writeln('Сумма цифр ', n:9, ' равна ', s:3)
end.
5.5. Задания по теме 5: Целочисленные типы данных.
В следующих заданиях i,
k
 заданные натуральные числа в диапазоне
0 .. 50 000; l  заданное натуральное число в диапазоне 0 .. 1 000 000 000; m, n 
натуральные числа в диапазоне 1000 .. 9999. При описании переменных i, k, l, m, n
выбрать один из целочисленных типов данных (byte, shortint, word, integer, longint), соответствующий заданному диапазону значений. Учесть, что
простым называется целое число, которое делится только на себя и на единицу;
34
совершенным называется целое число, равное сумме своих делителей (при
этом оно само не включается в число делителей). Например, 28 = 1+2+4+7+14.
1) Написать программу, которая находит все простые числа на интервале от
i до k.
2) Написать программу, которая находит все совершенные числа на интервале от i до k.
3) Написать программу, которая находит все числа на интервале от i до k,
которые делятся на 9.
4) Написать программу, которая проверяет, является ли сумма цифр натурального числа l простым числом.
5) Написать программу, которая проверяет, является ли произведение цифр
натурального числа l простым числом.
6) Написать программу, которая находит все числа на интервале от m до n,
все цифры которых различны.
7) Написать программу, которая находит все числа на интервале от m до n,
которые содержат три одинаковые цифры.
8) Написать программу, которая находит все числа на интервале от m до n,
которые содержат две одинаковые цифры.
9) Написать программу, которая находит все числа на интервале от m до n,
которые являются перевертышами. Перевертышами называются такие четырехзначные числа, у которых две первые цифры совпадают с двумя последними в обратном порядке, например, 2222, 6116, 8558.
10) Написать программу, которая находит все числа на интервале от m до
n, которые делятся на 7.
35
6. Вещественные типы данных
6.1. Типы данных и диапазон значений. В языке Pascal имеется 5 действительных типов данных.
single
длина 4 байт, 7 .. 8 значащих цифр, диапазон значений 
1E45 .. 1E+38;
real
длина 6 байт, 11 .. 12 значащих цифр, диапазон значений 
1E39 .. 1E+38;
double
длина 8 байт, 15 .. 16 значащих цифр, диапазон значений 
1E324 .. 1E+308;
extended
длина 10 байт, 19 .. 20 значащих цифр, диапазон значений 
1E4951 .. 1E+4932;
comp
длина 8 байт, 19 .. 20 значащих цифр, диапазон значений 
1E(2*1063 + 1) .. 1E(2*1063  1).
Возможность использования типов single, double, extended и comp
требует наличия арифметического сопроцессора. Для обращения к арифметическому сопроцессору служит опция 8087/80287 (меню OPTIONS  COMPILER 
NUMERIC PROCESSING  8087/80287). При активной опции 8087/80287 (отмечается крестиком X) компилятор будет обращаться к арифметическому сопроцессору, и в программе можно использовать типы single, double, extended,
comp. При неактивной опции 8087/80287 разрешается использовать в программе
только тип real.
Если компьютер не имеет сопроцессора, то его работу можно эмулировать
(воспроизводить) с помощью специальных подпрограмм. Для подключения этих
подпрограмм имеется опция EMULATION (меню OPTIONS  COMPILER 
NUMERIC PROCESSING  EMULATION). Когда опция EMULATION активна, программа становится независимой от наличия сопроцессора. Если сопроцессор имеется, будут использоваться все его возможности; если сопроцессора нет, его рабо-
36
та будет воспроизводиться с помощью подпрограмм, и все вещественные типы
данных можно использовать. Однако подключение дополнительных подпрограмм
увеличивает объем программы. Если опция 8087/80287 неактивна, опция
EMULATION игнорируется.
С другой стороны, в текст самой программы можно включить так называемые директивы компилятора, которые могут включать ту или иную опцию или
отменять ее действие.
{$N+}
директива использовать числовой сопроцессор (включает опцию 8087/80287);
{$N-}
директива не использовать числовой сопроцессор (отключает
опцию 8087/80287);
{$E+}
директива включить режим эмуляции работы сопроцессора
(включает опцию EMULATION);
{$E-}
директива отключить режим эмуляции работы сопроцессора
(отключает опцию EMULATION).
6.2. Пример вычислений с заданной точностью. Рассмотрим небольшую
программу, в которой вычисляется значение функции sin x  с заданной точностью  с помощью бесконечного ряда
x3 x5 x 7
sin  x   x  


3! 5! 7!
x 2 k 1
   1
.
 2k  1!
k 0

k
Будем считать, что требуемая точность достигнута, если вычислена сумма
нескольких первых слагаемых, и очередное слагаемое оказалось по модулю
меньше, чем . При этом условии (очередное слагаемое оказалось по модулю
меньше ) дальнейшие вычисления прекращаются. Если вычислено n первых слагаемых ряда, истинная погрешность вычислений есть разность между истинным
значением функции и суммой n первых слагаемых:
n 1
  sin  x     1
k 0
k

x 2 k 1
x 2 k 1
k
   1
.
 2k  1! k n
 2k  1!
37
Величина  определяет погрешность (точность) вычислений лишь приближенно. Действительно, условие того, что  n  1 -ый член ряда по модулю меньше
,
x 2 n1
 ,
 1
 2n  1!
n
не гарантирует того, что сумма членов ряда, начиная с  n  1 -го, также будет
меньше . Тем не менее, значение  дает представление о точности вычислений по
порядку величины. Поэтому в качестве значений , как правило, выбираются числа 0.01, 0.001, 10-5, 10-8 и т. п. Например, абсурдно задавать значение =3, так как
всегда sin  x   1 , и требование, чтобы очередной член ряда был меньше 3 по абсолютной величине, не обеспечит даже приблизительной точности вычислений.
В программе на языке Pascal нужно организовать цикл, при каждом исполнении которого очередной член ряда (его значение сохраняется в переменной s)
добавляется к сумме ряда (сумма ряда накапливается в переменной sinus), после
чего вычисляется следующий член ряда, и его абсолютная величина сравнивается
с . Перед входом в цикл выполняются начальные присваивания: s=x (s становится равным первому члену ряда), sinus=0 (сумма ряда первоначально равна 0). Переменная i определяет степень члена ряда и связана с его номером k соотношением i  2k  1. В ходе цикла она каждый раз увеличивается на 2. Очередной член
ряда отличается от предшествующего тем, что меняется его знак, числитель
умножается на x2, а знаменатель – на  i  1 i (чтобы накопить в знаменателе
 2k  1! ).
Чтобы при каждом выполнении цикла не возводить x в квадрат, для
экономии ресурсов компьютера вводится вспомогательная переменная sqrx.
Результат суммирования ряда сравнивается со значением, полученным с
помощью стандартной функции языка Pascal sin x  .
38
Program Real_types;
var
epsilon,x,sqrx,s,sinus:extended;
i:integer;
begin
write('Введите заданную точность: ');
readln(epsilon);
write('Введите аргумент функции:
');
readln(x);
s:=x;
sinus:=0;
i:=1;
sqrx:=sqr(x);
while abs(s)>epsilon
do begin
sinus:=sinus+s;
i:=i+2;
s:=-s*sqrx/((i-1)*i)
end;
write('Значение, вычисленное с помощью ');
writeln('суммирования ряда:
');
writeln(sinus:20:18);
write('Значение, вычисленное с помощью ');
writeln('стандартной функции: ');
writeln(sin(x):20:18)
end.
Приведем некоторые результаты вычислений.
1) Вычисление значения с различной точностью:
Введите заданную точность: 1e-3
39
Введите аргумент функции:
0.1
Значение, вычисленное с помощью суммирования ряда:
0.100000000000000000
Значение, вычисленное с помощью стандартной функции:
0.099833416646828152
Введите заданную точность: 1e-5
Введите аргумент функции:
0.1
Значение, вычисленное с помощью суммирования ряда:
0.099833333333333333
Значение, вычисленное с помощью стандартной функции:
0.099833416646828152
Введите заданную точность: 1e-9
Введите аргумент функции:
0.1
Значение, вычисленное с помощью суммирования ряда:
0.099833416666666667
Значение, вычисленное с помощью стандартной функции:
0.099833416646828152
Введите заданную точность: 1e-12
Введите аргумент функции:
0.1
Значение, вычисленное с помощью суммирования ряда:
0.099833416646825397
Значение, вычисленное с помощью стандартной функции:
0.099833416646828152
40
Очевидно, чем меньшее значение  мы задаем, тем большая точность будет
достигнута – при сравнении с правильным значением, полученном с помощью
стандартной функции sin x  , мы видим, что все большее число цифр совпадает.
2) Вследствие того, что мы суммируем знакопеременный ряд, может происходить нарастание ошибки вычисления при каждом выполнении цикла для больших значениях аргумента. Это иллюстрируется следующими примерами и говорит о том, что наш алгоритм хорошо работает лишь при малых значениях аргумента ( x  1 ). При достаточно больших значениях x программа выдает абсурдные
результаты. Чтобы программа работала при любых значениях x, необходимо ее
модифицировать.
Введите заданную точность: 1e-7
Введите аргумент функции:
1
Значение, вычисленное с помощью суммирования ряда:
0.841471009700176367
Значение, вычисленное с помощью стандартной функции:
0.841470984807896507
Введите заданную точность: 1e-7
Введите аргумент функции:
10
Значение, вычисленное с помощью суммирования ряда:
-0.544021064696450892
Значение, вычисленное с помощью стандартной функции:
-0.544021110889369813
Введите заданную точность: 1e-7
Введите аргумент функции:
50
Значение, вычисленное с помощью суммирования ряда:
13.111823886413041800
41
Значение, вычисленное с помощью стандартной функции:
-0.262374853703928787
Введите заданную точность: 1e-7
Введите аргумент функции:
70
Значение, вычисленное с помощью суммирования ряда:
9860810624.036733900
Значение, вычисленное с помощью стандартной функции:
0.773890681557889097
6.3 Задания по теме 6: Вещественные типы данных.
В следующих заданиях x,   заданные действительные числа ( > 0). Вычислить
бесконечную сумму с точностью . Считать, что требуемая точность достигнута,
если вычислена сумма нескольких первых слагаемых, и очередное слагаемое оказалось по модулю меньше, чем ,  тогда это и все последующие слагаемые можно уже не учитывать. Сравнить результат приближенного вычисления со значениями, полученными с помощью стандартных функций языка Turbo Pascal. Использовать тип данных extended.
x2 x4 x6
1) cos x   1 


 ;
2! 4! 6!
x2 x3
2) e  1  x 

 ;
2! 3!
x
3) arctg x   x 
x3 x5 x7


 ;
3
5
7
x2 x3 x4


 ;
4) ln 1  x   x 
2
3
4
5) ln 2   1 
6)

4
1
1 1 1
   ;
2 3 4
1 1 1
   ;
3 5 7
42
7)
8)
9)
2
6
2
12
2
8
10)
1
1
1
1
22
1
22
1
32



1
32
1
32
1
52



1
42
1
42
1
72
 ;
 ;
 ;
1 1 1 1 1
     .
e 2! 3! 4! 5!
7. Перечисляемый тип, тип-диапазон и оператор case.
7.1. Оператор выбора. Помимо условного оператора if, который, в зависимости от выполнения условия, позволяет выбрать ту или иную ветвь алгоритма,
в языке Pascal имеется также оператор выбора case  оператор, который позволяет выполнить то или иное действие в зависимости от значения специального
параметра, называемого ключом выбора.
case <ключ выбора> of
<значение ключа выбора>: <оператор 1>;
<значение ключа выбора>: <оператор 2>;
...
<значение ключа выбора>: <оператор N>;
else <оператор N+1>
end;
Ключ выбора может принимать значения любого порядкового типа. Данные любого порядкового типа имеют конечное множество возможных значений,
которые можно определенным образом упорядочить. Вместе с оператором case
удобно использовать перечисляемый тип данных, который задается перечислением тех значений, которые может принимать переменная этого типа.
43
Оператор выбора работает следующим образом: сначала вычисляется значение параметра  ключа выбора, затем выполняются операторы, соответствующие вычисленному значению. Если в списке выбора не будет найдена константа,
соответствующая вычисленному значению, будут выполнены операторы, стоящие
за служебным словом else. Ветвь else можно опускать. Если ветвь else опушена, а константа, соответствующая вычисленному значению ключа выбора не
найдена, оператор case не выполнит никаких действий.
7.2. Перечисляемый тип. Язык Pascal позволяет программисту определять
свои собственные типы данных. Перечисляемый тип данных относится к определяемым программистом типам. Такие типы данных должны быть описаны в разделе описаний программы. Описание типов должно предшествовать описанию переменных.
type <имя типа> = (<список значений через запятую>);
Пример: пусть нам необходима переменная, которая должна принимать
значения, соответствующие названиям месяцев. Определим тип Month (месяц) и
переменную m1 этого типа.
type
Month=(January, February, March, April, May, June,
July, August, September, October, November, December);
var
m1: Month;
Здесь каждое значение переменной типа Month задается идентификатором.
Естественно, русские слова в качестве идентификаторов употреблять нельзя!
Альтернативно, переменную перечисляемого типа можно объявлять в программе без предварительного описания самого типа.
var <имя переменной>: (<список принимаемых
значений через запятую>);
Пример:
44
var m2:(January, February, March, April, May, June, July,
August, September, October, November, December);
Перечислимый тип относится к порядковым типам данных. Каждому значению порядкового типа можно сопоставить порядковый номер значения. Первое
значение в списке, определяющем перечисляемый тип, получает порядковый номер 0, следующие значения  1, 2 и т. д. Максимальное число возможных значений  65536.
Ко всем порядковым типам применимы следующие функции:
ord(x)
возвращает порядковый номер значения выражения x;
pred(x)
возвращает предыдущее значение порядкового типа, соответствующее порядковому номеру ord(x)-1;
succ(x)
возвращает следующее значение порядкового типа, соответствующее порядковому номеру ord(x)+1.
К порядковым типам относятся также все целые типы, логический
(boolean) и символьный (char), а также тип-диапазон.
7.3. Тип-диапазон  это подмножество элементов другого порядкового типа, задаваемое своим первым и последним значениями.
type <имя типа> = <минимальное значение> ..
<максимальное значение>;
Пример: определим тип MonthNumber (номер месяца) как интервал целых
значений от 1 до 12.
type
MonthNumber=1..12;
var
n1:MonthNumber;
Альтернативно, переменную типа-диапазона можно объявлять в программе
без предварительного описания самого типа.
var <имя переменной> : <минимальное значение> ..
45
<максимальное значение>;
Пример:
var
n2:1..12;
К переменным типа-диапазона применимы следующие функции:
high(x)
возвращает максимальное значение типа-диапазона, к которому
принадлежит переменная x;
low(x)
возвращает минимальное значение типа-диапазона, к которому
принадлежит переменная x.
Использование перечисляемых типов и типов-диапазонов повышает надежность программы благодаря возможности контролировать множество значений,
которые могут принимать переменные перечисляемых типов. Для контроля возможного выхода значений переменных за границы допустимого диапазона служит опция RANGE CHECKING (меню OPTIONS  COMPILER  RUNTIME
ERRORS  RANGE CHECKING). В активном состоянии она позволяет контролировать выход значений переменных за границы диапазона. Существуют также директивы компилятора, которые позволяют включать (директива {$R+}) и отключать (директива {$R-}) контроль границ диапазона.
Однако, значение переменной перечисляемого типа нельзя ввести с клавиатуры с помощью оператора read или вывести на экран с помощью оператора
write, т. е. такие операторы, как
readln(m1);
write(m2);
недопустимы. Для ввода-вывода данных перечисляемого типа необходимо писать
специальные процедуры (см. ниже).
7.4. Пример использования перечисляемого типа данных и оператора
выбора case. Рассмотрим программу вычисления тригонометрических функций
46
sin  x  , cos  x  , tg  x  , arctg  x  . Пользователь указывает название функции и
значение аргумента, результат вычисления выводится на экран.
Введем перечисляемый тип func: Поскольку любое возможное значение переменной типа func – это идентификатор, эти значения (идентификаторы) не
должны совпадать со стандартными идентификаторами языка Pascal, например,
именами функций. Поэтому мы не можем использовать в качестве значений sin
или cos – в противном случае эти значения "закроют" стандартные функции
sin  x  и cos  x  , и мы не сможем обращаться к этим стандартным функциям в
данной программе. В то же время, принятое в русской литературе написание
функции arctg  x  не совпадает со стандартными функциями языка Pascal
arctan(x), а функция tg  x  вообще отсутствует, поэтому соответствующие
имена могут употребляться без изменений.
type func=(sinus, cosin, tg, arctg);
Первое, что должен сделать пользователь – ввести название функции. Для
этого нам потребуется вспомогательная строковая переменная name. Ее значение
можно ввести с клавиатуры с помощью оператора readln. В зависимости от того, какое значение примет переменная name, можно присвоить соответствующее
значение переменной f1 типа func. Заметим, что name не является переменной порядкового типа (строковая переменная может принимать бесконечное множество
значений) и не может использоваться в качестве ключа выбора в операторе case,
в данном случае приходится четыре раза использовать оператор if.
Эту часть программы, связанную с вводом названия функции, разумно выделить в отдельную процедуру. Хотя в данном учебном пособии мы не рассматриваем подробно использование процедур, нетрудно понять основные правила.
Процедуры включаются в раздел описаний (см. раздел 1). Каждая процедура
начинается со служебного слова Procedure, за которым следует имя процедуры
(выбираемый программистом идентификатор, в данном случае – ReadFunction –
47
чтение функции). Далее в скобках указываются формальные параметры, которые
при вызове процедуры из основной программы будут заменяться фактическими.
Служебное слово var перед именем параметра указывает на то, что этот параметр
изменяется в ходе выполнения процедуры. Если он остается неизменным, служебное слово var опускается. Внутри процедуры могут описываться локальные
переменные (в данном случае это – вспомогательная переменная name), память
для локальных переменных выделяется только на время вызова процедуры, в отличие от глобальных переменных, для которых память выделяется на все время
исполнения программы.
Далее пользователь вводит значение аргумента x, после чего, в зависимости
от значения переменной f1, вычисляется соответствующая функция (здесь используется оператор case), и результат (значение переменной r) выводится на
экран. Эти действия, представляющие вторую логическую часть программы,
можно выделить в следующую процедуру – Calculation – вычисление. Здесь x и r
также выступают в роли локальных переменных. Основная часть программы содержит вызовы двух процедур – ReadFunction и Calculation – с фактическим параметром – глобальной переменной f, которая подставляется на место формального параметра f1. Использование процедур делает структуру программы более ясной и отвечает современным правилам программирования на языке высокого
уровня. Использование в программе перечисляемого типа дает возможность проверить правильность вводимого имени функции, его принадлежность к определенному множеству значений.
Program Case_operator;
type func=(sinus, cosin, tg, arctg);
var
f:func;
Procedure ReadFunction (var f1:func);
var
48
name:string[8];
begin {ReadFunction}
write ('Введите название функции: ');
readln(name);
if name='sin'
then f1:=sinus;
if name='cos'
then f1:=cosin;
if name='tg'
then f1:=tg;
if name='arctg'
then f1:=arctg;
end;
{ReadFunction}
Procedure Calculation (f1:func);
var
x,r:real;
begin {Calculation}
write ('Введите значение аргумента: ');
readln(x);
case f1 of
sinus: r:=sin(x);
cosin: r:=cos(x);
tg:
r:=sin(x)/cos(x);
arctg: r:=arctan(x)
else
writeln('Неверный ввод!')
end;
writeln('Результат вычисления: ',r:7:4)
end;
{Calculation}
begin {Program}
49
ReadFunction(f);
Calculation(f)
end.
{Program}
7.5 Задания по теме 7: Перечисляемые типы данных и оператор case.
В следующих заданиях использовать перечисляемые типы данных и оператор выбора case.
1) Написать программу "калькулятор". Пользователь вводит с клавиатуры
два действительных числа и один из символов "+", "", "*", "/", соответствующий
знаку арифметической операции. Результат выполнения операции выводится на
экран.
2) Заданы названия стран: Австрия, Болгария, Греция, Италия, Норвегия,
Франция и названия их столиц: Афины, Вена, Осло, Париж, Рим, София. Написать программу, которая выводит на экран название страны по заданному названию столицы.
3) Заданы названия стран: Австрия, Бразилия, Греция, Индия, Канада,
Франция и названия частей света: Азия, Америка, Европа. Написать программу,
которая выводит на экран название части света по заданному названию страны.
4) Заданы названия планет Солнечной Системы: Земля, Марс, Юпитер и
названия некоторых спутников этих планет: Луна (спутник Земли), Фобос и Деймос (спутники Марса), Ио, Европа, Ганимед, Каллисто (спутники Юпитера).
Написать программу, которая выводит на экран название планеты по заданному
названию спутника.
5) В таблице приведены названия наиболее ярких звезд некоторых созвездий.
Самая яркая звезда
Созвездие
Альтаир
Орел
Бетельгейзе
Орион
Вега
Лира
50
Денеб
Лебедь
Сириус
Большой Пес
Написать программу, которая выводит на экран название самой яркой звезды по
заданному названию созвездия.
6) В таблице приведено количество известных на сегодняшний день спутников планет солнечной системы.
Планета
Количество спутников
Меркурий
0
Венера
0
Земля
1
Марс
2
Юпитер
16
Сатурн
22
Уран
5
Нептун
2
Плутон
1
Написать программу, которая выводит на экран количество спутников по заданному названию планеты.
7) В таблице приведены английские названия времен года
Зима
winter
Весна
spring
Лето
summer
Осень
autumn
Написать программу "словарь", которая выводит на экран английское название
времени года по заданному русскому названию.
8) В таблице приведены английские названия цифр от 1 до 5.
1
one
51
2
two
3
three
4
four
5
five
Написать программу "словарь", которая выводит на экран английское название
цифры по заданной цифре.
9) В таблице приведены сведения об успеваемости некоторых учеников по
математике.
Алексеев
5
Васильев
3
Ильин
5
Петров
4
Филиппов
4
Написать программу, которая выводит на экран фамилии тех учеников, которые
имеют определенную оценку.
10) Написать программу, которая выводит на экран количество дней в месяце по заданному названию месяца.
8. Файлы
8.1. Общие сведения о работе с файлами. Средства языка Pascal позволяют работать с файлами, что облегчает обработку данных: например, программа
может обращаться к файлам, содержащим необходимые данные, а также записывать в файлы результаты обработки данных. Напомним, что под файлом понимается именованная область памяти компьютера (жесткого диска, дискеты), либо
логическое устройство  потенциальный источник или приемник информации.
Длина файла ограничена только объемом памяти компьютера. Программа может
обращаться к нескольким файлам одновременно.
52
Для обращения к файлу необходимо ввести переменную файлового типа. В
процессе работы программы она будет связана с конкретным файлом или логическим устройством, с которым будет происходить обмен данными (см. ниже). Pascal позволяет работать с файлами трех видов – типизированные, текстовые и нетипизированные (вид файла определяет способ хранения информации в нем).
Необходимо прежде всего описать тип, к которому будет принадлежать
файловая переменная, и саму эту переменную, например,
type RealFile = file of real;
var f:RealFile;
Здесь переменная f типа RealFile может использоваться для работы с типизированными файлами, компонентами которых являются вещественные числа.
8.1.1. Открытие файла. Файлы или логические устройства становятся доступными программе только после выполнения особой процедуры открытия
файла. Исключение составляют ввод данных с клавиатуры и вывод на экран. При
открытии файла ранее объявленная файловая переменная связывается с именем
уже существующего или вновь создаваемого файла. Для этого служит стандартная процедура assign:
assign (<файловая переменная>,
<имя файла или логического устройства>);
Здесь <имя файла>  выражение строкового типа; может содержать прописные и строчные латинские буквы, цифры, а также символы
! @ # $ % ^ & ( ) ' ~ - _
(всего не более 8 символов).
Имя файла начинается с любого из названных символов и может сопровождаться расширением  последовательностью, состоящей не более чем из 3 допустимых символов, отделяющейся точкой от имени файла.
53
Перед именем файла может быть указан также путь к файлу, который может включать в себя имя диска и имя текущего каталога. Максимальная длина
имени файла, включая путь и расширение  79 символов. Пример:
assign(f,'C:\Mydocs\Progr#5.txt');
8.1.2. Стандартные имена логических устройств.
клавиатура или экран дисплея (монитор). Использование этого
con
логического имени позволяет осуществлять чтение данных с клавиатуры и вывод данных на экран.
принтер. При подключении к компьютеру нескольких принтеров
prn
они получают логические имена lpt1, lpt2, lpt3, ... , причем
prn и lpt1 по умолчанию считаются синонимами. Использование этих логических имен позволяет осуществлять вывод данных
непосредственно на принтер.
коммуникационный канал, используемый для связи компьютера с
aux
другими машинами. При наличии нескольких коммуникационных каналов они получают логические имена com1, com2, com3,
... , причем aux и com1 по умолчанию считаются синонимами.
логическое имя "пустого" устройства (может использоваться при
nul
отладке программы).
Перечисленные имена являются зарезервированными, т. е. нельзя, например, обратиться к файлу на жестком или гибком диске с логическим именем prn.
8.1.3. Открытие файла для чтения. После связывания файловой переменной с именем файла с помощью процедуры assign, необходимо его инициировать, указать направление передачи данных  открывается ли файл для чтения
или для записи.
Файл открывается для чтения с помощью стандартной процедуры reset:
reset (<файловая переменная>);
54
Если делается попытка инициировать чтение из несуществующего файла
или логического устройства prn, возникает ошибка ввода-вывода. Для контроля
за ошибками ввода-вывода служит опция I/O CHECKING (меню OPTIONS 
COMPILER  RUNTIME ERRORS  I/O CHECKING). В активном состоянии она
позволяет контролировать правильность операций ввода-вывода. Существуют
также директивы компилятора, которые позволяют включать (директива {$I+})
и отключать (директива {$I-}) контроль правильности операций ввода-вывода.
В случае типизированных файлов к файлу, открытому с помощью процедуры reset, можно обращаться не только для чтения, но и для записи информации
(т. е. использовать процедуры write/writeln). Для текстовых файлов, открытых с помощью процедуры reset, процедуры write/writeln использовать
нельзя.
8.1.4. Открытие файла для записи. Файл открывается для записи с помощью стандартной процедуры rewrite:
rewrite (<файловая переменная>);
Если файл, открытый с помощью процедуры rewrite, уже существовал
ранее (т. е. файловая переменная была связана с именем уже существующего
файла при выполнении процедуры assign), при выполнении процедуры rewrite старый файл с указанным именем уничтожается, и к приему информации
подготавливается новый, пока еще пустой файл, указатель файла устанавливается
в 0.
Для того, чтобы добавить записи в конец уже существующего файла, не
уничтожая его, служит процедура append:
append (<файловая переменная>);
Процедура append применима только к текстовым файлам (т. е. файловая
переменная должна иметь тип text). Процедура append инициирует запись
информации в ранее существовавший текстовой файл, указатель файла устанав-
55
ливается в его конец. Если текстовой файл ранее уже был открыт с помощью процедур reset или rewrite, использование процедуры append приводит к закрытию этого файла и открытию его вновь, но уже для добавления записей.
8.1.5. Стандартные процедуры для работы с файлами любого типа.
close (<файловая переменная>)
закрывает файл, обеспечивая сохранение в файле всех новых записей и регистрацию файла в каталоге. Связь файловой переменной с
именем файла, установленная ранее процедурой assign, сохраняется, поэтому файл можно повторно открыть без дополнительного
использования процедуры assign.
rename (<файловая переменная>, <новое имя>)
процедура переименования файла. Если файл был ранее открыт с
помощью процедур reset, rewrite или append, перед выполнением процедуры rename его необходимо закрыть с помощью
процедуры close.
erase
(<файловая переменная>)
уничтожает файл. Если файл был ранее открыт с помощью процедур reset, rewrite или append, перед выполнением процедуры rename
его необходимо закрыть с помощью процедуры
close.
flush
(<файловая переменная>)
очищает внутренний буфер файла. При выполнении процедуры
flush все записи, временно хранящиеся в буфере (т. е. во вспомогательной памяти, предназначенной для промежуточного хранения
данных), будут записаны на диск. Если файл был инициирован для
чтения процедурой reset, процедура flush игнорируется.
chdir
(<путь>)
56
изменяет текущий каталог, устанавливая путь к новому каталогу.
getdir (<устройство>, <каталог>)
определяет имя текущего каталога. В результате выполнения процедуры getdir получают определенные значения переменная типа word (<устройство>), содержащая номер устройства, и переменная типа string (<каталог>), содержащая путь к текущему
каталогу на указанном устройстве, причем 0 соответствует устройству по умолчанию, 1  диску a:, 2  диску b: и т. д.
mkdir
(<имя каталога, включая путь>)
создает каталог с указанным именем. Имя не может совпадать с
именем уже существующего каталога.
rmdir
(<имя каталога, включая путь>)
удаляет каталог с указанным именем. Удаляемый каталог должен
быть пустым, т. е. не содержать файлов или каталогов низшего
уровня.
8.1.6. Стандартные функции для работы с файлами любого типа.
eof (<файловая переменная>)
логическая функция типа boolean. Принимает значение true,
если указатель файла находится в конце файла. В этом случае при
записи данные будут добавляться в конец файла, при чтении это
означает, что файл исчерпан.
ioresult функция типа word. Ее значением является код последней операции ввода-вывода. В случае успешного завершения последней операции ввода-вывода принимает значение 0, в противном случае 
код ошибки ввода-вывода. Функция ioresult становится доступной только при отключении контроля за ошибками вводавывода с помощью директивы компилятора {$I+}.
57
8.2. Типизированные файлы содержат компоненты указанного типа,
например, действительные числа. Описание:
type <имя типа> = file of <тип компонентов>;
Примеры:
type
RealExtFile = file of extended;
IntFile
= file of byte;
Text80
= file of string[80];
var
f1: RealExtFile;
f2: IntFile;
f3: Text80;
Переменная f1 может использоваться для работы с файлами, компонентами которых являются действительные числа в расширенном формате, переменная f2 может использоваться для работы с файлами, компонентами которых являются целые числа от 0 до 255, переменная f3 – для работы с файлами, компоненты которых – строки длиной не более 80 символов.
Альтернативно, переменную файлового типа можно объявлять в программе
без предварительного описания самого типа:
var <имя переменной>: file of <тип компонентов>;
Примеры:
var
f4: file of word;
f5: file of char;
8.2.1. Стандартные процедуры для работы с типизированными файлами.
read (<файловая переменная>, <список переменных>)
чтение очередных компонентов файла. При выполнении проце-
58
дуры read переменные, указанные в списке, последовательно
принимают значения очередных компонентов типизированного
файла. При этом тип переменных из указанного списка должен
совпадать с типом компонентов файла. Файловая переменная
должна соответствовать типизированному файлу (т. е. иметь тип
file of ... ) и быть связана с именем конкретного файла с помощью процедуры assign. Файл должен быть открыт для чтения с помощью процедуры reset. После каждого чтения указатель файла сдвигается к следующему компоненту файла. Если
файл исчерпан, обращение к процедуре read вызовет ошибку
ввода-вывода.
write (<файловая переменная>, <список переменных>)
запись очередных компонентов файла. При выполнении процедуры write в файл записываются значения переменных, указанных в списке. При этом тип переменных из указанного списка
должен совпадать с типом компонентов файла. Файловая переменная должна соответствовать типизированному файлу (т. е.
иметь тип file of ... ) и быть связана с именем конкретного
файла с помощью процедуры assign. Файл должен быть открыт
с помощью процедуры reset или rewrite. После каждой записи указатель файла сдвигается к следующему компоненту файла.
seek (<файловая переменная>, <номер компонента>)
смещает указатель файла к компоненту с заданным номером. Номер компонента задается выражением типа longint. Первый
компонент файла имеет номер 0.
59
8.2.2. Стандартные функции для работы с типизированными файлами:
filesize (<файловая переменная>)
функция типа longint, ее значением является количество компонентов файла.
filepos
(<файловая переменная>)
функция типа longint, ее значением является порядковый номер компонента файла, который будет обрабатываться следующей операцией ввода-вывода. Первый компонент файла имеет
номер 0.
8.2.3. Пример работы с типизированным файлом. Ниже мы рассмотрим
пример программы, которая находит сумму действительных чисел, содержащихся
в файле. Программа состоит из двух частей (процедур). В первой процедуре
(WriteToFile) запрашивается имя файла, после чего файловая переменная freal
связывается с этим именем с помощью процедуры assign. Затем файл открывается для записи с помощью процедуры rewrite. В файл записываются действительные числа, вводимые с клавиатуры. Для этого используется специальная
форма цикла – while not eof. Напомним, что eof – это логическая функция,
которая принимает значение true, если достигнут конец файла. Если функция
употребляется без аргумента (файловой переменной), как в данном случае, по
умолчанию предполагается ввод данных с клавиатуры. Для проверки условия
цикла работа программы приостанавливается, и ожидается ввод данных с клавиатуры, поэтому первым оператором, выполняемым внутри цикла, должен быть
оператор read/readln. Если введена специальная комбинация клавиш Ctrl-Z,
сопровождаемая нажатием клавиши Enter, функция eof получает значение
true – комбинация Ctrl-Z указывает на окончание ввода данных (достигнут
"конец файла"). После окончания ввода данных файл закрывается с помощью
процедуры close.
60
Во второй процедуре (ReadFile – чтение файла) файл открывается для чтения с помощью процедуры reset, и вновь используется конструкция while
not eof(freal), на этот раз в качестве аргумента функции eof используется
файловая переменная freal. Цикл будет выполняться до тех пор, пока не будет достигнут конец файла, связанного с переменной freal. В цикле последовательно
считываются компоненты файла – вещественные числа, выводятся на экран и вычисляется их сумма.
Program Files_1;
type RealFile = file of real;
var freal:RealFile;
Procedure WriteToFile;
var
x:real;
name:string[8];
begin {WriteToFile}
write('Введите имя файла (не более 8 символов): ');
readln(name);
assign(freal,name);
rewrite(freal)
write('Последовательно вводите ');
writeln('действительные числа.');
write('Ввод каждого числа завершайте ');
writeln('нажатием клавиши Enter.');
write('Для окончания ввода данных ');
writeln('нажмите клавиши Ctrl-Z и Enter.');
while not eof
do begin
readln(x);
61
write(freal,x)
end;
close(freal);
writeln
end;
{WriteToFile}
Procedure ReadFile;
var x,sum:real;
begin {ReadFile}
sum:=0;
reset(freal);
write('Файл',name:9,' содержит следующие числа:');
while not eof(freal)
do begin
read(freal,x);
writeln(x:10:5);
sum:=sum+x
end;
writeln('Сумма чисел в файле: ', sum:10:5);
writeln
end;
{ReadFile}
begin {Program}
write('Определение суммы чисел, содержащихся ');
writeln('в типизированном файле');
writeln;
WriteToFile;
ReadFile;
end.
{Program}
8.3. Текстовые файлы в языке Pascal рассматривается как совокупность
строк переменной длины. Они определяются типом text. Доступ к каждой стро-
62
ке осуществляется последовательно, начиная с первой. При создании текстового
файла в конце каждой строки помещается специальный признак конца строки. В
конце файла помещается специальный признак конца файла. Описание:
type <имя типа> = text;
Примеры:
type TextFile = text;
var t1: TextFile;
Альтернативно, файловую переменную можно объявлять в программе без
предварительного описания типа text:
var <имя переменной>: text;
8.3.1. Стандартные процедуры для работы с текстовыми файлами.
read (<файловая переменная>, <список переменных>)
чтение данных из файла. Файловая переменная имеет тип text и
должна быть связана с именем конкретного файла с помощью процедуры assign. В отличие от типизированных файлов переменные, указанные в списке, могут иметь любой целый или вещественный тип, а также char или string.
В зависимости от типа переменных процедура чтения данных выполняется поразному. При чтении целых или вещественных данных в текстовом файле выделяется последовательность (подстрока) символов, которая должна соответствовать символьному представлению числовой константы, например,
65535
35
4.0
–78.128
–0.27408E–07
Пробелы, которые могут находиться в начале строки (так называемые ведущие
пробелы), при этом игнорируются. Признаком конца подстроки (после значащих
63
символов) является пробел, символ конца строки или конца файла. Если символы
подстроки не соответствуют принятому формату представления чисел (например,
подстрока представляет собой запись действительного числа, в то время как ожидается чтение целого числа), возникает ошибка ввода-вывода. Если достигнут конец файла, а значащих символов не обнаружено, переменная получает значение 0.
При чтении символьных данных переменная типа char получает значение, равное очередному считанному символу из файла.
При чтении строковых данных переменная типа string получает значение, соответствующее последовательности считанных из файла символов, причем
количество считанных символов равно максимальной длине строки, если только
один из считанных символов не является признаком конца строки или конца файла.
Если файловая переменная не указана, предполагается, что ввод данных
осуществляется с клавиатуры, т. е. мы имеем дело с уже хорошо знакомой нам
процедурой read.
readln (<файловая переменная>, <список переменных>)
процедура аналогична процедуре read, за исключением того, что
при выполнении процедуры readln считывается целая строка из
файла. При следующем обращении к процедуре readln чтение
данных из файла начинается с начала следующей строки. Использование процедуры readln без параметра <список переменных>
приводит к пропуску строки.
write (<файловая переменная>, <список переменных>)
запись данных в файл. Файловая переменная имеет тип text и
должна быть связана с именем конкретного файла с помощью процедуры assign. В отличие от случая типизированных файлов переменные, указанные в списке, могут иметь любой целый или веще-
64
ственный тип, а также char или string.
Если файловая переменная не указана, предполагается, что вывод данных осуществляется на экран, т. е. мы имеем дело с уже хорошо знакомой нам процедурой write.
Формат представления данных, записываемых в текстовой файл, может
быть определен программистом аналогично тому, как это можно сделать при выводе данных на экран. Например, при выводе десятичных чисел можно указать
число цифр после запятой и полное число десятичных знаков, включая знак числа
и десятичную точку.
writeln (<файловая переменная>, <список переменных>)
процедура аналогична процедуре write, за исключением того, что
при выполнении процедуры writeln в файл записывается целая
строка, в конец строки помещается признак конца строки. Использование процедуры writeln без параметра <список переменных> приводит к записи в файл пустой строки (содержащей только
признак конца строки).
8.3.2. Стандартные функции для работы с текстовыми файлами
eoln (<файловая переменная>)
логическая функция типа boolean. Принимает значение true, если
достигнут конец строки.
seekeoln (<файловая переменная>)
логическая функция типа boolean. Принимает значение true, если
в строке нет более значащих символов (пробелы и символы табуляции игнорируются).
seekeof (<файловая переменная>)
логическая функция типа boolean. Принимает значение true, если
в файле нет более значащих символов (пробелы, символы табуляции
и признаки концов строк игнорируются).
65
8.3.3. Пример работы с текстовым файлом. Рассмотрим вновь программу, которая находит сумму действительных чисел, содержащихся в файле, но теперь будем использовать текстовый файл. Структура программы остается той же
самой, отличия же заключаются в том, что, во-первых, используется файловая переменная типа text, во-вторых, данные – действительные числа – записываются
в файл с помощью оператора writeln, при этом каждое число располагается в
текстовом файле на отдельной строке. Запись в типизированный файл, в отличие
от текстового, с помощью оператора writeln невозможна, и необходимо использовать оператор write. Для записи в текстовый файл можно использовать
как оператор writeln, так и оператор write, в последнем случае данные в
строке будут разделяться пробелами. Текстовые файлы, созданные в результате
работы программы, можно просмотреть с помощью стандартных приложений
Windows, например, Блокнот или WordPad. Данные в типизированном файле хранятся во внутреннем представлении; при попытке просмотреть такой файл с помощью текстового редактора мы увидим только непонятные символы.
Program Files_2;
var ftext:text;
Procedure WriteToFile;
var
x:real;
name:string[8];
begin {WriteToFile}
write('Введите имя файла (не более 8 символов): ');
readln(name);
assign(ftext,name);
rewrite(ftext)
write('Последовательно вводите ');
writeln('действительные числа.');
66
write('Ввод каждого числа завершайте ');
writeln('нажатием клавиши Enter.');
write('Для окончания ввода данных ');
writeln('нажмите клавиши Ctrl-Z и Enter.');
while not eof
do begin
readln(x);
writeln(ftext,x)
end;
close(ftext);
writeln
end;
{WriteToFile}
Procedure ReadFile;
var x,sum:real;
begin {ReadFile}
sum:=0;
reset(ftext);
write('Файл',name:9,' содержит следующие числа:');
while not eof(ftext)
do begin
readln(ftext,x);
writeln(x:10:5);
sum:=sum+x
end;
writeln('Сумма чисел в файле: ', sum:10:5);
writeln
end;
{ReadFile}
begin {Program}
write('Определение суммы чисел, содержащихся ');
67
writeln('в типизированном файле');
writeln;
WriteToFile;
ReadFile;
end.
{Program}
8.4. Нетипизированные файлы отличаются тем, что для них не указан тип
компонентов. Это делает их совместимыми с любыми другими файлами. При работе с нетипизированными файлами необходимо указывать длину записи нетипизированного файла. Они определяются типом file. Описание:
type <имя типа> = file;
Примеры:
type FileType = file;
var t2:FileType;
Альтернативно, файловую переменную можно объявлять в программе без
предварительного описания типа file:
var <имя переменной>: file;
Для записи информации в нетипизированный файл и чтения данных из
файла используются специальные процедуры blockread и blockwrite (аналоги процедур read и write).
8.5 Задания по теме 8: Работа с файлами.
В следующих заданиях следует написать два различных варианта программы, в
первом случае  с использованием типизированного файла, во втором случае  с
использованием текстового файла.
1) Написать программу, которая создает файл, содержащий действительные
числа, и находит сумму наибольшего и наименьшего из чисел, содержащихся в
файле.
2) Написать программу, которая создает файл, содержащий целые числа, и
находит произведение всех чисел, содержащихся в файле.
68
3) Написать программу, которая создает файл, содержащий действительные
числа, и находит сумму квадратов чисел, содержащихся в файле.
4) Написать программу, которая создает файл, содержащий целые числа, и
находит модуль суммы и квадрат произведения чисел, содержащихся в файле.
5) Написать программу, которая создает файл, содержащий действительные
числа, и находит последнее из чисел, содержащихся в файле.
6) Написать программу, которая создает файл, содержащий целые числа, и
находит количество четных чисел, содержащихся в файле.
7) Написать программу, которая создает файл, содержащий действительные
числа, и находит наименьшее из чисел, содержащихся в файле.
8) Написать программу, которая создает файл, содержащий целые числа, и
находит сумму нечетных чисел, содержащихся в файле.
9) Написать программу, которая создает файл, содержащий действительные
числа, и находит разность первого и последнего из чисел, содержащихся в файле.
10) Написать программу, которая создает файл, содержащий целые числа, и
находит произведение четных чисел, содержащихся в файле.
9. Строки (тип данных string)
9.1. Описание строкового типа данных. При работе с текстовыми файлами удобно использовать специальный строковый тип данных – стандартный
тип string. По этой причине рассмотрение этого типа данных включено в
настоящее учебное пособие. Его описание:
type <имя типа> = string[<максимальное число
символов в строке>];
<максимальное число символов в строке> должно задаваться любой
константой порядкового типа, значение которой не превосходит 255. Если число
69
символов в строке не указано, оно принимается максимально возможным, равным
255.
Примеры:
type TextString=string[80];
WordString=string[10];
Здесь тип TextString представляет собой строку текста – последовательность
из 80 символов, тип WordString – слово – последовательность из не более, чем
10 символов
Альтернативно, переменную типа string можно объявлять в программе
без предварительного описания самого типа:
var <имя переменной>: string[<максимальное число
символов в строке>];
Пример:
var st,st1:string[20];
Тип string[n] (строка) в языке Pascal во многом аналогичен типу array
[0..n] of char, т. е. одномерному массиву символов (n  максимальное количество символов в строке, некоторая константа). В отличие от обычного массива, количество элементов которого фиксировано, количество символов в строке
может меняться от 0 до n. К каждому символу в строке можно обращаться так
же, как к элементу массива, например,
if st[5] = 'a' then ...
Первый байт в строке имеет индекс 0 и содержит текущую длину строки. При выполнении над строкой различных операций длина строки может изменяться.
Если при обращении к некоторой процедуре или функции необходимо использовать переменную типа string, этот тип, должен быть описан заранее.
Иными словами, объявление процедуры
Procedure p1(s:string[10]);
является недопустимым. Правильным в данном случае будет
70
Procedure p1(s:WordString);
(см. выше описание типа WordString).
9.2. Операции над строками в языке Pascal.
сцепление двух строк.
+
Например,
st:='a'+'b';
(Строка st будет содержать "ab".)
st:=st+'c';
(Строка st будет содержать "abc".)
Операции сравнения:
=
равно;
<>
не равно;
<
меньше;
>
больше;
<=
меньше или равно;
>=
больше или равно
При сравнении двух строк символы обеих строк сравниваются попарно друг
с другом таким образом, что первый символ первой строки сравнивается с первым
символом второй строки, второй символ первой строки сравнивается со вторым
символом второй строки и т. д. Если одна строка короче другой, недостающие
символы заменяются нулями. Фактически сравниваются коды символов, поэтому
при сравнении строк нужно иметь в виду таблицу кодов символов. Например,
цифры '0'..'9' имеют коды 048..057, большие буквы латинского алфавита 'A'..'Z'
имеют коды 065..090, поэтому
'A'<'D';
'AB'<'ABC';
'A'>'1';
'ABD'>'ABC'.
71
9.3. Стандартные процедуры для работы со строками.
delete (<строка>, <номер первого символа>,
<число символов>)
удаление из указанной строки заданного числа символов, начиная с
символа с указанным номером.
Например,
st:='12345';
(Строка st содержит 12345.)
delete(st,2,3);
(Строка st будет содержать 15.)
insert (<подстрока>, <строка>, <номер первого символа>)
вставка указанной подстроки в заданную строку, начиная с символа
с указанным номером.
Например,
st1:='345';
(Строка st1 содержит 345.)
insert('-',st1,2);
(Строка st1 содержит 3-45.)
str (<вещественное или целое число>:
<общее количество символов>:
<число символов после запятой>, <строка>)
преобразование вещественного или целого числа в строку символов,
подобно тому, как это делает стандартная процедура writeln.
Формат представления чисел, может быть определен программистом аналогично
тому, как это можно сделать при выводе данных на экран. Например, при выводе
вещественных чисел можно указать число цифр после запятой и полное число десятичных знаков, включая знак числа и десятичную точку.
st:='12345';
72
(Строка st содержит 12345.)
str(pi:5:2,st);
(Сейчас строка st содержит 3.14.)
val (<строка>,
<вещественная или целая переменная>,
<код выполнения преобразования>)
преобразование строки символов в вещественное или целое число,
которое становится значением указанной вещественной или целой
переменной. Если преобразование прошло успешно, код выполнения преобразования содержит 0, в противном случае он содержит
номер позиции в указанной строке, где обнаружен символ, не соответствующий формату числа. В последнем случае значение указанной переменной не изменяется. В строке допускаются ведущие пробелы (находящиеся в начале строки), в то время как ведомые пробелы (находящиеся в конце строки) не допускаются.
Например,
val('
3.1415',x,code);
(Переменная x получает значение 3.1415, а параметр code – 0.)
val('3.1415
',x,code);
(Значение переменной x не изменяется, а параметр code получает значение 7 –
номер позиции первого пробела после записи числа 3.1415.)
val('3,1415',x,code);
(Значение переменной x не изменяется, а параметр code получает значение 2 –
номер позиции, в которой вместо точки стоит запятая в записи числа 3.1415.)
9.4. Стандартные функции для работы со строками.
concat (<строка 1>, <строка 2>, ... <строка N>)
функция типа string, ее значением является строка, которая представляет собой сцепление указанных строк.
73
Например,
st:=concat('12','345');
(Строка st содержит 12345.)
copy (<строка>, <номер первого символа>,
<число символов>)
функция типа string, ее значением является строка, получаемая копированием из указанной строки заданного число символов, начиная
с символа с указанным номером.
Например,
st:='12345';
(Строка st содержит 12345.)
st1:=copy(st,2,3);
(Строка st1 содержит 234.)
length (<строка>)
функция типа integer, ее значением является длина строки (число
символов в строке).
Например,
st:='12345';
n:=length(st);
(n–- длина строки st – равна 5.)
pos (<подстрока>, <строка>)
функция типа integer, ее значением является номер символа (позиции), начиная с которого указанная подстрока входит в заданную
строку. Если в строке указанная подстрока не найдена, функция имеет значение 0.
Например,
st:='12345';
n:=pos('2',st);
74
(n – позиция символа “2” в строке st – равна 2.)
upcase (<символ>)
функция типа char, заменяет строчные латинские буквы на заглавные. Ее аргументом должна быть строчная буква латинского алфавита, ее значением является соответствующая заглавная буква. Если в
качестве аргумента функции upcase указан любой другой символ
(в том числе строчная буква русского алфавита), значением функции
является тот же символ без изменения.
9.5. Пример: редактирование текстового файла. В качестве примера рассмотрим программу, которая создает текстовой файл (который в языке Pascal рассматривается как совокупность строк). После создания файла программа предоставляет пользователю возможность редактировать файл  заменять одни последовательности символов на другие, задаваемые пользователем, в частности, заменять целые слова. Предполагается, что файл состоит из строк, каждая из которых
содержит не более 60 символов.
Программа состоит из трех процедур. Первая процедура – CreateFile –
предназначена для создания файла и ввода в него необходимой информации. Имя
файла получает расширение .dat и связывается с файловой переменной f. Файл
открывается для записи с помощью процедуры rewrite. На экран выводятся сообщения для пользователя, каким образом ему следует вводить текст в файл. После этого используется уже знакомая нам по работе с файлами конструкция
while not eof, в цикле с клавиатуры вводится очередная строка и записывается в файл.
Вторая процедура – PrintText – предназначена для вывода на экран содержащегося в файле текста. Файл открывается для чтения с помощью процедуры
reset, затем в цикле while not eof(f) из файла считывается и выводится
на экран очередная строка.
75
Наиболее интересна процедура корректировки текста Replacement – замены
неправильно введенных последовательностей символов. Сначала пользователю
предлагается ввести текст – строку символов, – которую следует заменить. Эта
строка сохраняется в переменной s1. Затем предлагается ввести текст, который
будет помещен на место неправильной последовательности символов. Он будет
сохранен в строковой переменной s2. Предусматривается возможность замены
только целых слов, т. е. последовательностей символов, в начале и в конце сопровождаемых пробелами. На экран выводится соответствующий запрос. Если пользователь ответит на этот вопрос утвердительно, в начало и в конец строк s1, s2
будет добавлено по одному пробелу. На этом заканчивается подготовительная
часть работы.
Далее старый файл переименовывается с помощью процедуры rename.
При этом изменяется его расширение: файл имел расширение .dat, теперь он
будет иметь расширение .bak. После переименования файл открывается для чтения. Затем создается новый файл с тем же именем и расширением .dat: он связывается с новой файловой переменной f1 с помощью процедуры assign и открывается для записи исправленного текста с помощью процедуры rewrite. В
цикле из старого файла считывается очередная строка, и в ней определяется позиция первого символа той подстроки s1, которую нужно заменить. Для этого используется функция pos, которая определяет номер символа, начиная с которого
указанная подстрока входит в очередную строку. Затем организуется новый цикл,
условием окончания работы которого является то, что подстрока не найдена
(функция pos получает значение 0). В случае, если подстрока найдена, она удаляется с помощью процедуры delete, и на ее место вставляется новая подстрока с
помощью процедуры insert, после чего вычисляется новое значение функции
pos. Таким образом, находим все последовательности символов в строке, которые необходимо заменить. Исправленная строка записывается в новый файл с
76
расширением .dat. Старый файл с расширением .bak, который нам больше не
потребуется, закрывается и удаляется с помощью процедуры erase.
Основная программа содержит вызовы процедур CreateFile (создание файла) и PrintText (вывод на экран его содержимого). В программе предусмотрена
возможность редактировать файл столько раз, сколько захочет пользователь (выдается соответствующий запрос пользователю). Если пользователь желает отредактировать текст, вызывается процедура Replacement, а затем исправленный
текст вновь выводится на экран с помощью процедуры PrintText.
Program Strings;
var
f:text;
name:string[8];
a:0..1;
Procedure CreateFile;
var s:string[60];
begin {CreateFile}
write('Введите имя файла (не более 8 символов): ');
readln(name);
writeln;
assign(f,name+'.dat');
rewrite(f);
write('Вводите текст в файл, последовательно ’);
writeln('набирая на клавиатуре строки.');
write('Каждая строка должна содержать ');
writeln('не более 60 символов.');
write('Ввод каждой строки завершайте ');
writeln('нажатием клавиши Enter.');
write('Для окончания ввода текста ');
77
writeln('нажмите клавиши Ctrl-Z и Enter.');
writeln;
while not eof
do begin
readln(s);
writeln(f,s)
end;
writeln;
close(f)
end;
{CreateFile}
Procedure PrintText;
var s: string[60];
begin {PrintText}
assign(f,name+'.dat');
reset(f);
write('Файл ',name,'.dat содержит ');
writeln('следующий текст:');
writeln;
while not eof(f)
do begin
readln(f, s);
writeln(s)
end;
writeln;
close(f)
end;
{PrintText}
Procedure Replacement;
var
f1:text;
78
s,s1,s2:string[60];
i:byte;
a1:0..1;
begin {Replacement}
writeln('Введите последовательность символов,');
write('которую необходимо найти в файле ');
writeln(name, '.dat и заменить:');
readln(s1);
write('Введите новую последовательность символов, ');
writeln('которую необходимо поместить на место ');
writeln('неправильной последовательности:');
readln(s2);
write('Вы хотите, чтобы заменялись ');
writeln('только целые слова');
write('(т. е. указанные Вами последовательности, ');
writeln('сопровождаемые пробелами ');
writeln('в начале и в конце)?
readln(a1);
if a1=1
then begin
s1:=' '+s1+' ';
s2:=' '+s2+' '
end;
rename(f,name+'.bak');
reset(f);
assign(f1, name+'.dat');
rewrite(f1);
while not eof(f)
do begin
79
1 - да, 0 - нет:
');
readln(f,s);
i:=pos(s1,s);
while i<>0
do begin
delete(s,i,length(s1));
insert(s2,s,i);
i:=pos(s1,s)
end;
writeln(f1, s)
end;
close(f);
erase(f);
close(f1)
end; {Replacement}
begin {Program}
CreateFile;
PrintText;
repeat
write('Вы хотите отредактировать ');
write('текст? 1 - да, 0 - нет:
readln(a);
if a=1
then begin
Replacement;
PrintText
end;
until a=0;
writeln
end. {Program}
80
');
9.6 Задания по теме 9: Строки.
В следующих заданиях использовать строковый тип данных (string). Учесть,
что
словами называются группы символов, разделенные пробелами и не содержащие пробелов внутри себя;
в вариантах 6  10 откорректированный текст должен быть записан в новый
файл, в то время как старый файл должен быть уничтожен.
Написать программу, которая создает текстовой файл, и, кроме того,
1) определяет, сколько раз заданный символ содержится в данном файле;
2) определяет, сколько раз заданное слово содержится в данном файле.
3) находит самую длинную строку в файле и выводит ее на экран;
4) определяет, сколько слов, состоящих из пяти букв, содержится в данном
файле;
5) определяет, сколько слов, начинающихся с латинской буквы "a", содержится в данном файле;
6) удаляет из файла все лишние пробелы между словами (оставляет слова
разделенными только одним пробелом);
7) удаляет из файла все ведущие пробелы (т. е. те, которые находятся в
начале строки);
8) заменяет в файле все символы "0" символами "1";
9) заменяет в файле все строчные буквы латинского алфавита прописными;
10) заменяет в файле все прописные буквы латинского алфавита строчными.
81
Литература
1. В. В. Фаронов, Turbo Pascal в подлиннике, “BHV-Санкт-Петербург”, 2004. 
1056 стр.
2. С. А. Немнюгин, Turbo Pascal. Программирование на языке высокого уровня: Учебник для вузов, 2-е издание, “Питер”, 2005.  544 стр.
3. С. А. Немнюгин, Turbo Pascal:Практикум, 2-е издание, “Питер”, 2004. 
272 стр.
4. Т. А. Павловская, Паскаль. Программирование на языке высокого уровня:
Учебник для вузов, “Питер”, 2004.  400 стр.
5. В. И. Грызлов, Т. П. Грызлова, Турбо Паскаль 7.0. Учебный курс, “Питер”,
2004.  416 стр.
6. В. Кораблев, Турбо Паскаль 7.0. Самоучитель, 16-е издание, “Питер”, 2004.
 480 стр.
82
Download