Имеется задание.
Создать и заполнить файл F с компонентами целочисленного типа. Отобразить содержимое исходного файла. Вычислить сумму компонент файла, имеющих четное значение. Увеличить на значение этой суммы отрицательные компоненты второй половины файла. Отобразить полученный файл. Удалить из файла компоненту с минимальным значением, файл сжать. Отобразить полученный файл.
Понятно, что Паскаль обладает набором средств, позволяющим решить эту задачу, как и любую другую. Но вот насколько они удобны?
Начало - тут все стандартно для работы с файлами. Надо открыть файл “с очисткой” и связать его имя с каким-нибудь дескриптором. Потом записать в него значения и закрыть. Никаких вопросов, все логично.
begin
var f:file of integer;
Rewrite(f,'F.bin');
Randomize(2); // отладочное, чтобы числа не менялись
var n:=20; // число компонент
loop n do
Write(f,Random(-50,50));
f.Close; // файл создан
end.
Вывод компонент файла. Снова открываем файл и в цикле читаем каждую запись и выводим её. Продолжаем до конца файла. В принципе, можно одновременно получить и сумму компонент, но попробуем быть последовательными в пошаговом решении.
Reset(f,'F.bin');
while not f.Eof do Print(f.Read);
Writeln;
Вычисляем сумму. Для этого нужно снова стать на начало файла и просмотреть его, отбирая компоненты по критерию.
var s:=0; var m:integer;
f.Reset;
while not f.Eof do begin
m:=f.Read;
if m.IsEven then s+=m
end;
Теперь просматриваем вторую половину файла и отрицательные компоненты увеличиваем на величину найденной суммы. Неприятная операция, потому что Н.Вирт (и разработчики этого Паскаля) не предусмотрели специальных средств корректировки записей в файле. Поэтому нужно прочитать значение, вернуть указатель на предыдущую запись и записать значение.
f.Seek(n div 2); // указатель на вторую половину файла
while not f.Eof do begin
m:=f.Read;
if m<0 then begin
f.Seek(f.FilePos-1); // это просто перл (((
Write(f,m+s)
end
end;
// вывод содержимого файла
f.Reset;
while not f.Eof do Print(f.Read);
Writeln;
Ищем номер записи с минимальной компонентой. Опять с начала файла, конечно же.
// поиск минимума
f.Reset;
var (pmin,min):=(0,f.Read);
while not f.Eof do begin
m:=f.Read;
if m<min then
(pmin,min):=(f.FilePos-1,m) // занятное место
end;
Здесь возможна частая ошибка, потому что Seek считает, будто компоненты нумеруют от нуля, а FilePos с завидным упорством отсчитывает их от единицы.
Ну и последний рубеж - удаление минимума. Занятие еще то. Внешне все понятно. Местоположение минимума найдено, оно в pmin. Теперь нам надо стать на следующую за pmin компоненту и переписать её на одну компоненту к началу файла. И поступить так для всех компонент. После записи последней компоненты на предпоследнее место надо усечь файл и закрыть его. А потом вновь открыть и вывести. Эту часть я оставляю желающим, поскольку эти f.Seek и анализ f.Eof меня несколько расстроили.
Надеюсь, что если кто-то пожелает сделать задачу полностью и проанализирует решение в целом, тоже ощутит желание кое-что в такой работе с файлами "подкрутить. Тогда и обменяемся идеями.