Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
записи_и_файлы_20ноя2012.doc
Скачиваний:
12
Добавлен:
01.03.2025
Размер:
513 Кб
Скачать
☆

If {…запись не удаляется…}

then write (f_temp, zap)

else {запись не выводится в файл f_temp,

либо, например, пишется в другой

файл};

until eof(f1);

close(f1);

close (f_temp);

. . .

  1. Корректировка с использованием последовательного доступа.

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

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

{ корректировка записей файла f1 }

. . .

reset(f1);

rewrite (F_temp);

repeat

read(f1,zap);

If {запись не корректируется}

then write (f_temp, zap)

else {запись корректируется}

begin

{ 1. исх. запись zap копируется

в поле zap_corr}

{ 2. пользователь корректирует}

{ поля записи в zap_corr }

{ 3. затем у пользователя }

{ запрашивается подтверждение}

{ сделанной корректировки}

If { корректировка подтверждена }

then {в файл записываеся

откорректированная

запись zap_corr }

write (f_temp, zap_corr)

else {в файл записывается

исходная запись zap}

write (f_temp, zap);

end;

until eof(f1);

close(f1);

close (f_temp);

. . .

Пользователь должен подтвердить корректировку или отказаться от неё. Перед подтверждением пользователь должен увидеть тексты старой, исходной и новой, откорректированной записей. Только после этого он принимает решение о подтверждении сделанной корректировки или отказе от неё. Лучший вариант – возможность видеть одновременно и прежнее, и новое значения полей.

После закрытия файлов возможны следующие варианты:

а) старый файл уничтожается, а новый файл получает имя старого файла;

б) старый файл сохраняет прежнее имя, но получает новое расширение ~.BAK, а новый файл получает имя старого файла;

в) содержимое нового файла переписывается в старый файл, новый файл уничтожается.

Корректировка с использованием прямого доступа:

  1. определяется корректируемая запись;

  2. значение ключевого признака корректируемой записи преобразуется в номер физической записи в файле;

  3. указатель записи позиционируется на искомую запись процедурой Seek (имя_файла_прогр, номер_записи);

  4. искомая запись читается в оперативную память с использованием Read (имя_файла_прогр, поле_записи);

  5. выполняется корректировка полей записи;

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

Seek (имя_файла_прогр, номер_записи);

либо

Seek (имя_файла_прогр, (FilePos ( имя_файла_прогр ) - 1); {возврат с текущей записи на предыдущую}

7) вывод откорректированной записи в файл на своё прежне место

Write (имя_файла_пр, поле_записи);

Внимание: здесь тоже необходимо подтверждать выполнение сделанной корректировки

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

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

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

  1. Исходя из количества записей, выделяется динамическая память под массив записей.

  2. Записи файла переносятся в массив.

  3. Над массивом записей в оперативной памяти выполняются требуемые действия (заполнение, добавление, удаление, корректировка), но реализуемые алгоритмами работы с массивом.

  4. После окончания обработки массив записывается в новый файл (желательно, чтобы пользователь подтвердил сделанные изменения).

  5. Принимается решение о варианте использования нового файла в совокупности с основным (переименование в основной файл, перепись в основной и удаление и т.д.).

Внимание! Только один этот вариант работы с файлами в лабораторных работах № 1 и № 2 использован быть не может. Необходимо применить варианты использования рабочего файла.

Особенности обработки текстовых файлов.

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

К текстовым файлам возможен только последовательный доступ. С текстовыми файлами работают различные редакторы текстов. Текстовые файлы имеют стандартный тип TEXT.

VAR

Имя_файла: TEXT;

Посимвольные операции ввода-вывода выполняются для текстовых файлов процедурами read и write.

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

Кроме того, для текстовых файлов применяются процедуры ASSIGN, RESET, REWRITE, CLOSE, EOF, eoln.

Процедура append открывает существующий текстовый файл для добавления записей.

Для текстовых файлов нельзя использовать процедуры и функции SEEK, FILEPOS, FILESIZE, т.к. элементы (записи текстового файла) имеют разную длину.

input и output стандартные текстовые файлы для ввода с клавиатуры и вывода на экран.

Рекомендация: при вводе/выводе преимущественно использовать процедуры READLN ( ) и WRITELN ( );

Пример

Рассмотрим программу, реализующую следующую задачу. Дан текстовый файл F1.Необходимо заменить во всех записях этого файла код группы ДКЕ-101 на ДКЕ-201. Скорректированные записи поместить в файл F2.

var

f1,f2: text;

pole:string;

filename, filenam2:string[12];

pz: integer;

begin

write(‘ввод имени входного файла:’);

readln(filename);

assign(f1, filename);

reset(f1); { без защиты }

write(‘ввод имени выходного файла:’);

readln(filenam2);

assign(f2, filenam2);

rewrite(f2);

while ( not eof(f1) ) do

begin

readln(f1,pole);

while ( pos(‘дке-101’, pole) ) <> 0 do

begin

pz:= pos(‘дке-101’, pole);

delete(pole,pz+4,1);

insert(‘2’,pole,pz+4);

end;

writeln(f2,pole)

end;

close(f1);

close(f2);

end.

Здесь читаются последовательно строки из входного файла и в каждой строке в номере группы заменяется символ 1 на 2. Скорректированные строки выводятся в новый файл.

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

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

SEEK (имя_файла_в_прог , физ_номер_записи) ;

Далее может следовать:

  • либо чтение указанной записи из файла,

  • либо занесение подготовленной записи в файл на указанное место вместо прежней записи (примерно так может быть выполнена корректировка или замена указанной записи в файле).

Для обеспечения прямого доступа необходимо следующее:

  • файл должен быть типизированным (фиксированная, постоянная длина записи);

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

  • обратить внимание: первая логическая запись будет размещена в физической области с нулевым номером, вторая логическая – в первой физической и т.д. В Seek (…) указывается физический номер записи

  • размещение записей желательно без пропусков.

  • использование процедур, обеспечивающих

    • контроль положения указателя чтения FilePos (…);

    • позиционирование указателя чтения в файле Seek (…);

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

Номер_зап = Ключ_тек – Ключ_мин

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

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

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

    • потери в используемой памяти («пустые» записи внутри файла);

    • необходимо выполнить предварительное резервирование места для записей – что-то вроде разметки файлового пространства, то есть занесение в файл только пустых записей;

    • заполнение файла реальными записями в файл прямым доступом в соответствии со значениями их ключей;

    • контроль записей при чтении из файла, чтобы не работать с пустыми записями.

Пример.

В следующей программе, используя прямой доступ к записям файла, созданного в предыдущей программе, требуется подсчитать общую сумму зарплаты тех рабочих, чьи табельные номера вводятся с клавиатуры. Предполагается, что при создании файла были использованы табельные номера в интервале 101-999 и запись с номером 101 занимает первое место в файле, за ней следует запись с табельным номером 102 и т.д. Таким образом, табельный номер и есть ключ записи, который будет преобразован в физический номер записи

program file_2;

type

tz=record

fio:string[20];

tn:integer;

zp:real

end;

var

zap:tz;

fout:file of tz;

tn1,tn2,n:integer;

s:real;

filename:string;

ans : string;

begin

writeln('введите имя файла ');

readln(filename);

assign (fout, filename);

reset(fout);

s:=0;

repeat

readln(tn2);

tn1:=tn2-101;

{формирование указателя записи,

101 – это минимальное значение табельного номера}

seek(fout,tn1);

read(fout,zap);

s:=s+zap.zp;

writeln('ещё запрос ? ( y/ n )');

readln(ans);

until ( ans = ‘n’ );

writeln(‘s= ‘,s);

close(fout)

end.

ВНИМАНИЕ: в задаче нет многих подстраховок: от ввода пустой строки, от несуществующего файла и др.

Материал к лабораторной работе по файлам

Подведение итога по файлу (одной степени).

Код цеха

Код участка

Таб.номер

Кол-во

Расценка за единицу

Начислено

1

1

111

10

10

100

1

1

111

11

10

110

1

1

111

10

2

20

1

1

111

5

5

25

1

1

111

12

5

60

1

1

120

2

2

4

1

1

120

5

2

10

1

1

120

3

3

9

1

1

120

10

5

50

1

1

120

5

10

50

1

2

130

100

1

100

1

2

130

110

2

220

1

2

130

100

1

100

1

2

130

5

50

250

1

2

130

120

2

240

1

2

135

20

2

40

1

2

135

5

20

100

1

2

135

3

30

90

1

2

135

10

5

50

1

2

135

10

10

100

2

10

200

10

20

200

2

10

200

11

10

110

2

10

200

10

2

20

2

10

200

5

5

25

2

10

200

12

5

60

2

10

250

2

2

4

2

10

250

5

2

10

2

10

250

3

3

9

2

10

250

10

5

50

2

10

250

5

10

50

2

20

130

100

1

100

2

20

130

110

2

220

2

20

130

100

1

100

2

20

130

5

50

250

2

20

130

120

2

240

2

2

135

20

2

40

2

2

135

5

20

100

2

2

135

3

30

90

2

2

135

10

5

50

2

2

135

10

10

100

Итого по заводу

 

 

 

 

3556

Type

Rec = record

Code_z : integer;

Code_uch : integer;

Tab_nom : integer;

Kol_vo : integer;

Rasz : real;

End;

Var

Zap : rec;

Sum_file : real;

Begin

Writeln (‘ Введите имя файла на диске: ‘);

Readln (Filename)’

Assign (Mainfile, filename);

Reset (mainfile);

Sum_file := 0;

While (not EOF (mainfile)) do

Begin

Read (Mainfile, zap);

Nachisl := zap.kol_vo * zap.rasz;

Sum_file := sum_file + nachisl;

End;

Writeln (‘ Итого по заводу начислено ‘,

Sum_file:10:2);

Readln;

End.

Подведение итога по по цехам и по файлу/заводу

(итоги двух степеней).

Код цеха

Код участка

Таб.номер

Кол-во

Расценка за единицу

Начислено

1

1

111

10

10

100

1

1

111

11

10

110

1

1

111

10

2

20

1

1

111

5

5

25

1

1

111

12

5

60

1

1

120

2

2

4

1

1

120

5

2

10

1

1

120

3

3

9

1

1

120

10

5

50

1

1

120

5

10

50

1

2

130

100

1

100

1

2

130

110

2

220

1

2

130

100

1

100

1

2

130

5

50

250

1

2

130

120

2

240

1

2

135

20

2

40

1

2

135

5

20

100

1

2

135

3

30

90

1

2

135

10

5

50

1

2

135

10

10

100

Итого по цеху 1

 

 

 

 

1728

2

10

200

10

20

200

2

10

200

11

10

110

2

10

200

10

2

20

2

10

200

5

5

25

2

10

200

12

5

60

2

10

250

2

2

4

2

10

250

5

2

10

2

10

250

3

3

9

2

10

250

10

5

50

2

10

250

5

10

50

2

20

130

100

1

100

2

20

130

110

2

220

2

20

130

100

1

100

2

20

130

5

50

250

2

20

130

120

2

240

2

2

135

20

2

40

2

2

135

5

20

100

2

2

135

3

30

90

2

2

135

10

5

50

2

2

135

10

10

100

Итого по цеху 2

 

 

 

 

1828

Итого по заводу

 

 

 

 

3556

Вариант 1 (необходимо особо учитывать случай обработки последней записи)

Type

Rec = record

Code_z : integer;

Code_uch : integer;

Tab_nom : integer;

Kol_vo : integer;

Rasz : real;

End;

Var

Zap : rec;

Sum_z, Sum_file : real;

Code_z : integer;

Begin

Writeln (‘ Введите имя файла на диске: ‘);

Readln (Filename)’

Assign (Mainfile, filename);

Reset (mainfile);

Sum_file := 0;

Read (Mainfile, zap);

While (not EOF (mainfile)) do

Begin

Code_z:=zap.code_z;

Sum_z := 0;

While (not EOF (mainfile)) and

(Code_z = zap.code_z) do

begin

Nachisl := zap.kol_vo * zap.rasz;

Sum_z := sum_z + nachisl;

Read (Mainfile, zap);

End;

Writeln (‘ Итого по цеху’, code_z,

‘ начислено ‘, Sum_file:10:2);

Sum_file := sum_file + Sum_z;

End;

Writeln (‘ Итого по заводу начислено ‘,

Sum_file:10:2);

Readln; End.

{ необходимо особо учитывать случай обработки последней записи}

Итоги трёх степеней

Код цеха

Код участка

Таб.номер

Кол-во

Расценка за единицу

Начислено

1

1

111

10

10

100

1

1

111

11

10

110

1

1

111

10

2

20

1

1

111

5

5

25

1

1

111

12

5

60

1

1

120

2

2

4

1

1

120

5

2

10

1

1

120

3

3

9

1

1

120

10

5

50

1

1

120

5

10

50

Итого по участку

1

 

 

 

438

1

2

130

100

1

100

1

2

130

110

2

220

1

2

130

100

1

100

1

2

130

5

50

250

1

2

130

120

2

240

1

2

135

20

2

40

1

2

135

5

20

100

1

2

135

3

30

90

1

2

135

10

5

50

1

2

135

10

10

100

Итого по участку

2

 

 

 

1290

 

 

 

 

 

 

Итого по цеху 1

 

 

 

 

1728

2

10

200

10

20

200

2

10

200

11

10

110

2

10

200

10

2

20

2

10

200

5

5

25

2

10

200

12

5

60

2

10

250

2

2

4

2

10

250

5

2

10

2

10

250

3

3

9

2

10

250

10

5

50

2

10

250

5

10

50

Итого по участку

10

 

 

 

538

2

20

130

100

1

100

2

20

130

110

2

220

2

20

130

100

1

100

2

20

130

5

50

250

2

20

130

120

2

240

2

2

135

20

2

40

2

2

135

5

20

100

2

2

135

3

30

90

2

2

135

10

5

50

2

2

135

10

10

100

Итого по участку

2

 

 

 

1290

 

 

 

 

 

 

Итого по цеху 2

 

 

 

 

1828

 

 

 

 

 

 

Итого по заводу

 

 

 

 

3556

Type

Rec = record

Code_z : integer;

Code_uch : integer;

Tab_nom : integer;

Kol_vo : integer;

Rasz : real;

End;

Var

Zap : rec;

Sum_uch, Sum_z, Sum_file : real;

Code_uch, Code_z : integer;

Begin

Writeln (‘ Введите имя файла на диске: ‘);

Readln (Filename)’

Assign (Mainfile, filename);

Reset (mainfile);

Sum_file := 0;

Read (Mainfile, zap);

While (not EOF (mainfile)) do

Begin

Code_z:=zap.code_z;

Sum_z := 0;

While (not EOF (mainfile)) and

(Code_z = zap.code_z) do

begin

Code_uch:=zap.code_uch;

Sum_uch := 0;

While (not EOF (mainfile)) and

(Code_z = zap.code_z) and

(Code_uch = zap.code_uch)do

begin

Nachisl := zap.kol_vo * zap.rasz;

Sum_uch := sum_uch + nachisl;

Read (Mainfile, zap);

End;

Writeln (‘ Итого по участку’, code_uch,

‘ начислено ‘, Sum_uch:10:2);

Sum_z := sum_z + Sum_uch;

End;

Writeln (‘ Итого по цеху’, code_z,

‘ начислено ‘, Sum_z:10:2);

Sum_file := sum_file + Sum_z;

End;

Writeln (‘ Итого по заводу начислено ‘,

Sum_file:10:2);

Readln;

End.

Итоги четырёх степеней

Код цеха

Код участка

Таб.номер

Кол-во

Расценка за единицу

Начислено

1

1

111

10

10

100

1

1

111

11

10

110

1

1

111

10

2

20

1

1

111

5

5

25

1

1

111

12

5

60

 

Итого по таб.номеру 111

 

 

315

1

1

120

2

2

4

1

1

120

5

2

10

1

1

120

3

3

9

1

1

120

10

5

50

1

1

120

5

10

50

 

Итого по таб.номеру 120

 

 

123

 

 

 

 

 

 

 

Итого по участку 1

 

 

 

438

1

2

130

100

1

100

1

2

130

110

2

220

1

2

130

100

1

100

1

2

130

5

50

250

1

2

130

120

2

240

 

Итого по таб.номеру 130

 

 

910

1

2

135

20

2

40

1

2

135

5

20

100

1

2

135

3

30

90

1

2

135

10

5

50

1

2

135

10

10

100

 

Итого по таб.номеру 135

 

 

380

 

Итого по участку 2

 

 

 

1290

Итого по цеху 1

 

 

 

 

1728

2

10

200

10

20

200

2

10

200

11

10

110

2

10

200

10

2

20

2

10

200

5

5

25

2

10

200

12

5

60

 

Итого по таб.номеру 200

 

 

415

2

10

250

2

2

4

2

10

250

5

2

10

2

10

250

3

3

9

2

10

250

10

5

50

2

10

250

5

10

50

Итого по таб.номеру 250

 

 

123

 

Итого по участку 10

 

 

 

538

2

20

130

100

1

100

2

20

130

110

2

220

2

20

130

100

1

100

2

20

130

5

50

250

2

20

130

120

2

240

 

Итого по таб.номеру 130

 

 

910

2

2

135

20

2

40

2

2

135

5

20

100

2

2

135

3

30

90

2

2

135

10

5

50

2

2

135

10

10

100

 

Итого по таб.номеру 135

 

 

380

 

Итого по участку 2

 

 

 

1290

Итого по цеху 2

 

 

 

 

1828

Итого по файлу (заводу)

 

 

 

3556