Федеральное агентство по образованию
Pascal. Файлы
Учебно-методическое пособие (Практикум)
Составители: В.В. Васильев...
39 downloads
167 Views
553KB Size
Report
This content was uploaded by our users and we assume good faith they have the permission to share this book. If you own the copyright to this book and it is wrongfully on our website, we offer a simple DMCA procedure to remove your content from our site. Start by pressing the button below!
Report copyright / DMCA form
Федеральное агентство по образованию
Pascal. Файлы
Учебно-методическое пособие (Практикум)
Составители: В.В. Васильев Л.В. Хливненко
ВОРОНЕЖ 2007
2
Утверждено Научно-методическим советом математического факультета 31 января 2007 года, протокол № 5
Рецензент В.В. Провоторов
Учебно-методическое пособие (практикум) подготовлен на кафедре математического моделирования математического факультета Воронежского государственного университета.
Рекомендовано для студентов 5-6 курсов всех форм обучения.
Для направления 010101 (010100) Математика
3 1. Классификация файлов. Типизированные файлы Различают физические и логические файлы. Физический файл это поименованная область памяти на каком-либо носителе информации. В этом смысле содержимое файла представляет собой последовательность байтов закодированной информации. Логический файл – файловая переменная структурированного типа данных, в котором описывается способ интерпретации содержимого физического файла. В логическом файле описан шаблон чтения/записи информации из физического файла. Файловый тип представляет собой структуру, состоящую из компонент одного вида. Длина переменной файлового типа в описании не объявляется. Фактически размер файла ограничивается размером памяти носителя информации. По логической структуре файлы в Паскале делятся на типизированные, текстовые и нетипизированные. Типизированный файл - это совокупность компонент объявленого в описании стандартного или пользовательского типа. Переменная файлового типа в этом случае описывается так: =file of ; Типом компонет файла может быть любой стандартный или пользовательский тип, кроме файлового и опирающегося на файловый. Текстовый файл - это совокупность строк, состоящих из символов. Переменную файлового типа можно описать так: =text; Нетипизированный файл - это совокупность компонент, для которых не объявлен тип. В файлах такого вида читается и записывается за одно обращение указанное количество байт. Переменная нетипизированного файлового типа описывается так: =file; Работа с файловой переменной в блоке операторов начинается с процедуры assign(, ‘‘), которая связывает логическую файловую переменную с полным именем физического файла на диске. В Delphi используется эквивалентная процедура AssignFile(). До выполнения операций чтения-записи файл должен быть открыт. Процедура reset() открывает существующий файл для чтения (и для записи- для типизированных и нетипизированных файлов). Процедура rewrite() создает новый файл и открывает его для записи. Если процедурой rewrite() открыть существующий файл, то вся информация из него потеряется, так как старый файл при этом уничтожится. При открытии файлов могут возникать ошибки периода исполнения. Например, при открытии процедурой reset() несуществующего файла. Автоматическая проверка ошибок, возникающих при операциях вводавывода, может быть включена и отключена директивами (командами) ком-
4 пилятора {$I+} и {$I-}.По умолчанию действует директива {$I+}. В следующем фрагменте программы показано, как корректно открыть существующий файл, а в случае отсутствия файла на диске - создать его. {$I-} reset(f) {$I+} if IoResult0 then rewrite(f); Функция IoResult: word возвращает код возникшей ошибки при операциях чтения-записи в файл. Если ошибка не возникла, то значение функции IoResult равно нулю. Вызов функции IoResult обнуляет ее значение. Если включить директиву {$I+} и не вызвать функцию IoResult , значение которой было отлично от нуля, то следующее обращение к процедуре ввода-вывода будет остановлено из-за имевшей место предыдущей ошибки ввода-вывода. По методу доступа к компонентам файлы делятся на файлы последовательного доступа и прямого доступа. При последовательном доступе компоненты считываются (записываются) одна за другой. Первая записанная компонента первой и считывается. Непосредственный доступ к компоненте файла невозможен. При прямом доступе возможно непосредственное обращение (чтение, запись) к нужному компоненту файла. Типизированные и нетипизированные файлы являются файлами последовательного и прямого доступа. К информации из текстовых файлов возможен только последовательный доступ. Для текстовых и типизированных файлов чтение информации из файла осуществляется с помощью процедуры read(,), а запись - с помощью процедуры write(,). При открытии файла указатель текущей позиции устанавливается на первый записанный компонент файла. Элементы типизированных файлов нумеруются, начиная с нуля. Обычно при последовательном доступе чтение информации из файла осуществляется с помощью цикла. Пока не считаны все компоненты файла, файл открыт для чтения и указатель текущей позиции показывает на элемент, находящийся за последним считанным. Признаком конца файла является значение True функции Eof(). Функция принимает значение True, когда указатель текущей позиции находится в файле за последним компонентом, либо когда файл пуст. Когда все операции с файлом завершены, его нужно закрыть и для чтения и для записи вызовом процедуры Close(). В Delphi для этого используется процедура CloseFile(). Познакомимся с процедурами и функциями, использующимися при прямом доступе. Чтобы прочитать или обновить нужный компонент типизированного файла, надо поставить на него указатель текущей позиции с
5 помощью процедуры seek (,). При записи информации в существующий типизированный файл, информация будет записана на место текущего компонента. Поэтому для добавления новой информации в конец существующего файла указатель текущей позиции надо расположить за последним элементом. Функция FileSize() возвращает размер файла, то есть число компонентов файла при счете от единицы. Для работы с прямым доступом к компонентам типизированных файлов предназначена функция FilePos(), которая возвращает номер текущей позиции указателя в файле (при счете от нуля) и процедура Trancate(), которая удаляет информацию в файле, расположенную после текущей позиции. Ниже приведена программа, в которой показано, как создать новый файл, записать информацию в него, а также как пополнить уже созданный файл новой информацией. Задача 1. Создайте типизированный файл workers.txt, содержащий информацию о сотрудниках (ФИО, должность, дату приема на работу). Если файл уже создан, то пополните его записями о новых сотрудниках. Предусмотрите вывод на экран информации о всех сотрудниках. План примера 1 1-3. Создание и сохранение консольного приложения. 4. Написание программы для решения задачи. 5-7. Исполнение, сохранение и закрытие проекта. Пример работы 2: Подсказка 1. Войдите в Delphi Пуск|Программы|Delphi 2. Создайте консольный проект (без File|New|Other… Console Appliформ) cation 3. Сохраните программу в новый подкаталог File⏐Save Project As… 4. Допишите программу к задаче 1, используя созданный Delphi шаблон program Sotrudnik; {$APPTYPE CONSOLE} uses SysUtils; type dt=record day,month,year: byte end; t_sotr = record fam, im, ot, dol: string[30]; dt_pr:dt end; t_file = file of t_sotr; var man:t_sotr; my_file:t_file; c:char; procedure input_inf (var man:t_sotr); (* ввод информации о сотруднике man *) begin write('Фамилия : '); readln(man.fam);
6 write('Имя : '); readln(man.im); write('Отчество : '); readln(man.ot); write('Должность: '); readln(man.dol); write('Число, месяц, год найма: '); readln(man.dt_pr.day,man.dt_pr.month,man.dt_pr.year); end;{input_inf} procedure output_inf (man:t_sotr); (* вывод информации о сотруднике man *) begin write('ФИО: '); writeln(man.fam,' ',man.im,' ',man.ot); write('Должность: '); writeln(man.dol); write('Дата найма: '); writeln(man.dt_pr.day,'.',man.dt_pr.month,'.',man.dt_ pr.year); end;{output_inf} begin {Sotr} (* связывание файловой переменной my_file с именем файла на диске *) assign(my_file,'Z:\N kurs\Familia\workers.txt'); (* попытка открытия существующего файла *) {$I-} reset(my_file); {$I+} if ioresult0 then begin (* создание файла и запись информации в него *) rewrite(my_file); repeat write('Добавить информацию о сотруднике(д/н)?'); readln(c); if c='д' then begin input_inf(man); write(my_file,man) end until c='n' end else begin (* добавление записей в существующий файл *) repeat write('Добавить информацию о сотруднике(д/н)?); readln(c); if c='д' then begin
7 (* перестановка указателя текущей позиции в конец файла *) seek(my_file,filesize(my_file)); input_inf(man); (* запись информации в файл *) write(my_file,man) end until c='n' end; close(my_file); (* чтение информации из файла и вывод на экран *) write(‘Вывести информацию о сотрудниках(д/н)?'); readln(c); if c='y' then begin {$I-} reset(my_file); {$I+} if ioresult=0 then begin while not eof(my_file) do begin read(my_file,man); output_inf(man) end; end else writeln('Файл пуст!'); (* закрытие файла*) close(my_file); end; readln end.{Sotr} 5. Запустите программу на исполнение Run⏐Run 6. Сохраните результаты работы File⏐Save 7. Закройте проект File⏐Close Единицей чтения-записи для типизированных файлов является переменная того же типа, что и компоненты файла! Задача 2. Выведите информацию о сотрудниках из файла workers.txt. Программу оформите в виде Delphi–проекта. План примера 2. 1-9. Разработка интерфейса проекта. 11. Указание названий столбцов. 12. Чтение информации из файла и вывод в сетку 13-15. Исполнение, сохранение и закрытие проекта.
8 Пример работы 2: Подсказка 1. Войдите в Delphi Пуск|Программы|Delphi 2. Сохраните проект в отдельную папку File|Save Project As... 3. В строке заголовка формы напиСвойство Caption шите Сотрудники 4. Добавьте компонент BitBtn – Вывести информаСвойство Caption цию о сотрудниках из файла 5. Добавьте компонент StringGrid Закладка Additional 6. Оставьте в фиксированной зоне Свойства FixedCols и FixedRows только первую строку 7. Измените ширину столбцов Свойство DefaultColWidth 8. Измените количество столбцов Свойство СolCount 9. Сделайте сетку невидимой при Свойство Visible запуске type dt=record day,month,year: byte 10. Опишите глоend; бальные типы и t_sotr = record переменные перед fam, im, ot, dol: string[30]; словом implementadt_pr:dt tion end; t_file = file of t_sotr; var man:t_sotr; f:t_file; procedure TForm1.FormCreate(Sender: 11. Напишите наTObject); звания столбцов, создав обработчик begin StringGrid1.Cells[0,0]:='Фамилия'; события OnCreate StringGrid1.Cells[1,0]:='Имя'; формы StringGrid1.Cells[2,0]:='Отчество'; StringGrid1.Cells[3,0]:='Должность'; StringGrid1.Cells[4,0]:='День'; StringGrid1.Cells[5,0]:='Месяц'; StringGrid1.Cells[6,0]:='Год'; end; 12. Выведите информацию из файла в сетку, создав обработчик события OnClick кнопки procedure TForm1.BitBtn1Click(Sender: TObject); var filename:string; i:byte; (* номер строки в сетке *) begin StringGrid1.Visible:=True; filename:='Z:\N kurs\Familia\workers.txt'; AssignFile(f,filename); (* связывание логического и физического файла *) if FileExists(filename) (* проверка существования физического файла *)
9 then begin (* открытие файла для чтения *) reset(f); i:=1; (* изменение количества строк в сетке в зависимости от длины файла *) StringGrid1.RowCount:=FileSize(f)+1; (* пока не конец файла читаются компоненты файла и выводятся в сетку *) while not eof(f) do begin read(f,man); StringGrid1.Cells[0,i]:=man.fam; StringGrid1.Cells[1,i]:=man.im; StringGrid1.Cells[2,i]:=man.ot; StringGrid1.Cells[3,i]:=man.dol; StringGrid1.Cells[4,i]:=IntToStr(man.dt_pr.day); StringGrid1.Cells[5,i]:=IntToStr(man.dt_pr.month); StringGrid1.Cells[6,i]:=IntToStr(man.dt_pr.year); inc(i) end ; (*while *) CloseFile(f) end (* then *) else ShowMessage('Файла ‘+filename+’ не существует!') end; 13. Запустите программу на исполнение Run⏐Run 14. Сохраните результаты работы File⏐Save 15. Закройте проект File⏐Close Задание: включите в проект возможность изменять существующую информацию в файле и добавлять новую. Задача 3. Проверьте, есть ли однофамильцы в файле workers.txt, содержащем информацию о сотрудниках. Результатом проверки являются ФИО однофамильцев и их должности или фраза “однофамильцев нет”. ♣ Для поиска однофамильцев организуем два вложенных цикла. Внешний цикл по i служит для просмотра всех компонентов файла с 1-го до предпоследнего. Внутренний цикл по j (диапазон изменения от номера i-го компонента файла до номера последнего компонента) служит для сравнения фамилий i-го и j-го сотрудников. Если фамилии совпали, то логической переменной net, хранящей ответ на вопрос: “Все ли фамилии сотрудников различны?”, присваивается значение false. При этом логической переменной flag, хранящей ответ на вопрос: “Есть ли однофамильцы у i-го сотрудника?”, присваивается значение true. ФИО и должность найденного j-го однофамильца записываются в файл с результатом проверки. По значению логической переменной flag делается аналогичная запись об i-ом сотруднике.
10 Особый случай. Если однофамильцев больше двух, то при описанном алгоритме в файле с результатами окажется несколько одинаковых записей. Например, однофамильцев трое, тогда в файле появятся записи о 2-м, 3-м и 1-м однофамильцах, а также о 3-м и 2-м. Для решения описанной проблемы предлагается создать множество z номеров сотрудников, информация о которых уже записана в файл. Новая запись в файл с результатами делается только при отсутствии номера найденного однофамильца во множестве z. По значению логической переменной net записывается в файл фраза: “Однофамильцев нет”. Проект к задаче 2 дополним кнопкой Поиск однофамильцев, к которой присоединим основной обработчик.♠ План примера 3 1-4. Разработка интерфейса проекта 5. Изменение доступности кнопки 6. Поиск однофамильцев 7-9. Исполнение, сохранение и закрытие проекта Пример работы 3: Подсказка 1. Войдите в Delphi Пуск|Программы|Delphi 2. Скопируйте проект к задаче 2 в от- Используйте Мой компьютер дельный каталог 3. Добавьте компонент Button – ПоСвойство Caption иск однофамильцев 4. Сделайте кнопку недоступной при запуске формы Свойство Enabled 5. Сделайте кнопку доступной, при нажатии на Button1.Enabled:= кнопку Вывести информацию о сотрудниках из True; файла 6. Найдите однофамильцев, создав обработчик события OnClick кнопки procedure TForm1.Button1Click(Sender: TObject); var filename:string; (* имя физического файла *) flag,net:boolean;(* логические переменные *) z:set of byte; (* множество номеров однофамильцев *) i,j:integer; (* счетчики циклов *) man1:t_sotr; (* запись об однофамильце *) result:string; (* список однофамильцев *) begin result:=''; filename:='Z:\N kurs\Familia\workers.txt'; AssignFile(f,filename); if FileExists(filename) then begin (* открытие существующего файла с информацией о сотрудниках фирмы *) reset(f);
11 net:=true; z:=[]; (* поиск однофамильцев *) for i:=0 to filesize(f)-2 do begin seek(f,i); read(f,man); flag:=false; for j:=i+1 to filesize(f)-1 do begin seek(f,j); read(f,man1); if man.fam=man1.fam then begin if not (j in z) then result:= result+ man1.fam+ ' '+man1.im+' '+man1.ot+' - '+man1.dol+chr(13); flag:=true; net:=false; z:=z+[j] end end; if flag and not (i in z) then result:=result+man.fam+' '+man.im+' '+man.ot+' '+man.dol+chr(13); end; CloseFile(f) end; (* запись отрицательного результата поиска *) if net=true then result:=result+'Однофамильцев нет'; ShowMessage(result) end; 7. Запустите программу на исполнение Run⏐Run 8. Сохраните результаты работы File⏐Save 9. Закройте проект File⏐Close В одной программе можно работать сразу с несколькими файлами. Задача 4. Сохраните последовательность целых чисел в файл. Создайте новый файл, значения в который записываются по следующему правилу: суммируются подряд идущие значения одного знака; вместо группы нулей записывается один нуль. Например: • исходный файл: 20 10 4 -1 -2 0 0 0 -10 41 62 • файл-результат: 34 -3 0 -10 103. ♣ Последовательность целых чисел вводится через компонент SpinEdit и сохраняется в файл. Признаком конца ввода служит число 999. По окончанию ввода кнопка Ввести становится недоступной и активизируется кнопка Просмотр исходного файла. Последовательность чисел выводится в информационном окне. Кнопка просмотра становится недоступной. Активизируется кнопка Создание файла-результата, к которой привя-
12 зывается основной обработчик. После создания файла-результата активной остается только кнопка Просмотр файла-результата. Алгоритм решения задачи. Логические переменные f1, f2, f3 имеют значение true, когда идет суммирование положительных, отрицательных и нулевых значений соответственно. Очередное число считывается из файла в переменную a. Суммирование продолжается, если (a>0) and f1 or (a0 then f1:=true else if a0) and f1 or (a0 then f1:=true else if amax then begin max:=n[j]; m:=j end; n[m]:=n[i]; n[i]:=max; (* перестановка номеров строк в массиве l *) p:=l[m]; l[m]:=l[i]; l[i]:=p end; (* проверка правильности упорядочивания элементов *) writeln('Количество букв – Номер строки'); for i:=1 to d do writeln(n[i],' - ',l[i]); (* запись строк файла в порядке невозрастания количества различных букв в них *) for i:=1 to d do begin reset(f1); for j:=1 to l[i] do readln(f1,s);
22 (* запись i-й строки результирующего файла, имеющей номер l[i] в исходном файле*) writeln(f2,s); (* закрытие исходного файла*) close(f1) end; (* закрытие файла-результата*) close(f2); readln end.{SortFile} 6. Запустите программу на исполнение Run⏐Run 7. Сохраните результаты работы File⏐Save 8. Проверьте правильность работы программы См. файлы text.txt и result.txt 9. Закройте проект File⏐Close Для работы с текстовыми файлами предназначены две логические функции: • SeekEoln() - обнаружение признака конца строки. Пропускает все пробелы и знаки табуляции до тех пор, пока не обнаружен первый значащий символ или признак конца строки. Возвращает значение true, если маркер конца строки обнаружен. • SeekEof() - обнаружение признака конца файла. Пропускает все пробелы, знаки табуляции и маркеры концов строк до тех пор, пока не обнаружен первый значащий символ или признак конца файла. Возвращает значение true, если маркер конца файла обнаружен. 3. Нетипизированные файлы Нетипизированные файлы рассматриваются как последовательность байтов. Для типизированных файлов в описании не определяется тип компонентов. При открытии таких файлов указывается размер записи (длина единицы чтения-записи). Читать информацию из нетипизированных файлов можно в переменные любого типа, кроме файлового. Нетипизированная файловая переменная описывается так: : file; Связать файловую переменную с именем файла на диске можно вызовом процедуры assign(). Открыть существующий файл для чтения и записи можно с помощью процедуры reset(,). Создать новый файл можно вызовом процедуры rewrite(, ). Скорость обмена информацией между диском и памятью наиболее высока для нетипизированных файлов. Для увеличения скорости длину записи нужно выбирать кратной длине физического сектора накопителя информации (обычно, 512 байт). Напомним, что при форматировании диск разбивается на дорожки и секторы. Единицей чтения-записи информации на диск является кластер, который занимает один или несколько секторов
23 на одной дорожке. Если длина записи в процедурах reset() и rewrite() не указана, то по умолчанию она равна 128 байтам. Работая с нетипизированными файлами, нельзя использовать процедуры read и write. Для чтения информации из нетипизированного файла предназначена процедура: blockread(,,,) - имя переменной, в которую будет читаться информация. - количество записей, которые должны быть прочитаны за одно обращение к диску. - необязательный параметр, принимающий свое значение в процессе работы программы. Значение параметра равно количеству фактически прочитанных записей. Если выбрать длину записи, равной единице, то информация из файла будет читаться по одному байту. Значение параметра будет равно размеру в байтах переменной . Размер переменной в байтах можно узнать с помощью функции SizeOf(). Размер файла в байтах можно узнать с помощью функции FileSize, если установить длину записи, равной единице. Для записи информации в нетипизированный файл предназначена процедура: blockwrite(,,, ) Указание необязательного параметра блокирует ошибку ввода-вывода, которая может возникнуть при чтении или записи информации на диск. После вызова процедур blockread (...) и blockwrite(...) указатель перемещается на заданное в файле. Используя процедуру и функции прямого доступа: Seek(), FilePos(), FileSize() можно организовать прямой доступ к компонентам нетипизированного файла. В программах к задачам 1 и 2 показано, как создать нетипизированный файл и как прочитать информацию из нетипизированного файла. Задача 1. Создайте нетипизированный файл info.dat, содержащий текстовую информацию о сотрудниках: ФИО; дата рождения: число, месяц, год; адрес: улица, дом, квартира. ♣ Информация о сотруднике описывается следующим образом: type tad=record ul:string[23]; dom:string[3]; kv:string[3] end; zap = record fio:string[40]; dr:string[6]; ad:tad end; Напомним, что переменная типа string представляет собой массив из
24 символов, в нулевом элементе которого хранится фактический размер строки. Переменная типа zap занимает в памяти 80 байт (41+7+24+4+4). Поэтому информацию в нетипизированный файл будем записывать блоками по 80 байт. За один прием в программе записывается информация об одном сотруднике. При запуске программы содержимое файла с информацией о сотрудниках выводится в сетку (если файл существует). В противном случае создается пустой файл. Чтобы ввести информацию о новом сотруднике, нужно добавить новую строку в сетку. Клик по кнопке Записать информацию в файл сохраняет информацию из сетки в файл. Кнопка Вывести список сотрудников, рожденных в одном месяце, будет использована при решении следующей задачи. ♠ План примера 1 1-10. Разработка интерфейса проекта 11. Описание глобальных переменных и типов 12. Чтение информации из файла в сетку при создании формы 13. Добавление новой строки в таблицу 14. Сохранение информации из ячеек сетки в файл 15-18. Исполнение, сохранение и тестирование проекта Подсказка Пример работы 1: 1. Войдите в Delphi Пуск|Программы|Delphi 2. Сохраните проект в отдельную пап- File|Save Project As... ку в своем каталоге 3. В строке заголовка формы напишите Сотрудники, рожСвойство денные в одном месяце Caption 4. Добавьте компонент StringGrid Закладка Additional 5. Уберите из фиксированной зоны FixedCols=0 сетки 1-й столбец 6. Сделайте в сетке 5 столбцов и 4 Свойства ColCount, RowCount строки 7. Выберите подходящий цвет ячеек сетки Свойство Color 8. Установите подходящую ширину Свойство DefaultColWidth столбцов сетки 9. Разрешите редактирование ячеек Опции goEditing, goAlwaysShowсетки Editor из группы свойств Options 10. Добавьте три компонента Button - Добавить строку в Закладка таблицу, Записать информацию в файл, Вывести список Standard. сотрудников, рожденных в одном месяце Свойство Caption type tad=record ul:string[23]; 11. Опишите гло-
25 dom:string[3]; бальные типы и kv:string[3] end; переменные перед zap = record fio:string[40]; словом implementadr:string[6]; ad:tad tion end; var f:file; z:zap; i,k:integer; Procedure Tform1.FormCreate(Sender: 12. Напишите обработчик события TObject); Begin OnCreate формы, StringGrid1.Cells[0,0]:='Фамилия в котором заполИ.О.'; няется фиксироStringGrid1.Cells[1,0]:='ДДММГГ'; ванная зона ячеек StringGrid1.Cells[2,0]:='Улица'; сетки. StringGrid1.Cells[3,0]:='Дом'; StringGrid1.Cells[4,0]:='Квартира'; AssignFile(f,'Z:\N Если файл с инkurs\Familia\info.dat'); формацией о соIf FileExists('Z:\N трудниках сущест- kurs\Familia\info.dat') вует, то Then файл открывается Begin для чтения, reset(f,80); число строк сетки StringGrid1.RowCount:=FileSize(f); устанавливается for i:=1 to FileSize(f)-1 do равным количестbegin blockread(f,z,1,k); ву записей в файStringGrid1.Cells[0,i]:=z.fio; ле, StringGrid1.Cells[1,i]:=z.dr; в цикле информаStringGrid1.Cells[2,i]:=z.ad.ul; ция из файла выStringGrid1.Cells[3,i]:=z.ad.dom; водится в ячейки StringGrid1.Cells[4,i]:=z.ad.kv; сетки, в конце выend; {for} вода информации CloseFile(f) файл закрывается. End; {Then} end; {procedure} Procedure TForm1.Button1Click(Sender: 13. Напишите обработчик события Tobject); begin OnClick кнопки Добавить строку в StringGrid1.RowCount:= StringGrid1.RowCount+1; таблицу end; procedure TForm1.Button2Click(Sender: 14. Напишите обраTObject); ботчик события OnClick кнопки Записать begin AssignFile(f,'Z:\N информацию в файл. kurs\Familia\info.dat'); Файл по указанному
26 rewrite(f,80); for i:=1 to StringGrid1.RowCount do begin z.fio:=StringGrid1.Cells[0,i]; z.dr:=StringGrid1.Cells[1,i]; z.ad.ul:=StringGrid1.Cells[2,i]; z.ad.dom:=StringGrid1.Cells[3,i]; z.ad.kv:=StringGrid1.Cells[4,i]; blockwrite(f,z,1,k); end; CloseFile(f); end; 15. Запустите программу на исполнение Run⏐Run 16. Запустите программу на исполнение повторно. Допол- Run⏐Run ните список информацией о новых сотрудниках 17. Запустите программу на исполнение. Убедитесь, что Run⏐Run список пополнился новой информацией 18. Сохраните результаты работы File⏐Save Задача 2. Используя созданный нетипизированный файл info.dat, распечатайте список сотрудников, у которых в заданном месяце день рождения. ♣ Для решения задачи продолжим разработку проекта, сделанного в примере работы 1. Ключевой обработчик подсоединяется к событию OnClick кнопки Вывести список сотрудников, рожденных в одном месяце. При чтении информации о сотруднике выделяется месяц из поля Дата рождения и сравнивается с заданным номером месяца. Номер месяца задается через диалог InputBox. При совпадении номеров месяцев Фамилия И.О. сотрудника дописывается в список, хранящийся в строковой переменной list. После проверки список сотрудников выводится через диалог ShowMessage. ♠
адресу создается вновь. В цикле построчно информация из ячеек сетки записывается в поля записи. Сформированная запись сохраняется в файл. В конце записи информации файл закрывается
План примера 2 1. Открытие проекта, созданного в примере работы 1 2. Определение номера месяца и поиск сотрудников, родившихся в этом месяце 3. Запуск и тестирование проекта 4-5. Сохранение и закрытие проекта Пример работы 2: Подсказка 1. Откройте проект, созданный в приFile|Open Project ... мере работы 1 2. Напишите обра- procedure TForm1.Button3Click(Sender: TObject); ботчик события var list,m,x:string; OnClick кнопки
27 Вывести список сотрудников, рожденных в одном месяце
begin m:=InputBox('Ввод номера месяца','Введите номер месяца','01'); list:=''; AssignFile(f, 'Z:\N kurs\Familia\info.dat'); reset(f,80); repeat blockread(f,z,1,k); x:=copy(z.dr,3,2); if x=m then list:=list+z.fio+chr(13); until eof(f); ShowMessage(list); CloseFile(f); End; 3. Запустите программу на исполнение и Run⏐Run протестируйте ее работу 4. Сохраните результаты работы File⏐Save 5. Закройте проект File⏐Close В следующей задаче показано, как сделать копию файла. Задача 3. Создайте копию файла info.dat, скопировав его содержимое в файл info1.dat. ♣ Файл info.dat связывается с файловой переменой f1, info1.dat - с переменной f2. Файл f1 открывается для чтения, а файл f2 - для записи. Длина единицы чтения-записи будет равна 1 байту. Буфером для ввода-вывода служит переменная z, представляющая собой массив из символов. Количество символов в массиве определяется в константе Size. Из файла info.dat записи читаются по одной. В переменной k1 хранится число фактически прочитанных записей. Именно столько записей должно быть записано в файл info1.dat за один прием. В переменной k2 хранится число фактически сделанных записей. Чтение и запись продолжаются до тех пор, пока либо не будет прочитано ноль записей (файл info.dat прочитан до конца), либо количества фактически прочитанных и сделанных записей станут различны (например, изза нехватки места на диске). Программу оформим в виде консольного приложения Delphi. ♠ План примера 3 1-3. Создание и сохранение консольного приложения. 4. Написание программы для решения задачи. 5-7. Исполнение, сохранение и закрытие проекта. Пример работы 3: Подсказка 1. Войдите в Delphi Пуск|Программы|Delphi 2. Создайте консольный проект (без File|New|Other… Console Ap-
28 форм) plication 3. Сохраните программу в новый File⏐Save Project As… подкаталог в своей папке 4. Допишите программу к задаче 3, используя созданный Delphi шаблон program FileCopy; {$APPTYPE CONSOLE} uses SysUtils; const Size=5; var f1,f2:file; k1,k2:integer; z:array[1..Size] of char; begin assign(f1, 'Z:\N kurs\Familia\info.dat'); assign(f2,'Z:\N kurs\Familia\info1.dat'); reset(f1,1); rewrite(f2,1); repeat blockread(f1,z,1,k1); blockwrite(f2,z,k1,k2); until (k1=0) or (k1k2); end.{FileCopy} 5. Запустите программу на исполнение Run⏐Run 6. Сохраните результаты работы File⏐Save 7. Закройте проект File⏐Close Размер копии файла точно совпадет с размером исходного файла, если размер файла будет кратен порции записываемой в новый файл информации. Задача 4. Напишите программу шифрования по методу наложения битов, используя некоторый файл как ключ. ♣ Алгоритм шифрования заключается в следующем. Биты исходного файла и биты файла-ключа складываются согласно таблице истинности логической операции Xor (исключающее ИЛИ). Если операнды логических операций являются целыми числами, то результатом логической операции является тоже целое число, биты которого формируются из битов операндов согласно таблице истинности используемой логической операции. Из исходного файла и файла-ключа считывается по одному байту в переменную типа char. Коды прочитанных символов складываются посредством логической операции Xor. Результат сложения интерпретируется как код зашифрованного символа. Новый символ записывается в файлрезультат. Построенная по описанному алгоритму программа позволит шифровать и расшифровывать информацию. Например, Код исходного файла: 0 1 1 0 … 1010… Код файла-ключа :
29 Код файла-результата: 1 1 0 0 … Если к зашифрованному файлу применить то же правило шифрования, то получится исходный файл. Код зашифрованного файла: 1 1 0 0 … Код файла-ключа : 1010… Код файла-результата: 0110… Программу оформим в виде консольного приложения Delphi. В нашем примере файл, который надо шифровать, будет называться file.dat. Файл kod.dat используется как ключ. Зашифрованный вариант хранится в файле result.dat.♠ План примера 4 1-2. Создание исходного файла и файла-ключа. 3-5. Создание и сохранение консольного приложения. 6. Написание программы для решения задачи. 7-13. Шифрование и дешифрование файлов, сохранение и закрытие проекта. Пример работы 4: Подсказка 1. Создайте файл с именем Для создания файла с помощью встроfile.dat в своей папке. Для более енного в FAR текстового редактора наглядной работы программы используйте клавиши Shift+F4. можно создать текстовый файл. При использовании Word сохраните Например, с отрывком из стихофайл в формате Обычный или Текст творения А.С. Пушкина: MS DOS. Я помню чудное мгновенье. Можно скопировать и переименоПередо мной явилась ты, вать другой файл Как мимолетное виденье, Как гений чистой красоты. 2. Создайте файл-ключ с именем Используйте встроенный в FAR текkod.dat в своей папке. Можно стовый редактор или Word. создать текстовый файл. НаприМожно скопировать и переименомер, с фразой: Это очень очень вать другой файл секретный код 3. Войдите в Delphi Пуск|Программы|Delphi 4. Создайте консольный проект File|New|Other… Console Applica(без форм) tion 5. Сохраните программу в новый File⏐Save Project As… подкаталог в своей папке 6. Допишите программу к задаче 4, используя созданный Delphi шаблон Program Shifr; {$APPTYPE CONSOLE} uses SysUtils; var f,k,r:file; (* Исходный файл, файл-ключ и файлрезультат *)
30 c1,c2,c3:char; (* Единицы чтения-записи *) p1,p2,p3:integer; (* Коды контроля над ошибками *) begin (* Связывание логических и физических файлов *) assign(f,'Z:\N kurs\Familia\file.dat'); assign(k,' Z:\N kurs\Familia\kod.dat'); assign(r,' Z:\N kurs\Familia\result.dat'); (* Открытие файлов f и k для чтения, создание файла r *) reset(f,1); reset(k,1); rewrite(r,1); (* Шифрование исходного файла *) repeat blockread(f,c1,1,p1); (* если файл-ключ короче исходного файла, то файл-ключ читается повторно сначала *) if eof(k) then seek(k,0); blockread(k,c2,1,p2); c3:=chr(ord(c1) xor ord(c2)); blockwrite(r,c3,1,p3); until (p1=0) or (p1p3); (* Закрытие файлов*) close(f);close®;close(k) end. 7. Запустите программу на исполнение Run⏐Run 8. Сохраните результаты работы File⏐Save 9. Просмотрите файл result.dat с зашифрованным FAR, клавиша F3 текстом 10. Переименуйте файл result.dat в файл file.dat FAR, клавиша F6 11. Запустите программу на исполнение Run⏐Run 12. Просмотрите файл result.dat. Должен полуFAR, клавиша F3 читься исходный текст 13. Закройте проект File⏐Close Задание: исправьте программу так, чтобы в конце файларезультата не появлялся дополнительный символ. Задание: отладьте программу так, чтобы в качестве исходного файла и файла-ключа можно было брать любые файлы.
© Учебное издание
31 Pascal. Файлы Учебное пособие для вузов (Практикум)
Составители: Васильев Валерий Викторович, Хливненко Любовь Владимировна
Редактор
Бунина Т.Д.