Как найти максимальный компонент файла

uses crt;
var f: file of integer;
    g: file of real;
    i,c,max,sum: integer;
    n: real;
 
 begin
 assign(f,'C:1.dat');
 assign(g,'C:2.dat');
 rewrite(f);
 for i:=1 to random(11)+10 do
     begin
     c:=random(199)-99;
     write(f,c);
     end;
 writeln('Файл заполнен случайным количеством случайных чисел');
 reset(f);
 rewrite(g);
 i:=0;
 while not eof(f) do
       begin
       read(f,c);
       inc(i);
       if i=1 then max:=c
          else if c>max then max:=c;
       if c<>0 then n:=c/2 else n:=c;
       write(g,n);
       if c mod 4=0 then inc(sum,c);
       end;
writeln('Макс. элемент файла = ',max);
writeln('Сумма элементов, кратных 4 =',sum);
writeln('Исходный файл');
reset(f);
while not eof(f) do
       begin
       read(f,c);
       write(c:5);
       end;
writeln('');
writeln('Итоговый файл');
reset(g);
while not eof(g) do
       begin
       read(g,n);
       write(n:5:1);
       end;
readln;
close(f);
close(g);
end.

Ваша ошибка в том, что вы не понимаете как работает .Count() вот здесь:
string im = words.Count().ToString();
int max = im.Max();

Тут вы берете words, считаете сколько в нем элементов (скажем в массиве после разбития через .Split() у вас 10 значений, вот 10 вы и получаете), дальше вы преобразовываете это число в строку (а строка это по сути массив из символов) и дальше вы из этого «массива символов» берете максимальное.

Что бы ваш код работал, вам надо достать от туда только числа, преобразовать их в правильный формат (int) и уже потом из получившейся коллекции доставать минимальное и максимальное.


Как вариант на LINQ:

var fileText = "1199821 119982 System.Random 1116040 404655 928284 1739503 495362 49536 System.Random 2085769 95405 954 Save";
var result = fileText.Split().Select(x => new { isNum = int.TryParse(x, out int value), value }).Where(x=> x.isNum).Select(x=> x.value);
Console.WriteLine($"Min: {result.Min()} Max: {result.Max()}");

Пояснения:

  • fileText — это то, что у нас прочиталось из файла, я просто взял строку из комментария.
  • .Split() — разбиваем строку по пробелу.
  • .Select(x => new { isNum = int.TryParse(x, out int value), value }) — преобразуем каждое значение в анонимный тип, который будет содержать 2 значения:
    1. bool isNum — метод TryParse() возвращает true если ему удалось преобразовать в число и false если нет.
    2. int value — метод TryParse() через out вернет либо default(0), если значение не удалось преобразовать, либо само преобразованное число.
  • .Where(x=> x.isNum) — берем только то, что удалось преобразовать.
  • .Select(x=> x.value) — ну и берем только числа, ибо bool значения нам дальше не понадобятся.

Остается взять минимальное и максимальное. Для этого не поверите, но тоже есть свои методы — Min() и соответственно Max(), нам остается просто их вызвать, что я и делаю в данной строке: Console.WriteLine($"Min: {result.Min()} Max: {result.Max()}");

Результат: Min: 954 Max: 2085769

7.2.8 Функция filesize

Одной из проблем при копировании данных из типизированного файла в массив является невозможность корректного выделения памяти под массив. При выделении памяти заранее неизвестно, сколько элементов находится в файле. Для решения этой задачи существует функция filesize(f) (f — файловая переменная), которая возвращает значение типа longint — число реальных компонентов в открытом файле, связанном с файловой переменной f. Для пустого файла функция возвращает число 0.

Рассмотрим использование функции filesize при переписывании чисел из файла вещественных чисел в массив.

ЗАДАЧА 7.3. Переписать содержимое файла вещественных чисел в массив.

program Project1;
{$mode objfpc}{$H+}
uses Classes, SysUtils
{ you can add units after this };
//Massiw - тип данных - массив из 1000 элементов.
type
	massiw=array [ 1.. 1000 ] of real;
var
f : file of real;
//a - указатель на массив;
a :^ massiw;
n, i : word;
begin
//Связываем файловую переменную с реальным файлом на диске.
assign file ( f, ’ /home/ evgeniy/pascal /6/ pr1 / abc. dat ’ );
//Открываем файл для чтения.
reset ( f );
//Записываем в переменную n количество элементов в файле f.
n:= file size ( f );
writeln ( ’в файле  ’, n, ’  чисел ’ );
//Выделяем память для динамического массива a
//из n вещественных чисел.
getmem( a, n * sizeof ( real ) );
for i :=1 to n do
begin
//Считываем очередной элемент из файла в массив.
read ( f, a ^[ i ] );
//Вывод элемента на экран.
write ( a ^[ i ] : 1 : 3, ’   ’ )
end;
//Освобождаем память, выделенную для динамического массива.
freemem ( a, n * sizeof ( real ) );
//Закрываем файл.
close file ( f );
readln;
end.

7.2.9 Функция filepos

Функция filepos(f) возвращает значение типа longint — текущую позицию в открытом файле, связанном с файловой переменной f. Сразу после открытия файла значение filepos(f) равно 0. После прочтения последнего компонента из файла значение filepos(f) совпадает со значением filesize(f). Достижение конца файла можно проверить с помощью условия:

if filepos ( f )= file size ( f ) then
writeln ( ’достигнут конца файла ’ );

7.2.10 Процедура seek

Процедура seek(f,n) устанавливает указатель в открытом файле, связанном с файловой переменной f, на компонент с номером n (нумерация компонентов идет от 0). Затем значение компонента может быть считано.

7.2.11 Процедура truncate

Процедура truncate(f), где f — имя файловой переменной, отсекает часть открытого файла, начиная с текущего компонента, и подтягивает на его место конец файла.

Использование процедур seek и truncate рассмотрим на примере решения следующих двух несложных задач по обработке файлов.

ЗАДАЧА 7.4. В файле /home/evgeniy/pascal/6/pr1/abc.dat вещественных чисел поменять максимальный и минимальный элементы.

Рассмотрим два варианта решения этой задачи.

В первом, консольном варианте программы после считывания компонентов файла в массив происходит поиск минимального и максимального элементов массива и их индексов. Затем максимальное и минимальное значения перезаписываются в файл.

program Project1;
{$mode objfpc}{$H+}
uses Classes, SysUtils
{ you can add units after this };
var f : file of real;
i, nmax, nmin : integer;
a : array [ 0.. 200 ] of real;
max, min : real;
begin
assignfile ( f, ’ /home/ evgeniy/pascal /6/ pr1 / abc. dat ’ );
reset ( f );
//Cчитываем компоненты файла в массив а.
for i :=0 to file size ( f ) -1 do
begin
read ( f, a [ i ] );
write ( a [ i ] : 1 : 2, ’   ’ );
end;
//Начальное присваивание максимального и
//минимального элементов массива и их индексов.
max:=a [ 0 ]; nmax : = 0;
min:=a [ 0 ]; nmin : = 0;
//Основной цикл для поиска максимального b
//минимального элементов массива и их индексов.
for i :=1 to file size ( f ) -1 do
begin
if a [ i ]>max then
begin
max:=a [ i ];
nmax:= i
end;
if a [ i ]<min then
begin
min:=a [ i ];
nmin:= i
end;
end;
//Перезапись максимального и минимального значений в файл.
//Передвигаем указатель файла к максимальному элементу.
seek ( f, nmax );
//Записываем на место максимального элемента минимальный.
write ( f, min );
//Передвигаем указатель файла к минимального элементу.
seek ( f, nmin );
//Записываем на место максимального элемента минимальный.
write ( f, max );
//Обязательно закрываем файл.
closefile ( f ); readln;
end.

Вторую версию программы напишем как полноценное приложение. Использовать массив в программе не будем. Будет организован единственный цикл, в котором очередное значение считывается в переменную a и осуществляется поиск минимального и максимального элементов среди компонентов файла и их индексов. Затем происходит перезапись в файл максимального и минимального значений.

Разработку программы начнём с создания шаблона графического приложения (Проект — Создать Проект — Приложение).

На форме расположим следующие компоненты:

  1. Две метки Label1 и Label2 для подписи.
  2. Edit1 — текстовое поле редактирования, в котором будем хранить содержимое исходного файла.
  3. Edit2 — текстовое поле редактирования, в котором будет храниться файл после преобразования.
  4. OpenDialog1 — компонент для выбора имени обрабатываемого файла.
  5. Button1 — кнопка для запуска программы.
  6. Button2 — кнопка для завершения программы.

Расположим компоненты на форме примерно так, показано на рис. 7.7.

Основные свойства компонентов будем устанавливать программно при создании формы. Поэтому подпрограмма FormCreate будет такой:

procedure TForm1. FormCreate ( Sender : TObject );
begin
	Form1. Caption :=
’Обмен максимального и минимального элемента в файле ’;
	label1.Caption := ’Исходный файл ’;
	label1.Visible := False;
	label2.Caption := ’Файл после преоброзования ’;
	label2.Visible := False;
	Edit1.Text := ’ ’;
	Edit1.Visible := false;
	Edit2.Text := ’ ’;
	Edit2.Visible := false;
	OpenDialog1. Filter :=
’Файлы вещественных_чисел | *. datВсе |  файлы | *. * ’;
OpenDialog1. InitialDir := ’ /home/ evgeniy/pascal /6/ pr1 ’;
	Button1. Caption := ’Преобразовать файл ’;
	Button2. Caption := ’Выход ’;
	Button2. Visible := False;
end;

Авторы надеются, что читателям, дочитавшим книгу до этого момента, текст процедуры TForm1.FormCreate понятен без пояснений.

При запуске программы окно формы будет иметь вид, представленный на рис. 7.8.

Основные действия программа будет осуществлять при щелчке по кнопке Преобразовать файл, текст соответствующей подпрограммы с комментариями приведён ниже.

procedure TForm1. Button1Click ( Sender : TObject );
var
f : file of real;
i, nmax, nmin : integer;
a, max, min : real;
s1, s : string;
begin
//Открываем диалоговое окно для выбора файла.
if OpenDialog1. Execute then
begin
//В переменную s записываем полное имя файла.
	s := OpenDialog1. FileName;
//Связываем файловую переменную с файлом на диске.
	assignfile ( f, s );
//Открываем файл в режиме чтения.
	reset ( f );
//Делаем видимыми первую метку и поле ввода.
	label1 Visible := true;
	Edit1.Visible := true;
//В строке s1 будем формировать содержимое файла.
	S1:= ’ ’;
//Цикл для последовательного чтения всех элементов из файла
//вещественных чисел.
	for i :=0 to file size ( f ) -1 do
	begin
//Считывание очередного элемента массива в переменную a.
		read ( f, a );
		if i =0 then
//Начальное присваивание максимального и минимального значений
//и их индексов.
		begin
			max:=a; nmax:= i;
			min:=a; nmin:= i;
		end
		else
		begin
//Сравнение текущего значения с максимальным (минимальным).
			if max<a then
			begin
				max:=a;
				nmax:= i
			end;
			if min>a then
			begin
				min:=a;
				nmin:= i
			end
		end;
//Добавление очередного значения к выходной строке s1.
		s1 := s1+FloatToStr ( a)+ ’   ’;
	end;
//Вывод содержимого файла в первое текстовое поле
//редактирования.
	Edit1. Text := s1;
//Запрет изменения текстового поля.
	Edit1. ReadOnly:= true;
//Перезапись максимального и минимального значений в файл.
//Передвигаем указатель файла к максимальному элементу.
	seek ( f, nmax );
//Записываем на место максимального элемента минимальный.
	write ( f, min );
//Передвигаем указатель файла к максимальному элементу.
	seek ( f, nmin );
//Записываем на место минимального элемента максимальный.
	write ( f, max );
//Обязательно закрываем файл.
	closefile ( f );
	reset ( f );
//Делаем видимыми вторую метку и поле ввода.
	label2.Visible := true;
	Edit2.Visible := true;
//Считываем данные из преобразованного файла
	s1 := ’ ’;
	for i :=0 to file size ( f ) -1 do
	begin
		read ( f, a );
//Добавление очередного значения из преобразованного файла
//к выходной строке s1.
	s1 := s1+FloatToStr ( a)+ ’   ’;
end;
//Вывод содержимого преобразованного файла во второе текстовое
//поле редактирования.
	Edit2. Text := s1;
//Запрет изменения текстового поля.
	Edit2. ReadOnly:= true;
//Делаем видимой вторую кнопку.
	Button2. Visible :=True;
	CloseFile ( f );
	end;
end;

При щелчке по кнопке Выход программа должна завершать свою работу. Поэтому текст обработчика щелчка по кнопке будет очень простым.

procedure TForm_File. Button2Click ( Sender : TObject );
begin
	Close;
end;

При щелчке по кнопке Преобразовать файл появляется окно выбора файла, подобное представленному на рис. 7.5. После выбора файла в нём происходит обмен максимального и минимального элементов и вывод содержимого файла до и после преобразования (см. рис. 7.9). При щелчке по кнопке Выход работа программы завершается.

При решении задачи 7.4 была использована процедура seek, с помощью которой стало возможным изменение данных в файле непосредственно на диске, без считывания в массив.

ЗАДАЧА 7.5. Задан файл вещественных чисел abc.dat. Удалить из него максимальный и минимальный элементы.

Рассмотрим две программы, решающие эту задачу. Программы будем создавать как консольные приложения в Lazarus. Алгоритм первой состоит в следующем: считываем компоненты файла в массив, в котором находим максимальный и минимальный элементы и их номера. Открываем файл для записи и вносим в него все элементы, за исключением максимального и минимального.

program Project1;
{$mode objfpc}{$H+}
uses Classes, SysUtils
{ you can add units after this };
var
f : file of real;
max, min : real;
j, i, nmax, nmin : integer;
a : array [ 1.. 300 ] of real;
begin
assignfile ( f, ’ /home/ evgeniy/pascal /6/ pr1 / abc. dat ’ );
reset ( f );
//Запоминаем в переменной j количество компонентов в файле.
j := filesize ( f );
//Считываем компоненты файла в массив а.
for i :=1 to j do read ( f, a [ i ] );
for i :=1 to j do write ( a [ i ] : 1 : 2, ’   ’ );
writeln;
closefile ( f );
//Открываем файл для записи.
rewrite ( f );
//Начальное присваивание максимального и
//минимального элементов массива и их индексов.
max:=a [ 1 ]; min:=a [ 1 ];
nmax : = 1; nmin : = 1;
//Основной цикл для поиска максимального и
//минимального элементов массива и их индексов.
for i :=2 to j do
begin
	if a [ i ]>max then
	begin
		max:=a [ i ];
		nmax:= i
	end;
	if a [ i ]<min then
	begin
		min:=a [ i ];
		nmin:= i;
	end;
end;
//Перезапись элементов массива в файл, за исключением
//элементов с номерами nmax и nmin.
writeln ( ’Преобразованный_файл ’ );
for i :=1 to j do
	if ( i <>nmax) and ( i <>nmin ) then
	begin
		write ( f, a [ i ] );
//Вывод записанного в файл элемента на экран.
		write ( a [ i ] : 1 : 2, ’   ’ );
	end;
closefile ( f );
readln;
end.

Вторая программа работает следующим образом. Находим максимальный и минимальный элементы и их номера среди компонентов файла. Если nmin > nmax, то меняем содержимое переменных nmin и nmax. Далее элементы, лежащие между минимальным и максимальным (формально между элементами с номерами nmin и nmax), сдвигаем на один порядок влево. Тем самым мы убираем элемент с номером nmin. После этого все компоненты, лежащие после элемента с номером nmax, сдвинем на два порядка влево. Этим мы сотрём максимальный элемент. Затем два последних компонента в файле необходимо удалить.

program Project1;
{$mode objfpc}{$H+}
uses Classes, SysUtils
{ you can add units after this };
var
f : file of real;
a : real;
max, min : real;
i, nmax, nmin : integer;
begin
assignfile ( f, ’ /home/ evgeniy/pascal /6/ pr1 / abc. dat ’ );
reset ( f );
//Поиск максимального и минимального элементов в файле и их
//индексов.
writeln ( ’Исходный файл ’ );
for i :=0 to filesize ( f ) -1 do
begin
	read ( f, a );
	write ( a : 1 : 2, ’   ’ );
	if i =0 then
	begin
		max:=a;
		nmax:= i;
		min:=a;
		nmin:= i
	end
	else
	begin
		if a>max then
		begin
			max:=a;
			nmax:= i;
		end;
		if a<min then
		begin
			min:=a;
			nmin:= i;
		end
	end
end;
writeln;
//Сравниваем nmin и nmax.
if nmax<nmin then
begin
	i :=nmax;
	nmax:=nmin;
	nmin:= i
end;
//Сдвигаем элементы, лежащие между компонентами
//с номерами nmin и nmax, на один влево.
for i :=nmin to nmax-2 do
begin
	seek ( f, i +1);
	read ( f, a );
	seek ( f, i );
	write ( f, a );
end;
//Сдвигаем элементы, лежащие после компонента
//с номером nmax, на два влево.
for i :=nmax to filesize ( f ) -3 do
begin
	seek ( f, i +1);
	read ( f, a );
	write ( a : 1 : 2 );
	seek ( f, i - 1);
	write ( f, a );
	write ( a : 1 : 2 );
end;
//Отрезаем последние два компонента.
truncate ( f );
closefile ( f );
reset ( f );
//Вывод преобразованного файла.
writeln ( ’Преобразованный_файл ’ );
for i :=1 to file s i z e ( f ) do
begin
	read ( f, a );
//Вывод записанного в файл элемента на экран.
	write ( a : 1 : 2, ’ _ ’ );
	end;
closefile ( f );
readln;
end.

В результате работы программы из файла вещественных чисел удалено наибольшее и наименьшее число.

Кроме типизированных файлов широкое применение при обработке числовых данных получили бестиповые файлы.

На занятии будет рассмотрена работа с типизированными файлами в Паскале и разобраны конкретные решенные примеры задач

Содержание:

  • Типизированные файлы в Паскаль
    • Описание:
    • Открытие файла
    • Чтение из текстового файла
    • Запись в текстовый файл
    • Процедуры работы с файлом
  • Символьные и строковые файлы (типизированные)
    • Последовательный доступ
  • Числовые файлы (типизированные)
    • Последовательный доступ
    • Прямой доступ

Типизированные файлы в Паскаль

Типизированный файл может быть описан как файл любого типа (кроме типа file). Описывают подобный файл словосочетанием file of с последующим указанием типа компонентов файла.

Файл с типом, т.е. типизированный файл состоит из последовательности записей (компонент), имеющих одинаковую длину и одинаковый внутренний формат.

Записи (компоненты) следуют непрерывно друг за другом. К данным такого файла можно обращаться как последовательно, так и выборочно — с прямым доступом.

При последовательном доступе записи (компоненты) размещаются в файле последовательно в порядке их поступления.

При прямом доступе данные размещаются в определенных областях, имеющих последовательную нумерацию, и начинаются с нуля. Движение по записям осуществляется посредством так называемого указателя, перемещение которого осуществляется при помощи процедур (seek pascal). После открытия файла указатель (номер текущей компоненты) стоит в самом начале, т.е. на нулевом компоненте. После каждого прочтения или записи указатель сдвигается к следующему компоненту.

Описание:

  1. var
       f1: file of char;
       f2: file of integer;
  2. type t = file of real;
    var f: t;
  3. type st = record
            a: string[10];
            b: integer;
    end;
    var dan: file of st;
    </ol>

Открытие файла

Чтение из текстового файла

Read (f, список переменных);

Запись в текстовый файл

Write (f, список переменных);
WriteLn (f, список переменных);

Процедуры работы с файлом

Смещение указателя файла:
Процедура seek в Паскаль смещает указатель файла f на n-ную позицию. Используется при прямом доступе к файлу:

Процедура возвращающая размер файла:

функция проверки конца файла:

Символьные и строковые файлы (типизированные)

Последовательный доступ

Пример: (последовательный доступ) Посимвольно считывать данные из файла и выводить их на экран – каждый символ с новой строки

1
2
3
4
5
6
7
8
9
10
11
12
13
var
    f: file of char;
    c: char;
begin
    assign (f, 'c:file.txt');
    reset (f);
    while not eof (f) do begin {пока не достигнут конец файла}
        read (f, c);
        writeln (c);
    end;
close (f);
readln
end.

Пример: (последовательный доступ) Записывать в файл определенное кол-во символов (символы и их количество вводит пользователь)

Показать решение:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var
    f: file of char;
    c: char;
    i, n: byte;
begin
    assign (f, 'c:file.txt');
    rewrite (f);
 
    write ('Количество символов: ');
    readln (n);
 
    for i:=1 to n do begin
        write ('Введите символ: ');
        readln (c);
        write (f, c);
    end;
close (f);
end.

Пример: (последовательный доступ) Дан символьный файл, содержащий, по крайней мере, один символ пробела. Удалить все его элементы, расположенные после первого символа пробела, включая и этот пробел.

* Предварительно следует программно записать в исходный файл символы

Показать решение:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var
 F_in,F_out: File of Char;
 a,C:Char;
 i:integer;
begin
  Assign(F_in,'c:text.txt');
  ReWrite(F_in);
  write('Какие символы записываем в исходный файл?');
  for i:=1 to 5 do
  begin
       read(a);
       write(F_in,a);
  end;
 
  Reset(F_in);
  Assign(F_out,'c:text1.txt');
  ReWrite(F_out);
 
  Read(F_in,C);
  while (not eof(F_in)) and (C<>' ') do
   begin
    Write(F_out,C);
    Read(F_in,C);
   end;
   Close(F_out);
   Close(F_in);
   Erase(F_in);
   Rename(F_out,'c:text.txt');
end.

pascal file string1. Дан символьный файл, содержащий, по крайней мере, один символ пробела. Удалить все его элементы, расположенные после последнего символа пробела, включая и этот пробел.

Пример: Дан строковый файл. Создать новый строковый файл, содержащий все строки исходного файла наименьшей длины (в том же порядке).

Пример:

Введите строки исходного файла:
первая строка
вторая строка длинная
третья строка
строка
пятая строка

результирующий файл:
строка

Показать решение:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
var
 S: String;
 F_in,F_out: file of string;
 MinLen: integer;
  i:integer;
begin
  Assign(F_in,'c:text.txt');
  Rewrite(F_in);
   write('Введите строки исходного файла:');
  for i:=1 to 5 do
  begin
       read(s);
       write(F_in,s);
  end;
  Reset(F_in);
  Assign(F_out,'c:text1.txt');
  Rewrite(F_out);
 
 MinLen:=-1;
 
 
 while (not eof(F_in)) do
  begin
   Read(F_in,S);
   if (Length(S)<MinLen) or (MinLen=-1) then
   MinLen:=Length(S);
  end;
 
 Close(F_in);
 Reset(F_in);
 
 
 while (not eof(F_in)) do
  begin
   Read(F_in,S);
   if Length(S)=MinLen then
   Write(F_out,S);
  end;
 
 Close(F_in);
 Close(F_out);
end.

pascal file string2. Дан строковый файл. Создать новый строковый файл, содержащий все строки исходного файла наибольшей длины (в обратном порядке).

Числовые файлы (типизированные)

Последовательный доступ

Пример: Дан файл целых чисел. Создать новый файл, содержащий те же элементы, что и исходный файл, но в обратном порядке.
Внимание: числа в исходном файле должны быть записаны программно! Иначе считывание будет происходить неверно.

Показать решение:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
var
 S,s1:String;
 F_in,F_out: File of Integer;
 k,i:integer;
 a:array[1..100] of integer;
begin
  S:='c:text.txt';
  Assign(F_in,S);
  rewrite(F_in);
  for i:=1 to 10 do
      write(F_in,i); {записываем в исходный файл числа}
  close(F_in);
  Reset(F_in);
  S1:= 'c:text1.txt';
  Assign(F_out,S1);
  ReWrite(F_out);
 
  k:=1;
  writeln('считанные из файла числа:');
   while (not eof(F_in)) do
   begin
    Read(F_in,a[k]);
    writeln(a[k]);
    k:=k+1;
   end;
  Close(F_in);
writeln('записываемые числа в файл');
 for i:=k-1 downto 1 do
   begin
    Write(a[i]:3);
    Write(F_out,a[i]);
   end;
 
 Close(F_out);
end.

pascal file 2. Дан файл вещественных чисел. Создать два новых файла, первый из которых содержит элементы исходного файла с нечетными номерами (1,3,…), а второй — с четными (2,4,…).
Внимание: числа в исходном файле должны быть записаны программно! Иначе считывание будет происходить неверно.

pascal file 3. Дан файл вещественных чисел. Найти сумму его элементов с четными номерами.
Внимание: числа в исходном файле должны быть записаны программно! Иначе считывание будет происходить неверно.

Пример: Дан файл вещественных чисел. Найти его первый локальный минимум (локальным минимумом называется элемент, который меньше своих соседей).

* Для решения не использовать массивы.

Показать решение:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
var
 S:String;
 F_in: File of Real;
 El2,El1,El:Real;
 i:integer;
 a:real;
 
begin
  Assign(F_in,'c:text.txt');
  rewrite(F_in);
  writeln ('Введите вещественные числа');
  for i:=1 to 5 do begin
      read(a);
      write(F_in,a); {заполняем исходный файл числами}
  end;
  close(F_in);
  Reset(F_in); 
  Read(F_in,El);
  Read(F_in,El1);
  Read(F_in,El2);
  writeln('Результат =');
  if (El1<El)and(El1<El2) then Writeln('s',El1:4:2)
  else
   begin
    while (not eof(F_in)) and not((El>El1) and (El1<El2)) do
     begin
      El:=El1;
      El1:=El2;
      Read(F_in,El2);
     end;
    if (El>El1) and (El1<El2) then
       Writeln(El1:4:2)
    else if eof(F_in) and (El1>El) then
       Writeln(El:4:2);
   end;
  Close(F_in);
end.

pascal file 4. Дан файл вещественных чисел. Найти его последний локальный максимум (локальным максимумом называется элемент, который больше своих соседей).

Пример:
Дан файл вещественных чисел. Заменить в нем все элементы на их квадраты.

* Перед выполнением программы необходимо узнать в какой папке сохраняются файлы, созданные программой ABC.

Показать решение:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var
 S:String;
 F_in,F_temp: File of Real;
 temp:Real;
begin
    Assign(F_in,'text.txt');
  Reset(F_in);
  Assign(F_temp,'text1.txt');
  ReWrite(F_temp);
  while (not eof(F_in)) do
   begin
    Read(F_in,temp);
    temp:=sqr(temp);
    Write(F_temp,temp);
   end;
 
  Close(F_in);
  Close(F_temp);
  Erase(F_in); {удаление файла}
  Rename(F_temp,'text.txt'); {Переименование файла}
end.

Здесь следует обратить внимание на то, что файлы, скорее всего, сохраняются в папке : C:Usersимя пользователяAppDataLocalVirtualStore

pascal file 5. Дан файл вещественных чисел. Поменять в нем местами минимальный и максимальный элементы.
Алгоритм:

  • найти в исходном файле минимальный элемент, сохранить его и его индекс в переменные;
  • найти в исходном файле максимальный элемент, сохранить его и его индекс в переменные;
  • создать временный файл и переписать туда элементы исходного файла кроме тех позиций, на которых должны стоять максимальный и минимальный элементы; в указанные позиции разместить элементы, поменяв их местами.
  • Прямой доступ

    Пример: (прямой доступ) В файле заменить символ определенной позиции. Позицию символа и сам новый символ запросить у пользователя. Использовать процедуру seek Паскаль

    Показать решение:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    var
        f: file of char;
        c: char;
        n: integer;
    begin
        assign (f, 'c:text.txt');
        reset (f);
        write('Введите позицию: ');
        readln(n);
        seek(f,n);
        write('Введите новый символ: ');
        readln(c);
        write(f,c);
        close(f);
     end.

    Задание: (прямой доступ) В файле заменить символы с четной позицией на восклицательные знаки (‘!’). Использовать процедуру seek

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    347

    Вданной главе будут рассмотрены возможности языка FreePascal для работы с файлами. По ходу изложения материала читатель также познакомится с компонентами Lazarus, предназначенными для выбора файла.

    Начнем со знакомства с типами файлов.

    7.1 Типы файлов

    Ввод данных с клавиатуры удобен при обработке небольших объемов информации. В случае обработки массивов, состоящих из сотен элементов, использовать ввод данных с клавиатуры нерационально. В подобных случаях данные удобно хранить в файлах, программа будет их считывать, обрабатывать, выводить результаты на экран или в файл. Рассмотрим, как это можно сделать.

    C точки зрения программиста, все файлы можно разделить на три класса:

    типизированные;

    бестиповые;

    текстовые.

    Файлы, состоящие из компонентов одного типа (целые, вещественные, массивы и т.д.), число которых заранее не определено и может быть любым, называются типизированными. Они заканчиваются специальным символом «конец файла», хранятся в двоичном виде, содержимое подобных файлов нельзя просмотреть обычным текстовым редактором, для просмотра подобных файлов нужно писать специальную программу.

    В бестиповых файлах информация считывается и записывается блоками определенного размера. В подобных файлах хранятся данные любого вида и структуры.

    Текстовые файлы состоят из любых символов. При записи информации в текстовый файл все данные преобразуются к символьному типу, в котором и хранятся. Просмотреть данные в подобном файле можно с помощью любого текстового редактора. Информация в текстовом файле хранится построчно. В конце каждой строки хранится специальный символ «конец строки». Конец самого файла обозначается символом «конец файла».

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    348

    Для работы с файлами в программе следует описать файловую переменную. Для работы с текстовым файлом файловая переменная

    (например, f) описывается с помощью служебного слова text. var f:text;

    Для описания типизированных75 файлов можно описать файло-

    вую переменную следующим образом: var f:file of тип; 76

    Бестиповый файл описывается с помощью служебного слова file.

    Рассмотрим несколько примеров описания файловых перемен-

    ных. type

    massiv=array[1..25]of real; ff=file of real;

    var

    a:text; {Файловая переменная a для работы с текстовым файлом}

    b:ff; {Файловая переменная f для работы с файлом вещественных чисел}

    c:file of integer; {Файловая переменная c для работы с файлом целых чисел}

    d:file of massiv; {Файловая переменная d предназначена для работы с типизированным файлом, элементами которого являются массивы из 25 вещественных чисел. }

    Рассмотрим последовательно работу с файлами каждого типа.

    7.2 Работа с типизированными файлами

    Знакомство с методами обработки типизированных файлов начнем с подпрограмм, которые являются общими для всех типов файлов.

    7.2.1 Процедура AssignFile

    Для начала работы с файлом необходимо связать файловую переменную в программе с файлом на диске. Для этого используется про-

    75 Типизированные файлы иногда называют компонентными.

    76 Здесь f — имя файловой переменной, тип — тип компонентов файла, это могут быть как стандартные типы данных (например, real, integer и т.д.), так и типы, определенные пользователем.

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    349

    цедура AssignFile(f,s), где f – имя файловой переменной, а s

    полное имя файла на диске (файл должен находиться в текущем каталоге при условии, что к нему специально не указывается путь).

    Рассмотрим примеры использования AssignFile для различ-

    ных операционных систем. var

    f:file of real; begin

    //Пример процедуры assign для ОС Windows. AssignFile (f, ‘d:tptmpabc.dat’); //Пример процедуры assign для ОС Linux. AssignFile(f,’/home/pascal/6/pr1/abc.dat’);

    7.2.2 Процедуры reset, rewrite

    После установления связи между файловой переменной и именем файла на диске нужно открыть файл, воспользовавшись процедурами reset или rewrite.

    Процедура reset(f) (где f – имя файловой переменной) открывает файл, связанный с файловой переменной f, после чего ста-

    новится доступным для чтения первый элемент, хранящийся в файле. Далее можно выполнять чтение и запись данных из файла.

    Процедура rewrite(f) создает пустой файл (месторасположение файла на диске определяется процедурой AssignFile) для по-

    следующей записи в него данных.

    Внимание!!! Если файл, связанный с файловой переменной f, существовал на диске, то вся информация в нем уничтожается.

    7.2.3 Процедура СloseFile

    Процедура CloseFile(f), где f – имя файловой переменной, закрывает файл, который ранее был открыт процедурами rewrite, reset.

    Процедуру CloseFile(f) следует обязательно использовать

    при закрытии файла, в который происходила запись данных.

    Дело в том, что процедуры записи в файл не обращаются непосредственно к диску, они пишут информацию в специальный участок памяти, называемый буфером файла. После того как буфер заполнится, вся информация из него переносится в файл. При выполнении

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    350

    процедуры closefile сначала происходит запись буфера файла на

    диск, и только потом файл закрывается. Если его не закрыть вручную, то закрытие произойдет автоматически при завершении работы программы. Однако при автоматическом закрытии файла информация из буфера файла не переносится на диск, и как следствие часть информации может пропасть.

    Внимание!!! После записи информации в файл его обязательно закрывать с помощью процедуры CloseFile. Однако при чтении дан-

    ных из файла нет необходимости в обязательном его закрытии.

    7.2.4 Процедура rename

    Переименование файла, связанного с файловой переменной f,

    осуществляется в то время, когда он закрыт, при помощи процедуры rename(f,s), где f – файловая переменная, s – новое имя файла

    (строковая переменная).

    7.2.5 Процедура erase

    Удаление файла, связанного с переменной f, выполняется посредством процедуры erase(f), в которой f также является именем

    файловой переменной. Для корректного выполнения этой операции файл должен быть закрыт.

    7.2.6 Функция eof

    Функция eof(f) (end of file), где f – имя файловой переменной, принимает значение «истина» (true), если достигнут конец файла, иначе – «ложь» (false). С помощью этой функции можно проверять,

    достигнут ли конец файла и можно ли считывать очередную порцию данных.

    7.2.7 Чтение и запись данных в файл

    Для записи данных в файл можно использовать процедуру write: write(f, x1, x2,…, xn);

    write(f, x);

    здесь

    f — имя файловой переменной,

    x, x1, x2, …, xn — имена переменных, значения из которых записываются в файл.

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    351

    Тип компонентов файла обязательно должен совпадать с типом переменных. При выполнении процедуры write значения x1, x2, …,

    xn последовательно записываются в файл (начиная с текущей позиции), связанный с файловой переменной f.

    Для чтения информации из файла, связанного с файловой переменной f, можно воспользоваться процедурой read:

    read(f, x1, x2, x3,…, xn); read(f, x);

    здесь

    f — имя файловой переменной,

    x, x1, x2, …, xn — имена переменных, в которые считываются

    значения из файла.

    Процедура read последовательно считывает компоненты из файла, связанного с файловой переменной f, в переменные x1, x2, …, xn. При считывании очередного значения доступным становится следующее. Следует помнить, что процедура read не проверяет, достигнут ли конец файла. За этим нужно следить с помощью функции eof.

    Для того чтобы записать данные в файл, необходимо выполнить следующее:

    1.Описать файловую переменную.

    2.Связать ее с физическим файлом (процедура AssignFile).

    3.Открыть файл для записи (процедура rewrite).

    4.Записать данные в файл (процедура write).

    5.Обязательно закрыть файл (процедура CloseFile). Рассмотрим создание компонентного файла на примере решения

    следующей несложной задачи.

    ЗАДАЧА 7.1. Создать типизированный файл и записать туда n вещественных чисел.

    Алгоритм решения задачи состоит из следующих этапов:

    1.Открыть файл для записи с помощью оператора rewrite.

    2.Ввести значение n.

    3.В цикле (при i меняющемся от 1 до n) вводим очередное ве-

    щественное число a, которое сразу же записываем в файл с помощью процедуры write.

    4. Закрываем файл с помощью процедуры closefile.

    Текст консольного приложения, предназначенного для решения

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus 352

    данной задачи приведен ниже. program pr1;

    {$mode objfpc}{$H+} uses

    Classes, SysUtils

    { you can add units after this }; var f:file of real;

    i,n:integer;

    a:real; begin

    //Связываем файловую переменную с файлом //на диске. AssignFile(f,’/home/pascal/6/pr1/abc.dat’); //Открываем пустой файл для записи.

    rewrite(f);

    //Определяем количество элементов в файле. write(‘n=’);

    readln(n);

    //В цикле вводим очередной элемент и //записываем его в файл.

    for i:=1 to n do begin

    write(‘a=’);

    readln(a);

    write(f,a);

    end; //Закрываем файл.

    //При записи данных в файл это делать //обязательно.

    CloseFile(f)

    end.

    Рассмотрим следующую задачу

    ЗАДАЧА 7.2. В папке /home/evgeniy/pascal/6/pr2/ находятся файлы вещественных чисел с расширением dat. В выбранном пользователем файле удалить все числа, меньшие среднего арифметического, расположенные между максимальным и минимальным элементами.

    В задаче предполагается выбор пользователем файла для обра-

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    353

    ботки. Для этого понадобится специальный компонент для выбора файла. Решение задачи 7.2 начнем со знакомства с компонентом OpenDialog . Это компонент предназначен для создания стан-

    дартного диалогового окна выбора файла и расположен первым на странице Dialogs (см. рис. 7.1).

    Рисунок 7.1: Компоненты страницы Dialogs

    Среди основных свойств этого компонента можно выделить: FileName: String — полное имя выбранного пользователем

    файла;

    Filter: String — строка, которая возвращает фильтры отбираемых файлов; это свойство можно задать с помощью редактора фильтров или с помощью специальной строки. Для вызова редактора необходи-

    мо щелкнуть по кнопке , после чего появится окно редактора фильтров (см. рис. 7.2).

    Окно редактора фильтров состоит из двух столбцов: Filter name — имя фильтра (например, все файлы, программы на Паскале); Filter — соответствующая имени фильтра маска (фильтру «все файлы» соответствует маска «*.*», фильтру «программы на

    Рисунок 7.2: Редактор фильтров

    Паскале» — маска «*.pas».

    Специальная строка состоит из последовательных имен фильтров и соответствующих им масок, разделенных символом «|». Специальная строка, соответствующая фильтру, представленному на рис.7.2,

    имеет вид.

    OpenDialog1.Filter:=

    ‘Программы на C|*.c|Программы на Паскале|*.pas|Все файлы|*.*’;

    Первый фильтр в списке является фильтром по умолчанию. В примере на рис. 7.2 фильтр по умолчанию — «Программы на C». InitialDialog — имя каталога по умолчанию для выбора файлов.

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    354

    DefaultExt — расширение, добавляемое к имени файла по

    умолчанию, если пользователь при ручном вводе имени файла не указал расширение.

    Основным методом для компонента OpenDialog — является логическая функция Execute, которая приводит к открытию диалого-

    вого окна в соответствии со свойствами компонента. Функция Execute возвращает true, если пользователь выбрал файл каким-

    либо методом. Если пользователь нажал в диалоговом окне Отмена (Cancel), то метод Execute возвращает false. Имя выбранного файла возвращается в свойстве FileName.

    Таким образом, вызов диалогового окна можно записать так.

    Var s:String; begin

    if OpenDialog1.Execute then s:=OPenDialog1.FileName;

    {Имя файла, выбранного пользователем, хранится в переменной s}.

    end;

    Разобравшись с компонентом для выбора файла, вернемся к задаче 7.2. Можно выделить следующие этапы ее решения.

    1.Выбор файла.

    2.Чтение данных из файла в массив вещественных чисел.

    3.В массиве вещественных чисел удалить все числа, меньшие среднего арифметического, расположенные между максимальным и минимальным элементами.

    4.Запись преобразованного массива в файл.

    Разработку программы начнем с создания графического приложения (Проект — Создать Проект — Приложение).

    На форме расположим следующие компоненты:

    1.Две метки Label1 и Label2 для подписи.

    2.Memo1 — компонент, в котором будем хранить содержимое исходного файла.

    3.Memo2 — компонент, в котором хранится преобразованный

    файл.

    4. OpenDialog1 — компонент для выбора имени обрабатываемого файла.

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    355

    5.Buttom1 — кнопка для запуска программы.

    6.Buttom2 — кнопка для завершения программы.

    Установим следующие свойства формы и компонентов (см. табл. 7.1 — 7.8).

    Таблица 7.1: Свойства формы

    Свойство

    Caption

    Name

    Значение

    Преобразование файла

    Form_File

    Таблица 7.2: Свойства метки label1

    Свойство

    Caption

    Visible

    Значение

    Файл до преобразования

    False

    Таблица 7.3: Свойства метки label2

    Свойство

    Caption

    Visible

    Значение

    Файл после преобразования

    False

    Таблица 7.4: Свойства компонента Memo1

    Свойство

    Lines

    Visible

    Значение

    »

    False

    Таблица 7.5: Свойства компонента Memo2

    Свойство

    Lines

    Visible

    Значение

    »

    False

    Таблица 7.6: Свойства компонента OpenDialog1

    Свойство

    InitDialog

    DefaultExt

    Значение

    /home/evgeniy/pascal/6/pr2/

    dat

    Таблица 7.7: Свойства кнопки Button1

    Свойство

    Caption

    Name

    Visible

    Значение

    Преобразовать файл

    Button_File

    True

    Таблица 7.8: Свойства кнопки Button2

    Свойство

    Caption

    Name

    Visible

    Значение

    Закрыть

    Button_Close

    False

    Расположим компоненты на форме подобно показанному на рис. 7.3. При запуске программы на выполнение все компоненты, кроме кнопки «Преобразовать файл», будут невидимыми, свойство

    Visible установлено в False. Окно приложения при запуске пока-

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    356

    зано на рис. 7.4.

    Рисунок 7.3: Форма с расположенными на ней компонентами

    Рисунок 7.4: Приложение при запуске

    Проектирование интерфейса приложения завершено. Осталось написать тексты обработчиков событий.

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    357

    При создании формы установим свойство Filter компонента

    OpenDialog1. Поэтому подпрограмма FormCreate будет такой. procedure TForm_File.FormCreate(Sender: TObject);

    begin OpenDialog1.Filter:=

    ‘Файлы вещественных чисел|*.dat|Все файлы|*.*’; end;

    При щелчке по кнопке «Преобразовать файл» должно происходить следующее:

    1.Выбор файла из диалогового окна.

    2.Считывание данных из файла в массив вещественных чисел.

    3.Установка свойства Visible в True у компонентов

    label1 и Memo1.

    4.Вывод содержимого массива в Memo1.

    5.Преобразование массива.

    6.Запись преобразованного массива в файл.

    7.Установка свойства Visible в True у компонентов

    label2 и Memo2.

    8.Вывод преобразованного массива в Memo2.

    9.Установка свойства Visible в True у компонента

    Button_Close.

    Ниже приведен текст обработки события Button_FileClick с

    подробными комментариями.

    procedure Tform_File.Button_FileClick(

    Sender: TObject);

    var

    f:file of real; s:string; a:array[1..100] of real; nmax,nmin,i,j,n:integer; sum,max,min:real;

    begin

    //Открываем диалоговое окно для выбора файла. if opendialog1.execute then

    begin

    //Имя выбранного файла считываем в s. s:=OpenDialog1.FileName;

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    358

    //Связываем файловую переменную //с файлом на диске.

    AssignFile(f,s); //Открываем файл для чтения.

    Reset(f);

    //Обнуляем счетчик элементов массива. n:=0;

    //Делаем видимыми первую //метку и компонент Memo1.

    label1.Visible:=true;

    Memo1.Visible:=true; //Переменная sum служит для //нахождения суммы компонентов файла.

    Sum:=0;

    //Пока не встретится конец файла, //будем считывать очередной компонент.

    while not eof(f) do begin

    //Индекс массива увеличиваем на 1. n:=n+1;

    //Считываем очередной элемент из //файла в массив.

    read(f,a[n]);

    //Накапливаем сумму элементов массива. sum:=sum+a[n];

    //Выводим очередной элемент в Memo1. Memo1.Lines.Add(FloatToStr(a[n]));

    end; //Закрываем файл.

    CloseFile(f);

    //Находим среднее арифметическое //элементов массива.

    sum:=sum/n;

    //Поиск максимального, минимального //элементов в массиве и их индексов.

    max:=a[1];min:=max;nmin:=1;nmax:=1; for i:=2 to n do

    begin

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    359

    if a[i]>max then begin

    max:=a[i]; nmax:=i; end;

    if a[i]<min then begin

    min:=a[i]; nmin:=i; end;

    end;

    //Если максимальный элемент расположен //раньше минимального, то меняем местами //nmin и nmax.

    if nmax<nmin then begin

    i:=nmax;

    nmax:=nmin;

    nmin:=i;

    end;

    i:=nmin+1;

    //Цикл для удаления элементов, //расположенных между максимальным // и минимальным.

    while(i<nmax) do begin

    //Если очередной элемент массива //меньше среднего арифметического, то

    if a[i]<sum then begin

    //удаляем его.

    for j:=i to n-1 do a[j]:=a[j+1]; //После удаления уменьшаем количество //элементов и номер максимального на 1.

    n:=n-1; nmax:=nmax-1;

    end

    //Если очередной элемент массива //больше среднего арифметического, то

    else

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    360

    //переходим к следующему. i:=i+1;

    end;

    //Делаем видимыми вторую метку //и компонент Memo2.

    label2.Visible:=true;

    Memo2.Visible:=true; rewrite(f);//Открываем файл для записи.

    //Преобразованный массив записываем //в файл и выводим в компонент Memo2.

    for i:=1 to n do begin

    write(f,a[i]);

    Memo2.Lines.Add(FloatToStr(a[i]));

    end;

    //Закрываем файл, делаем видимой вторую кнопку. CloseFile(f);

    Button_Close.Visible:=True;

    end;

    end;

    При щелчке по кнопке «Закрыть» программа должна завершать свою работу. Поэтому текст обработчика щелчка по кнопке будет

    очень простым.

    procedure Tform_File.Button_CloseClick( Sender: TObject);

    begin Close;

    end;

    Проверим функционирование созданного приложения. После запуска программы появляется окно, подобное представленному на рис. 7.4. Щелкаем по кнопке Преобразовать файл, появляется

    окно, подобное представленному на рис. 7.5. После щелчка по кнопке OK окно программы становится похожим на представленное на рис. 7.6. Щелчок по кнопке Закрыть завершает работу приложения. Зада-

    ча 7.2 решена.

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    361

    В связи с тем что файл —

    последовательная структу-

    ра данных, при

    решении

    задачи пришлось содержи-

    мое файла целиком считы-

    вать

    в массив, проводить

    обработку данных в мас-

    сиве и только затем запи-

    сывать в файл. Такой ме-

    тод не всегда удобен. Кро-

    ме того,

    при считывании

    данных из файла в массив

    мы ограничены описанием

    статического

    массива.

    Если

    в

    файле

    окажется

    Рисунок 7.5: Диалоговое окно выбора

    больше

    элементов,

    чем

    при

    описании

    статиче-

    файла

    ского

    массива (в нашем

    случае >100), то программа не будет правильно работать.

    Рисунок 7.6: Окно с результатами работы программы

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    362

    Использование динамического массива не решит эту проблему, потому что неизвестно количество элементов в массиве. Для решения этой программы в языке FreePascal реализован прямой доступ к файлу с помощью рассмотренных далее подпрограмм работы с файлами.

    Одной из проблем при копировании данных из типизированного файла в массив является невозможность корректного выделения памяти под массив. При выделении памяти заранее неизвестно, сколько элементов находится в файле. Для решения этой задачи существует функция filesize(f)(f– файловая переменная), которая возвра-

    щает значение типа longint — число реальных компонентов в открытом файле, связанном с файловой переменной f. Для пустого файла функция возвращает число 0.

    Применим функцию filesize для переписывания вещественных чисел из файла в массив.

    ЗАДАЧА 7.3. Переписать содержимое файла вещественных чисел в массив.

    program Project1; {$mode objfpc}{$H+} uses Classes, SysUtils

    { you can add units after this }; //Massiw — тип данных — массив

    //из 1000 элементов. type

    massiw=array[1..1000] of real;

    var

    f:file of real;

    //a -указатель на массив; a:^massiw;

    n,i:word; begin

    //Связываем файловую переменную //реальным файлом на диске.

    assignfile(f,’/home/pascal/6/pr1/abc.dat’); //Открываем файл для чтения

    reset(f);

    //Записываем в переменную n — количество

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    363

    //элементов в файле f. n:=filesize(f);

    writeln(‘в файле ‘,n, ‘ чисел’);

    //Выделяем память для динамического массива a //из n вещественных чисел. getmem(a,n*sizeof(real));

    for i:=1 to n do begin

    //Считываем очередной элемент из файла //в массив.

    read(f,a^[i]);

    //Вывод элемента на экран. write(a^[i]:1:3, ‘ ‘) end;

    //Освобождаем память, выделенную //для динамического массива. freemem(a,n*sizeof(real)); //Закрываем файл.

    closefile(f);

    readln;

    end.

    Функция filepos(f) возвращает значение типа longint

    текущую позицию в открытом файле, связанном с файловой переменной f. Сразу после открытия файла значение filepos(f) равно 0.

    После прочтения последнего компонента из файла значение filepos(f) совпадает со значением filesize(f). Достижение

    конца файла можно проверить с помощью условия: if filepos(f)=filesize(f) then

    writeln(‘достигнут конца файла’);

    Процедура seek(f,n) устанавливает указатель в открытом файле, связанном с файловой переменной f, на компонент с номером n (нумерация компонентов идет от 0). Затем значение компонента мо-

    жет быть считано.

    Процедура truncate(f), где f – имя файловой переменной, от-

    секает часть открытого файла, начиная с текущего компонента, и подтягивает на его место конец файла.

    Использование процедур seek и truncate рассмотрим на при-

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    364

    мере решения следующих двух несложных задач по обработке файлов.

    ЗАДАЧА 7.4. В файле вещественных чисел /home/pascal/6/pr1/abc.dat поменять максимальный и минимальный элементы.

    Рассмотрим два варианта решения этой задачи.

    В первом консольном варианте программы — после считывания компонентов файла в массив происходит поиск минимального и максимального элементов массива и их индексов. Затем максимальное и

    минимальное значения перезаписываются в файл. program Project1;

    {$mode objfpc}{$H+} uses Classes, SysUtils

    { you can add units after this }; var f:file of real;

    i, nmax, nmin :integer; a:array[0..200] of real; max,min:real;

    begin assignfile(f,’/home/pascal/6/pr1/abc.dat’); reset(f);

    //Cчитываем компоненты файла в массив а. for i:=0 to filesize(f)-1 do

    begin read(f,a[i]);

    write(a[i]:1:2,’ ‘); end;

    //Начальное присваивание максимального и //минимального элементов массива и их индексов. max:=a[0]; nmax:=0;

    min:=a[0]; nmin:=0;

    //Основной цикл для поиска максимального и //минимального элементов массива и их индексов. for i:=1 to filesize(f)-1 do

    begin

    if a[i]>max then begin

    max:=a[i];

    nmax:=i

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    365

    end;

    if a[i]<min then begin

    min:=a[i];

    nmin:=i

    end;

    end;

    //Перезапись максимального и //минимального значений в файл. //Передвигаем указатель файла //к максимальному элементу. seek(f,nmax);

    //Записываем на место максимального //элемента минимальный. write(f,min);

    //Передвигаем указатель файла //к минимального элементу. seek(f,nmin);

    //Записываем на место //максимального элемента минимальный. write(f,max);

    //Обязательно закрываем файл. closefile(f);readln;

    end.

    Вторую версию программы напишем как полноценное приложение. Использовать массив в программе не будем. Будет организован единственный цикл, в котором очередное значение считывается в переменную a и осуществляется поиск минимального и максималь-

    ного элементов среди компонентов файла и их индексов. Затем происходит перезапись в файл максимального и минимального значений.

    Разработку программы начнем с создания шаблона графического приложения (Проект — Создать Проект — Приложение).

    На форме расположим следующие компоненты:

    1.Две метки Label1 и Label2 для подписи.

    2.Edit1 — текстовое поле редактирования, в котором будем хранить содержимое исходного файла.

    3.Edit2 — текстовое поле редактирования, в котором хранит-

    ся файл после преобразования.

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    366

    4. OpenDialog1 — компонент для выбора имени обрабатываемого файла.

    5.Button1 — кнопка для запуска программы.

    6.Button2 — кнопка для завершения программы. Расположим компоненты на форме примерно так, как показано на

    рис. 7.7.

    Рисунок 7.7: Окно проекта с компонентами

    Основные свойства компонентов будем устанавливать программно при создании формы. Поэтому подпрограмма FormCreate будет

    такой.

    procedure TForm1.FormCreate(Sender: TObject); begin

    Form1.Caption:=

    ‘Обмен максимального и минимального элементов в файле’;

    label1.Caption:=’Исходный файл’; label1.Visible:=False; label2.Caption:=’Файл после

    преобразования’;

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    367

    label2.Visible:=False;

    Edit1.Text:=»;

    Edit1.Visible:=false;

    Edit2.Text:=»;

    Edit2.Visible:=false;

    OpenDialog1.Filter:=

    ‘Файлы вещественных чисел|*.dat|Все файлы|*.*’; OpenDialog1.InitialDir:=’/home/pascal/6/pr1′; Button1.Caption:=’Преобразовать файл’;

    Button2.Caption:=’Выход’;

    Button2.Visible:=False;

    end;

    Авторы надеются, что читателям, дочитавшим книгу до этого момента, текст процедуры TForm1.FormCreate понятен без поясне-

    ний.

    При запуске программы окно формы будет иметь вид, представленный на рис. 7.8.

    Основные действия программа будет осуществлять при щелчке по кнопке Преобразовать файл, текст соответствующей подпрограммы с комментариями приведен ниже.

    procedure TForm1.Button1Click(Sender: TObject); var

    f:file of real; i,nmax,nmin:integer; a,max,min:real; s1,s:string;

    begin

    //Открываем диалоговое окно для выбора файла. if OpenDialog1.Execute then

    begin

    //В переменную s записываем полное имя файла. s:=OpenDialog1.FileName;

    //Связываем файловую переменную //с файлом на диске.

    assignfile(f,s);

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    368

    Рисунок 7.8: Окно программы решения задачи 7.4 при запуске

    //Открываем файл в режиме чтения. reset(f);

    //Делаем видимыми первую метку и поле ввода. label1.Visible:=true; Edit1.Visible:=true;

    //В строке s1 будем формировать //содержимое файла.

    S1:=»;

    //Цикл для последовательного чтения //всех элементов из файла // вещественных чисел.

    for i:=0 to filesize(f)-1 do begin

    //Считывание очередного элемента //массива в переменную a.

    read(f,a); if i=0 then

    //Начальное присваивание максимального //и минимального значений и их индексов.

    begin max:=a;

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    369

    nmax:=i;

    min:=a;

    nmin:=i;

    end else begin

    //Сравнение текущего значения с //максимальным (минимальным).

    if max<a then begin

    max:=a;

    nmax:=i

    end;

    if min>a then begin

    min:=a;

    nmin:=i

    end end;

    //Добавление очередного значения //к выходной строке s1.

    s1:=s1+FloatToStr(a)+’ ‘; end;

    //Вывод содержимого файла //в первое текстовое поле.

    Edit1.Text:=s1;

    //Запрет изменения текстового поля. Edit1.ReadOnly:=true;

    //Перезапись максимального //и минимального значений в файл. //Передвигаем указатель файла //к максимальному элементу.

    seek(f,nmax); //Записываем на место

    //максимального элемента минимальный. write(f,min);

    //Передвигаем указатель //файла к максимальному элементу.

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus 370

    seek(f,nmin); //Записываем на место

    //минимального элемента максимальный. write(f,max);

    //Обязательно закрываем файл. closefile(f);

    reset(f);

    //Делаем видимыми вторую метку и поле ввода. label2.Visible:=true; Edit2.Visible:=true;

    //Считываем данные из преобразованного файла s1:=»;

    for i:=0 to filesize(f)-1 do begin

    read(f,a);

    //Добавление очередного значения

    //из преобразованного файла к строке s1. s1:=s1+FloatToStr(a)+’ ‘;

    end;

    //Вывод содержимого преобразованного //файла во 2-е текстовое поле.

    Edit2.Text:=s1;

    //Запрет изменения текстового поля. Edit2.ReadOnly:=true;

    //Делаем видимой вторую кнопку. Button2.Visible:=True; CloseFile(f);

    end;

    end;

    При щелчке по кнопке Выход программа должна завершать свою работу. Поэтому текст обработчика щелчка по кнопке будет очень

    простым.

    procedure Tform_File.Button2Click(Sender: TObject);

    begin Close;

    end;

    При щелчке по кнопке Преобразовать файл, появляется окно

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    371

    выбора файла, подобное представленному на рис. 7.5. После выбора файла в файле происходит обмен максимального и минимального элементов и вывод содержимого файла до и после преобразования (см. рис. 7.9).При щелчке по кнопке Выход работа программы завершит-

    ся.

    Рисунок 7.9: Окно программы решения задачи 7.4 после преобразования файла

    При решении задачи 7.4 была использована процедура seek, с

    помощью которой стало возможным изменение данных в файле непосредственно на диске, без считывания в массив. Однако следует помнить, что большое количество отдельных обращений к файлу занимает больше времени, чем однократное обращение к файлу для обработки большого объема данных.

    ЗАДАЧА 7.5. Задан файл вещественных чисел abc.dat. Удалить из него максимальный и минимальный элементы.

    Рассмотрим две программы, решающие эту задачу. Алгоритм первой состоит в следующем: считываем компоненты файла в массив, в котором находим максимальный и минимальный элементы и их номера. Открываем файл для записи и вносим в него все элементы, за исключением максимального и минимального.

    program Project1;

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    372

    {$mode objfpc}{$H+} uses Classes, SysUtils

    { you can add units after this }; var

    f:file of real; max,min:real;

    j, i,nmax,nmin:integer; a:array [1..300] of real; begin

    assignfile(f,’/home/pascal/6/pr1/abc.dat’);

    reset(f);

    //Запоминаем в переменной j //количество компонентов в файле. j:=filesize(f);

    //Считываем компоненты файла в массив а. for i:=1 to j do read(f,a[i]);

    for i:=1 to j do write(a[i]:1:2,’ ‘); writeln;

    closefile(f);

    //Открываем файл для записи. rewrite(f);

    //Начальное присваивание максимального и //минимального элементов массива и его индекса. max:=a[1];min:=a[1];

    nmax:=1;nmin:=1;

    //Основной цикл для поиска максимального и //минимального элементов массива и его индекса. for i:=2 to j do

    begin

    if a[i]>max then begin

    max:=a[i];

    nmax:=i

    end;

    if a[i]<min then begin

    min:=a[i];

    nmin:=i;

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus 373

    end;

    end;

    //Перезапись элементов массива в файл, //за исключением элементов с //номерами nmax и nmin. writeln(‘Преобразованный файл’);

    for i:=1 to j do

    if (i<>nmax)and (i<>nmin) then begin

    write(f,a[i]);

    //Вывод записанного в файл элемента на экран. write(a[i]:1:2,’ ‘);

    end;

    closefile(f);

    readln;

    end.

    Вторая программа работает следующим образом. Находим максимальный и минимальный элементы и их номера среди компонентов файла. Если nmin>nmax, то меняем содержимое переменных nmin и

    nmax. Далее элементы, лежащие между минимальным и максимальным (формально между элементами с номерами nmin и nmax), сдви-

    гаем на один порядок влево. Тем самым мы убираем элемент с номером nmin. После этого все компоненты, лежащие после элемента с

    номером nmax, сдвинем на два порядка влево. Этим мы сотрем мак-

    симальный элемент. Затем два последних компонента в файле необхо-

    димо удалить.

    program Project1; {$mode objfpc}{$H+} uses Classes, SysUtils

    { you can add units after this }; var

    f:file of real; a:real; max,min:real; i,nmax,nmin:integer; begin

    assign(f,’/home/pascal/6/pr1/abc.dat’); reset (f);

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus

    374

    //Поиск максимального и //минимального элементов в файле и их индексов. writeln(‘Исходный файл’);

    for i:=0 to filesize(f)-1 do begin

    read(f,a); write(a:1:2,’ ‘); if i=0 then begin

    max:=a;

    nmax:=i;

    min:=a;

    nmin:=i

    end else begin

    if a>max then begin

    max:=a;

    nmax:=i;

    end;

    if a<min then begin

    min:=a;

    nmin:=i;

    end

    end

    end;

    writeln;

    //Сравниваем nmin и nmax. if nmax<nmin then

    begin i:=nmax;

    nmax:=nmin;

    nmin:=i

    end;

    // Сдвигаем элементы, лежащие между //компонентами с номерами nmin и nmax,

    Алексеев Е.Р., Чеснокова О.В., Кучер Т.В. Самоучитель по программированию на Free Pascal и Lazarus 375

    //на один влево.

    for i:=nmin to nmax-2 do begin

    seek(f,i+1);

    read(f,a);

    seek(f,i);

    write(f,a);

    end;

    //Сдвигаем элементы, лежащие после компонента //с номером nmax, на два влево.

    for i:=nmax to filesize(f)-3do begin

    seek(f,i+1);

    read(f,a);

    write(a:1:2); seek(f,i-1); write(f,a); write(a:1:2);

    end;

    //Отрезаем последние два компонента. truncate(f);

    closefile(f);

    reset(f);

    //Вывод преобразованного файла. writeln(‘Преобразованный файл’); for i:=1 to filesize(f) do

    begin

    read(f,a);

    //Вывод записанного в файл элемента на экран. write(a:1:2,’ ‘);

    end;

    closefile(f);

    end.

    В результате программы из файла вещественных чисел удалено наибольшее и наименьшее число.

    Кроме типизированных файлов, широкое применение при обработке числовых данных получили бестиповые файлы.

    Понравилась статья? Поделить с друзьями:

    Не пропустите также:

  • Как найти сайт америки
  • Как составить формулы бинарных соединений химия 8 класс
  • Как найти дом 2 рейтинг
  • Как составить план организации проекта
  • Как исправить ошибку в бланке олимпиады

  • 0 0 голоса
    Рейтинг статьи
    Подписаться
    Уведомить о
    guest

    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии