По первому тесту выполнил дважды задания. Результат получается правильный (проверял калькулятором). Пишет, что "Задание не проверено" и предлагает повторить. |
Обработка файлов средствами Free Pascal
7.3 Бестиповые файлы в языке Free Pascal
Для хранения данных различного типа удобно использовать бестиповые файлы. При открытии бестиповых файлов следует использовать расширенный синтаксис процедур reset и rewrite.
Reset ( var f : File; BuferSize : word );
Rewrite ( var f : File; BuferSize : word );
Необязательный параметр BufSize определяет размер блока передачи данных — количество байт, считываемых или записываемых в файл данных за одно обращение к нему. Если этот параметр отсутствует, то используется значение, устанавливаемое по умолчанию при открытии файла (128). Наибольшей гибкости можно достичь при размере блока 1 байт.
Для записи данных в бестиповый файл используется процедура BlockWrite:
BlockWrite ( var f : file; var X; Count : word; var WriteCount : word );
здесь f — имя файловой переменной, X — имя переменной, из которой данные записываются в файл, Count — количество блоков размером BufSize, записываемых в файл; необязательный параметр WriteCount определяет реальное количество записанных в файл блоков.
Процедура BlockWrite записывает Count блоков в файл, связанный с файловой переменной f2Размер блока определяется при выполнении процедур Reset, Rewrite., из переменной X. При корректной записи в файл возвращаемое процедурой BlockWrite значение WriteCount совпадает c Count.
При чтении данных из бестипового файла используется процедура BlockRead:
BlockRead ( var f : file; var Y; Count : word; var ReadCount : word );
где f — имя файловой переменной, Y — имя переменной, в которую считываются данные из файла, Count — количество блоков размером BufSize, считываемых из файла, необязательный параметр ReadCount определяет количество блоков размером BufSize, реально считанных из файла.
BlockRead считывает из файла, связанного с файловой переменной f, Count блоков в переменную Y. При корректном чтении из файла возвращаемое процедурой BlockRead значение ReadCount должно совпадать c Count.
Рассмотрим работу с бестиповыми файлами на примере решения нескольких задач.
Напишем консольное приложение для создания файла.
program Project1; {$mode objfpc}{$H+} uses Classes, SysUtils { you can add units after this }; type massiv=array [ 1.. 100000 ] of real; var i,N: word; f : file; x :^ massiv; begin Assignfile ( f, ’ /home/ evgeniy/pascal /6/pr_6/ new_file. dat ’ ); //Открываем файл для записи, размер блока передачи данных - 1 //байт. rewrite ( f, 1 ); //Ввод числа N - количества целых положительных чисел в //файле write ( ’N= ’ ); readln (N); //Записываем в файл f целое число N, а точнее 2 блока //(sizeof(word)=2) по одному байту из переменной N. BlockWrite ( f,N, sizeof ( word ) ); //Выделяем память для N элементов массива x вещественных //чисел. getmem( x,N*sizeof ( real ) ); //Ввод массива. writeln ( ’Введите массив ’ ); for i :=1 to N do begin write ( ’ x ( ’, i, ’ )= ’ ); readln ( x ^[ i ] ); end; for i :=1 to N do //Записываем в файл f вещественное число x^[i], а точнее 8 //блоков (sizeof(real)=8) по одному байту из переменной x^[i]. BlockWrite ( f, x ^[ i ], sizeof ( real ) ); //Запись массива в файл можно осуществить и без цикла с //помощью следующего обращения к функции BlockRead //BlockWrite(f,x^,N*sizeof(real)); //Запись массива в бестиповый файл без цикла с помощью одного //оператора BlockWrite(f,x^,N*sizeof(тип)) кажется авторам //предпочтительнее. //Закрываем файл. CloseFile ( f ); //Освобождаем память. freemem ( x,N*sizeof ( real ) ); readln; end.
Разработку программы решения задачи 7.6 начнём с создания шаблона графического приложения (Проект — Создать Проект — Приложение).
На форме расположим следующие компоненты:
- Две метки Label1 и Label2 для подписи.
- Edit1 — текстовое поле редактирования, в котором будем хранить содержимое исходного файла.
- Edit2 — текстовое поле редактирования, в котором будет храниться файл после преобразования.
- OpenDialog1 — компонент для выбора имени обрабатываемого файла.
- Button1 — кнопка для преобразования файла.
Расположим компоненты на форме примерно так, показано на рис. 7.10.
Основные свойства компонентов будем устанавливать программно при создании формы. Программа решения задачи 7.6 будет выполняться при щелчке по кнопке. Полный текст модуля с необходимыми комментариями:
unit Unit1; {$mode objfpc}{$H+} interface uses Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, StdCtrls; type { TForm1 } TForm1 = class (TForm) //На форме находятся: //Кнопка. Button1 : Tbutton; //Поле редактирования - для вывода содержимого исходного //файла. Edit1 : Tedit; //Поле редактирования - для вывода содержимого файла после //преобразования. Edit2 : Tedit; //Метки для подписи полей редактирования. Label1 : TLabel; Label2 : Tlabel; //Компонент для выбора файла. OpenDialog1 : TOpenDialog; procedure Button1Click ( Sender : TObject ); procedure FormCreate ( Sender : TObject ); private { private declarations } public { public declarations } end; massiv=array [ 1.. 50000 ] of real; var Form1 : TForm1; f : file; implementation { TForm1 } //Текст процедуры обработчика события "Щелчок по кнопке". procedure Tform1. Button1Click ( Sender : TObject ); var x :^ massiv; y : array [ 1.. 3000 ] of real; i,N: word; max : real; nmax : word; s : string; begin //Выбираем файл, который будем обрабатывать. if OpenDialog1. Execute then begin //Имя обрабатываемого файла записываем в переменную s. s := OpenDialog1. FileName; //Связываем файловую переменную с именем файла, хранящимся в //переменной s. AssignFile ( f, s ); //Открываем файл для чтения, размер блока передачи данных 1 //байт. Reset ( f, 1 ); //Считываем из файла f целое число (word) N, а точнее 2 блока //(sizeof(word)=2) по одному байту из переменной N. BlockRead ( f,N, sizeof ( word ) ); //Выделяем память для N элементов массива x вещественных //чисел. getmem( x,N* sizeof ( real ) ); //Считываем из файла f N вещественных чисел в переменную x. //Реально считываем N*sizeof(real) блоков по 1 байту. //Заполняем массив X значениями, хранящимися в файле. BlockRead ( f, x ^,N* sizeof ( real ) ); //Делаем видимыми первую метку и первый компонент Edit1. Label1. Visible := true; Edit1. Visible := true; for i :=1 to N do //Добавление очередного значения из массива x к первому //текстовому полю редактирования. //В результате в первом текстом поле будет выведен исходный //массив вещественных чисел. Edit1. Text := Edit1. Text+FloatToStrF ( x ^[ i ], ffFixed,5, 2)+ ’ ’; //Поиск максимального элемента и его номера. max:=x ^ [ 1 ]; nmax : = 1; for i :=2 to N do if x ^[ i ]>max then begin max:=x ^[ i ]; nmax:= i; end; //Удаление максимального элемента из массива. for i :=nmax to N -1 do x ^[ i ] : = x ^[ i + 1 ]; //Уменьшение количества элементов в массиве. N:=N-1; //Закрываем файл. CloseFile ( f ); AssignFile ( f, s ); //Открываем файл для записи. Rewrite ( f, 1 ); //Записываем в файл f целое число N, а точнее 2 блока //(sizeof(word)=2) по одному байту из переменной N. BlockWrite ( f,N, sizeof ( word ) ); BlockWrite ( f,N, sizeof ( word ) ); //Запись массива в файл с помощью обращения к функции //BlockRead. BlockWrite ( f, x ^,N* sizeof ( real ) ); //Закрываем файл. CloseFile ( f ); //Освобождаем память. freemem ( x,N* sizeof ( word ) ); //Чтение данных из преобразованного файла. AssignFile ( f, s ); Reset ( f, 1 ); //Считываем из файла f целое число (word) N, а точнее 2 блока //(sizeof(word)=2) по одному байту из переменной N. BlockRead ( f,N, sizeof ( word ) ); //Выделяем память для N элементов массива x вещественных //чисел. getmem( x,N* sizeof ( real ) ); //Считываем из файла f N вещественных чисел в переменную x. //Реально считываем N*sizeof(real) блоков по 1 байту. //Заполняем массив X значениями, хранящимися в файле. BlockRead ( f, x ^,N* sizeof ( real ) ); //Делаем видимыми вторую метку и второй компонент Edit2. Label2. Visible := true; Edit2. Visible := true; //Содержимое массива x выводим в текстовое поле Edit2. for i :=1 to N do Edit2. Text := Edit2. Text+FloatToStrF ( x ^[ i ], ffFixed,5, 2)+ ’ ’; //Закрываем файл и освобождаем память. CloseFile ( f ); freemem ( x,N* sizeof ( real ) ); end; end; procedure TForm1. FormCreate ( Sender : TObject ); begin //При создании формы устанавливаем свойства компонентов Edit1, //Edit2, label1, label2 и кнопки Button1. Все компоненты, //кроме кнопки, делаем невидимыми. Form1. Caption := ’Работа с бестиповыми файлами ’; Label1. Width := 80; Label1. Caption := ’Содержимое исходного файла ’; Edit1. Clear; Label2. Caption := ’Содержимое преобразованного файла ’; Label2. Width := 80; Edit2. Clear; Button1. Width :=150; Button1. Caption := ’Преобразование файла ’; Label1. Visible := false; Edit1. Visible := false; Label2. Visible := false; Edit2. Visible := false; end; initialization {$I unit1.lrs} end.
При запуске программы окно приложения будет таким, как на рис. 7.11.
После щелчка по кнопке Преобразовать файл появится окно выбора файла (см. рис. 7.12).
Окно программы после преобразования файла представлено на рис. 7.13.
Решение задачи начнём с написания консольной программы создания файла. Для этого определимся со структурой файла. Пусть в нём хранятся два значения типа word: N и M, затем матрица вещественных чисел A(N,M), затем значения P и L типа word и матрица B(P,L).
Ниже приведён листинг программы создания бестипового файла с комментариями.
program Project1; {$mode objfpc}{$H+} uses Classes, SysUtils { you can add units after this }; var f : file; i, j, n,m, l, p : word; a, b : array [ 1.. 20, 1.. 20 ] of real; begin AssignFile ( f, ’ Prim. dat ’ ); //Открываем файл для записи, размер блока передачи данных 1 //байт. rewrite ( f, 1 ); write ( ’N= ’ ); readln (N); write ( ’M= ’ ); readln (M); //Записываем в файл f целое число N, а точнее 2 блока //(sizeof(word)=2) по одному байту из переменной N. BlockWrite ( f,N, sizeof ( word ) ); //Записываем в файл f целое число M, а точнее 2 блока //(sizeof(word)=2) по одному байту из переменной M. BlockWrite ( f,M, sizeof ( word ) ); writeln ( ’ Matrica A ’ ); for i :=1 to N do for j :=1 to M do begin //Вводим очередной элемент матрицы. read (A[ i, j ] ); //Записываем в файл f вещественное число A[i,j], а точнее //sizeof(real) блоков по одному байту из переменной A[i,j]. BlockWrite ( f,A[ i, j ], sizeof ( real ) ); end; write ( ’L= ’ ); readln (L ); write ( ’P= ’ ); readln (P ); //Записываем в файл 2 блока по одному байту из переменной L. BlockWrite ( f, L, sizeof ( word ) ); //Записываем в файл 2 блока по одному байту из переменной P. BlockWrite ( f, P, sizeof ( word ) ); writeln ( ’ Matrica B ’ ); for i :=1 to L do for j :=1 to P do begin read (B[ i, j ] ); //Записываем в файл sizeof(real) блоков по одному байту из //переменной B[i,j]. BlockWrite ( f,B[ i, j ], sizeof ( real ) ); end; //Закрываем файл. CloseFile ( f ); end.
Теперь напишем консольное приложение Lazarus, с помощью которого из бестипового файла считаем матрицы A, B, их размеры, после чего вычислим матрицу С как произведение А и B.
program Project1; {$mode objfpc}{$H+} uses Classes, SysUtils { you can add units after this }; var f : file; k, i, j, n,m, l, p : word; a, b, c : array [ 1.. 20, 1.. 20 ] of real; begin //Связываем файловую переменную с файлом на диске. AssignFile ( f, ’Pr_7_6. dat ’ ); //Открываем файл и устанавливаем размер блока в 1 байт. reset ( f, 1 ); //Считываем в переменную N из файла f 2 байта (sizeof(word)=2 //блоков по одному байту). BlockRead ( f,N, sizeof ( word ) ); //Считываем в переменную M из файла f 2 байта (sizeof(word)=2 //блоков по одному байту). BlockRead ( f,M, sizeof ( word ) ); for i :=1 to N do for j :=1 to M do //Считываем в переменную A[i,j] из файла f sizeof(real) байт //(sizeof(real) блоков по одному байту). BlockRead ( f,A[ i, j ], sizeof ( real ) ); //Считываем в переменную L из файла f 2 байта. BlockRead ( f, L, sizeof ( word ) ); //Считываем в переменную P из файла f 2 байта. BlockRead ( f, P, sizeof ( word ) ); for i :=1 to L do for j :=1 to P do //Считываем в переменную B[i,j] из файла f sizeof(real) байт. BlockRead ( f,B[ i, j ], sizeof ( real ) ); //Вывод матрицы A на экран. writeln ( ’ Matrica A ’ ); for i :=1 to N do begin for j :=1 to M do write (A[ i, j ] : 1 : 2, ’ ’ ); writeln; end; //Вывод матрицы B на экран. writeln ( ’ Matrica B ’ ); for i :=1 to L do begin for j :=1 to P do write (B[ i, j ] : 1 : 2, ’ ’ ); writeln end; //Проверяем, возможно ли умножение матриц, если да, if m=l then begin //то умножаем матрицу А на B for i :=1 to N do for j :=1 to P do begin c [ i, j ] : = 0; for k:=1 to M do c [ i, j ] : = c [ i, j ]+a [ i, k ] * b [ k, j ] end; //Вывод матрицы C. writeln ( ’ Matrica C=A * B ’ ); for i :=1 to N do begin for j :=1 to P do write (C[ i, j ] : 1 : 2, ’ ’ ); writeln end; //Дописываем в файл f целое число N, а точнее 2 блока по //одному байту из переменной N. BlockWrite ( f,N, sizeof ( word ) ); //Дописываем в файл f целое число P, а точнее 2 блока по //одному байту из переменной P. BlockWrite ( f, P, sizeof ( word ) ); for i :=1 to N do for j :=1 to P do //Записываем в файл f вещественное число C[i,j], а точнее //sizeof(real) блоков по одному байту из переменной C[i,j]. BlockWrite ( f, c [ i, j ], sizeof ( real ) ); end else writeln ( ’Умножение невозможно ’ ); //Закрываем файл. CloseFile ( f ); end.