- •Основы программирования на языке Паскаль
- •Часть 1. Основы языка Паскаль 2
- •Часть 2. Элементы профессионального программирования на Паскале 44
- •От автора
- •Часть 1. Основы языка Паскаль
- •1. Алгоритм и программа
- •1.1. Алгоритм
- •1.2. Свойства алгоритма
- •1.3. Формы записи алгоритма
- •1.4. Программа и программное обеспечение
- •1.5. Этапы разработки программы
- •2. Данные в языке Паскаль
- •2.1 Константы
- •2.2 Переменные и типы переменных
- •3. Арифметические выражения
- •4. Линейный вычислительный процесс
- •4.1 Оператор присваивания
- •4.2 Оператор ввода
- •4.3 Оператор вывода
- •4.4 Управление выводом данных
- •4.5 Вывод на печать
- •5. Структура простой программы на Паскале
- •6. Компилятор и оболочка Turbo Pascal
- •7. Разветвляющийся вычислительный процесс и условный оператор
- •7.4. Короткий условный оператор
- •If логическое_выражение then оператор1;
- •7.5. Полный условный оператор
- •If логическое_выражение then оператор1
- •7.7. Вложенные условные операторы
- •7.9. Примеры программ с условным оператором
- •8. Директивы компилятора и обработка ошибок ввода
- •9. Оператор цикла. Циклы с предусловием и постусловием
- •10. Цикл со счетчиком и досрочное завершение циклов
- •11. Типовые алгоритмы табулирования функций, вычисления количества, суммы и произведения
- •11.1 Алгоритм табулирования
- •11.2 Алгоритм организации счетчика
- •11.3 Алгоритмы накопления суммы и произведения
- •12. Типовые алгоритмы поиска максимума и минимума
- •13. Решение учебных задач на циклы
- •14. Одномерные массивы. Описание, ввод, вывод и обработка массивов на Паскале
- •15. Решение типовых задач на массивы
- •Часть 2. Элементы профессионального программирования на Паскале
- •16. Кратные циклы
- •16.1 Двойной цикл и типовые задачи на двойной цикл
- •16.2 Оператор безусловного перехода
- •17. Матрицы и типовые алгоритмы обработки матриц
- •18. Подпрограммы
- •18.1 Процедуры
- •18.2 Функции
- •18.3 Массивы в качестве параметров подпрограммы
- •18.4 Открытые массивы
- •19. Множества и перечислимые типы
- •20. Обработка символьных и строковых данных
- •20.1. Работа с символами
- •20.2 Работа со строками
- •21. Текстовые файлы
- •21.1 Общие операции
- •21.2 Примеры работы с файлами
- •21.3 Работа с параметрами командной строки
- •22. Записи. Бинарные файлы
- •23. Модули. Создание модулей
- •23.1. Назначение и структура модулей
- •23.2. Стандартные модули Паскаля
- •24. Модуль crt и создание простых интерфейсов
- •25. Модуль Graph и создание графики на Паскале
- •Приложение 1. Таблицы ascii-кодов символов для операционных систем dos и Windows
- •Приложение 2. Основные директивы компилятора Паскаля
- •Приложение 3. Основные сообщения об ошибках Паскаля
- •Приложение 4. Дополнительные листинги программ
- •Приложение 5. Расширенные коды клавиатуры
- •Ascii‑коды
- •Расширенные коды
- •Приложение 6. Правила хорошего кода
- •Приложение 7. Рекомендуемая литература
21. Текстовые файлы
Для написания большинства сложных программ требуется обмен данными с файлами. В этой главе мы рассмотрим только текстовые файлы, для работы с бинарными и типизированными файлами см. специальную литературу и главу 22.
21.1 Общие операции
Для работы с каждым файлом описывается переменная типа text:
var f:text;
Ее называют файловой переменной. Если программа использует несколько файлов одновременно, для каждого из них описывается такая переменная. Можно использовать и одну переменную для нескольких файлов, если они обрабатываются последовательно, и каждый следующий файл открывается после завершения работы с предыдущим. Вся работа с файлом происходит через файловую переменную, имя файла нам придется указать только один раз следующим оператором:
assign (f,'имя_файла');
где f – ранее описанная файловая переменная.
Этот оператор предшествует открытию файла и связывает файловую переменную с файлом на жестком или гибком диске. В качестве имени файла может быть указано фиксированное имя:
assign (f,'data.txt'); {будет открываться файл с именем data.txt из текущей папки}
assign (f,'a:\my.dat'); {будет открываться файл my.dat из корневой папки дискеты}
Имя файла также может быть введено пользователем с клавиатуры:
Var name:string; f:text;
Begin
Writeln ('Введите имя файла:');
Readln (name);
Assign (f,name);
. . .
или передано программе параметром командной строки (см. п. 5.3).
После связывания следует открыть файл. Каждый файл может быть открыт только в одном из трех режимов – для чтения данных, для записи новых данных (при этом, если файл уже существовал, его прежнее содержимое будет стерто) или для добавления данных в конец файла. Если требуется сначала прочитать данные из файла, а потом переписать этот же файл, следует открыть файл для чтения, после чтения закрыть его и вновь открыть для записи. Открытие файла выполняется одним из трех операторов:
reset (f); - открыть для чтения
rewrite (f); - открыть для записи
append (f); – открыть для добавления
Чтение или запись данных осуществляется знакомыми нам операторами read, readln, write и writeln, но первым параметром этих операторов указывается имя файловой переменной:
Var a,b,c:real; f1,f2:text;
Begin
Assign (f1,'read.txt');
Assign (f2,'write.txt');
Reset (f1); {открыли файл read.txt из текущей папки}
Rewrite (f2); {для чтения, а файл write.txt для записи}
Read (f1,a,b); {Прочитали 2 числа из файла read.txt}
C:=(a+b)/2;
Writeln (f2,c:6:2); {записали значение c и перевод строки в файл write.txt}
. . .
После того, как все операции с файлом выполнены, его следует закрыть, особенно если происходила запись или добавление данных:
close(f); {закрыли файл, связанный с файловой переменной f}
При работе с файлами могут возникнуть ошибки, связанные как с отсутствием нужного файла на диске, так и с проблемами чтения или записи (например, мы пытаемся открыть файл для записи на защищенном от записи диске). Поэтому операторы открытия файла и чтения или записи данных следует защищать директивой компилятора {$I-}. . .{$I+}, а после оператора проверять статус операции ввода-вывода с помощью стандартной функции IoResult:
var f:text; name,s:string;
begin
writeln ('Введите имя файла для открытия:');
readln (name);
assign (f,name);
{$I-}reset(f);{$I+}
if IoResult<>0 then begin
writeln ('Не могу открыть файл ',name,' для чтения!');
writeln ('Нажмите Enter для выхода из программы');
readln;
halt;
end;
readln(f,s);
writeln ('Первая строка этого файла выглядит так:');
writeln (s);
close(f);
writeln ('Нажмите Enter для выхода из программы');
readln; end.
В дальнейших примерах мы для краткости не всегда будем выполнять эти проверки, но хороший стиль программирования предполагает, что в своих программах Вы будете их делать.
При чтении из файлов зачастую объем читаемых данных неизвестен заранее. Поэтому необходима функция, умеющая определять, прочитаны ли уже все данные:
Function Eof(Var F : Text) : Boolean; - возвращает истину, если при чтении достигнут конец файла
Function Eoln (Var F : Text) : Boolean; - возвращает истину, если при чтении достигнут конец строки
Как правило, основной цикл чтения файла с заранее неизвестным количеством строк выглядит так:
While not eof (f) do begin
{операторы для чтения строк файла и работы с ними}
End;
При чтении из одного файла "смешанных" строковых и числовых данных следует проверять, действительно ли в нужных строках файла содержатся числа. Для этого можно использовать стандартную процедуру val. Как правило, формат файлов, понимаемых той или иной программой, выбирается программистом, и важно предусмотреть реакцию программы на ошибочный формат исходных данных. Допустим, наша программа представляет собой простейший телефонный справочник, включающий имена абонентов и по одному телефонному номеру на каждое имя. Формат файла, хранящего данные справочника, также выберем простейшим:
Фамилия1
Номер1
Фамилия2
Номер2
и т. д., то есть, в строках 1,3,5,… файла содержатся фамилии абонентов, а в строках 2,4,6,… их номера телефонов. Примем также, что файл справочника называется phones.txt, существует и находится в той же папке, откуда запускается программа.
var f:text;
name,phone,search:string;
number,strings:longint; error:integer; found:boolean;
begin
assign (f,'phones.txt');
reset(f);
writeln ('Введите фамилию абонента для поиска:');
readln (search);
strings:=1; {Счетчик прочитанных строк файла}
found:=false; {Переключатель состояний "найдено"-"не найдено"}
while not eof(f) do begin
readln (f,name); {Прочитали фамилию}
readln (f,phone); {Прочитали номер}
val (phone,number,error);
{Пробуем номер-строку преобразовать в число}
if error<>0 then begin {если это не удалось сделать - ошибка}
Writeln ('Ошибка - нет номера телефона! Номер строки=', strings);
Writeln ('Нажмите Enter для выхода из программы');
Readln;
Halt;
end;
if name=search then begin
writeln ('Телефон найден:',number);
found:=true;
break;
end;
strings:=strings+1;
end;
close (f);
if found=false then writeln ('Телефон не найден!');
Writeln ('Нажмите Enter для выхода из программы');
Readln;
end.
Разумеется, этой программе недостает как умения редактировать открываемый ей справочник, так и гибкости при поиске – например, она различает как разные символы строчные и прописные буквы во вводимой фамилии.