Работа с файлами. 1. Файлы. Сегодня работу за компьютером практически невозможно себе представить без возможности сохранить данные на винчестере (флэшке, диске и т.д. ). Представьте себе самую простую ситуацию: Вы набираете текст в текстовом редакторе, печатаете на принтере, а сохранить не можете (когда-то примерно так все и начиналось) или забыли. При обнаружении через некоторое время ошибок текст приходится перенабирать! Примерно то же самое можно отнести и к компьютерной программе. Вы написали программу, которая подсчитывает средний балл и сортирует учеников в классе по рейтингу (в порядке убывания среднего балла). Понятно, что для расчета Вам необходимо ввести все необходимые данные (а их немало!). После расчетов Вы обнаружили «логическую» ошибку в программе или ошиблись при вводе данных и… все надо вводить заново! А если и со второго раза не получится? Другая проблема: программа правильно посчитала рейтинг, вывела на экран… А что дальше? Его надо как минимум распечатать, а еще лучше сохранить и иметь возможность просмотреть в нужный момент. Поэтому при написании даже несложных программ с большим количеством исходных данных практически необходимо: использовать ввод данных из файла, результаты сохранять в файл. Паскаль работает с двумя видами файлов: текстовыми и типизированными. В этом занятии мы остановимся на принципах работы с текстовыми файлами (именно умение работать с текстовыми файлами – одно из требований к участникам олимпиады по информатике). Существует два основных способа чтения и записи данных в текстовые файлы: 1. С использованием файловых переменных текстового типа. 2. С перенаправлением ввода-вывода. Оба метода в принципе очень похожи, но у каждого из них есть свои преимущества и недостатки, которые особенно важно помнить при решении задач именно на олимпиадах (когда один неправильно поставленный символ может лишить участника большого количества баллов).
2. Этап подготовки. Перед тем, как работать с файлами, надо знать, как и в какой папке создавать исходные файлы, и где будут создаваться выходные файлы. Создание исходных текстовых файлов. Текстовые файлы можно создавать в Проводнике (Правая кнопка мыши, Создать, Текстовый документ) – в этом случае обязательно просмотрите свойства файла (Правая кнопка мыши, Свойства), одна из наиболее частых ошибок: набирается имя файла с расширением txt, Windows (не всегда!) дописывает расширение txt еще раз и имя файл, например, вместо input.txt, выглядит так: input.txt.txt . Второй способ создания тестового файла в Total Commander (Windows Commander): нажать Shift+F4, ввести имя фала, ввести данные, при выходе – сохранить. Внимание! При вводе исходных данных на олимпиаде строго следуйте условию задачи и приведенным примерам! Перед созданием файлов с исходными данными при решении прикладных задач предварительно тщательно продумайте порядок и структуру исходных данных! От этого зависит весь алгоритм решения задачи. Числовые данные разделяйте одним пробелом или записывайте в столбик (если это не регламентировано условием задачи). Где создавать файлы? Исходные текстовые файлы должны «лежать» в рабочей папке. Почти для всех версий Паскаля, чтобы узнать расположение рабочей папки на диске достаточно запустить Паскаль, выбрать пункт меню File-Change dir и посмотреть путь. Внимание! Рекомендуем для работы с ранее созданными программами скопировать их в рабочую папку Паскаля. Для некоторых версий (в том числе для PascalABC) при открытии готового файла с расширением pas рабочей папкой становится папка с открытым файлом! При этом если полный путь к этой папке содержит русские буквы или длинные имена, может возникать сообщение об ошибке! После компиляции программы и создания файла с расширением exe его можно копировать в любую папку, при этом файл с исходными данными должен быть в одной папке с exe файлом. Именно так проходит тестирование большинства задач на олимпиаде: exe файл участника копируется в папку с текстовым файлом с исходными данными, после его запуска в той же папке (при корректной работы программы) создается выходной файл, который сравнивается с эталонным. Внимание! Запустите программу несколько раз, если при повторном запуске программы возникли ошибки, проверьте текстовый файл с исходными данными (может быть, Вы при копировании забыли изменить имя, и Ваша программа вывела результаты в тот же файл, уничтожив исходные данные)! И, наконец, принцип работы с файлами:
3. Работа с текстовыми файлами с использованием файловых переменных текстового типа. Прежде всего в разделе описания переменных необходимо указать переменную текстового типа (текстовый файл): var f:text; В основном блоке программы связываем переменную с конкретным файлом на диске, например: assign(f,’input.txt’); Теперь при любом указании в программе переменной f она будет обращаться к файлу input.txt в рабочей папке (так как не указан путь к файлу). Обратите внимание на то, что Паскалю «абсолютно все равно», какое расширение имеет файл. К указанному между апострофами файлу, он будет обращаться как к текстовому. На олимпиаде имя файла должно совпадать с указанным в условии задачи! Далее попробуем прочитать данные из файла и записать результаты в файл. Для чтения используются процедуры работы с файлами (где f – описанная Вами переменная текстового типа): reset(f); - Открыть файл для чтения. readln(f,t); или read(f,t); - Прочитать значение из файла в переменную t, причем ввод данных из файла практически не отличается от ввода с клавиатуры, только перед именем переменной указывается файловая (текстовая) переменная. Но в отличии от ввода с клавиатуры появляются существенные различия между операторами read и readln (чтение без перевода строки и чтение с переводом строки). Если данные в исходном файле расположены в столбик, то разницы нет, так как и оператор read, доходя до конца строки, переводит «курсор». А вот если данные записаны в несколько строк, то с помощью readln при чтении чисел можно сразу перейти к следующей строке, игнорируя расположенные правее значения. Например, если в файле: 14 17 235 15 2 191 2 1 3 то при использовании операторов: read(f,a); read(f,b); read(f,c); read(f,d); writeln(a,' ',b,' ',c,' ',d); на экране появится: 14 17 235 15 а при использовании операторов: readln(f,a); readln(f,b); read(f,c); read(f,d); writeln(a,' ',b,' ',c,' ',d); строка будет выглядеть так: 14 15 2 1 close(f); - Закрыть файл. Никогда не забывайте закрывать файл, особенно при записи данных, иначе можно «нарваться» на ошибку или последняя строка выходного файла может остаться не записанной. А на олимпиаде – это практически не решенная задача! Для записи используются процедуры работы с файлами (где f – описанная Вами переменная текстового типа): rewrite(f); - Пересоздать файл. То есть файл будет создан, если его не было или уничтожен и создан, если был. append(f); - Открыть файл для дополнения. Все данные будут добавляться в конец файла. write(f,t); или writeln(f,t); - Вывод данных в файл. Формат операторов вывода полностью аналогичен выводу на экран, только перед именем переменной указывается файловая (текстовая) переменная. close(f); - Закрыть файл. Иначе последняя строка выходного файла может остаться не записанной! Пример: Вычислить среднее арифметическое N целых чисел (N<=1000, числа <=50000). Исходный файл text.in, в котором в первой строке указано N, а затем в столбик записано соответствующее количество чисел. Результат записать в файл text.out . Ответ округлить до сотых. Перед тем, как решать задачу создаем в рабочей папке текстовый файл text.in, в котором в первой строке указываем число N (например, 5, так как сначала надо на простых значениях проверить программу), а далее в столбик набираем соответствующее количество чисел, одно из которых 50000. Вычисляем и записываем среднее арифметическое. А теперь составляем программу:
program prim;
var f:text; {описать переменную f как файл текстового типа}
n,i:integer;
t:longint;
s:real;
begin
assign(f,'text.in'); {связать переменную f с файлом на диске}
reset(f); {открыть файл для чтения}
readln(f,n); {прочитать значение переменной n из файла}
s:=0;
for i:=1 to n do
begin
readln(f,t); {прочитать значение переменной t из файла}
s:=s+t;
end;
close(f); {закрыть файл}
s:=s/n;
assign(f,'text.out'); {связать переменную f с файлом на диске}
rewrite(f); {пересоздать файл}
append(f); {открыть файл для дополнения, в данном случае необязательна, так как rewrite открывает новый файл для чтения, но хуже не будет}
writeln(f,s:0:2); {записать в файл результат}
close(f); {закрыть файл}
end. Вывод: Работа с текстовыми файлами с использованием файловых переменных текстового типа удобна тем, что легко можно организовать параллельный ввод из файла и с клавиатуры и вывод в файл и на экран. Способ более надежен и универсален, но… Если при отладке программы на олимпиаде использовался клавиатурный ввод и экранный вывод (что зачастую удобнее), то перед «сдачей» программы необходимо во все операторы ввода-вывода добавить файловую (текстовую) переменную, если хоть где-нибудь забыли, то… Будьте внимательны!!! 4. Работа с текстовыми файлами с перенаправлением ввода-вывода. Второй способ работы с файлами основан на перенаправлении ввода (зарезервированное слово input) с клавиатуры на текстовый файл и вывода(output) с экрана в файл. В остальном все очень похоже на работу с файловыми переменными, но переменную объявлять не надо. Рассмотрим тот же пример: Вычислить среднее арифметическое N целых чисел (N<=1000, числа <=50000). Исходный файл text.in, в котором в первой строке указано N, а затем в столбик записано соответствующее количество чисел. Результат записать в файл text.out . Ответ округлить до сотых.
program prim;
var n,i:integer;
t:longint;
s:real;
begin
assign(input,'text.in'); {перенаправить ввод с клавиатуры на файл на диске}
reset(input); {открыть файл для чтения}
readln(n); {прочитать значение переменной n из файла}
s:=0;
for i:=1 to n do
begin
readln(t); {прочитать значение переменной t из файла}
s:=s+t;
end;
close(input); {закрыть файл}
s:=s/n;
assign(output,'text.out'); {перенаправить вывод с экрана в файл на диске}
rewrite(output); {пересоздать файл}
append(output); {открыть файл для дополнения, в данном случае необязательна, так как rewrite открывает новый файл для чтения, но хуже не будет}
writeln(s:0:2); {записать в файл результат}
close(output); {закрыть файл}
end. Обратите внимание, что в данном случае формат операторов read, readln, write, writeln полностью совпадает с теми же операторами при отсутствии необходимости работы с файлами. Этот способ позволяет легко перестроить программу от работы с файлами к обычному вводу-выводу и обратно. Но использование совместного ввода-вывода с файлами и с клавиатурой и экраном затруднено. 5. Чтение данных из файла посимвольно. И последнее… В некоторых задачах для работы с длинными числами или абзацами текста необходимо считывать данные из файла посимвольно. В этом случае можно использовать следующие циклы (переменная ch – типа char): 1) До конца строки.while not seekeoln(f) do
begin
read(f,ch);
…
end;
или (при перенаправленном вводе):
while not seekeoln do
begin
read(ch);
…
end; Читает данные из файла посимвольно до конца строки. Функция seekeoln(f) пропускает пробелы, символы табуляции и возвращает True, если файловый указатель стоит на конце строки, и False в противном случае. 2) До конца файла.while not seekeof(f) do
begin
read(f,ch);
…
end;
или (при перенаправленном вводе):
while not seekeof do
begin
read(ch);
…
end; Читает данные посимвольно до конца файла. Функция seekeof(f) пропускает пробелы, символы табуляции и перехода на новую строку, после чего возвращает True, если файловый указатель стоит на конце файла, и False в противном случае. Данные циклы можно применять, если считываются числовые данные (позволяет избежать ошибок при лишних пробелах). При считывании строк, в которых пробелы являются значимыми, данные, скорее всего, придется считывать построчно!
6. Решение задач. Любые задачи решить с использованием файлового ввода-вывода… :-)
|