- •Содержание
- •Рекомендации к проведению лабораторных работ
- •Комментарии в тексте программы
- •Компиляция и запуск программы на выполнение
- •Переменные и константы
- •Операторы и выражения
- •Оператор присваивания
- •Арифметические операции
- •Логические операции
- •Составной оператор begin..end
- •Условный оператор if..then
- •Оператор-селектор case..of
- •Операторы обработки циклов
- •Цикл с параметром for .. do
- •Цикл с предусловием while..do
- •Цикл с постусловием repeat..until
- •Процедуры break и continue
- •Оператор with..do
- •Процедуры и функции
- •Процедуры
- •Функции
- •1. Фундаментальные структуры данных
- •Общее понятие типа данных
- •Простой тип
- •Перечислимые типы данных
- •Поддиапазонны
- •Строковый тип
- •Структурные типы
- •Массивы
- •Записи
- •Множества
- •Представление структур в памяти
- •Задание
- •2. Работа с последовательностями, файлы
- •Доступ к файлу
- •Операции над файлами
- •Окончание файла
- •Пример работы с файлом
- •Задание
- •3. Анализ алгоритмов
- •Рост функций
- •Задание
- •4. Простейшие методы сортировки массивов
- •Оценка алгоритмов сортировки
- •Шейкер-сортировка
- •Сортировка простыми вставками
- •Сортировка бинарными вставками
- •Задание
- •5. Улучшенные методы сортировки массивов
- •Сортировка с помощью включений с уменьшающимися расстояниями (сортировка Шелла)
- •Пирамидальная сортировка
- •Сортировка с разделением (быстрая сортировка)
- •Задание
- •6. Сортировка последовательных файлов
- •Сортировка простым слиянием
- •Естественное слияние
- •Задание
- •7. Рекурсивные алгоритмы
- •Сравнение рекурсии и итерации
- •Задание
- •8. Динамические структуры данных, связные списки
- •Списки
- •Пример создания и заполнения списка
- •Задание
- •9. Нелинейные структуры данных
- •Граф
- •Бинарное дерево
- •Задание
- •10. Алгоритмы на графах
- •Алгоритмы обхода в глубину и по уровням
- •Построение минимального остовного дерева
- •Поиск кратчайшего пути
- •Задание
- •11. Поиск данных
- •Двоичный (бинарный) поиск элемента в массиве
- •Интерполяционный поиск элемента в массиве
- •Алгоритм Бойера-Мура
- •Задание
- •12. Хеширование
- •Отечественный стандарт хеширования
- •Создание хеш-функции
- •Хеш-функции для строковых значений, алгоритм Гонера
- •Задание
- •13. Методы сжатия текстовых данных
- •Метод “Running”
- •Словарные методы сжатия
- •Алгоритм Хаффмана
- •Задание
- •14. Алгоритмы вывода графических примитивов
- •Рисование отрезка
- •Прямое вычисление координат
- •Инкрементный алгоритм Брезенхэма
- •Простейший алгоритм закрашивания замкнутой области
- •Задание
- •15. Псевдослучайные последовательности
- •Метод середин квадратов
- •Линейный конгруэнтный метод
- •Генератор псевдослучайных чисел, поставляемый с системой
- •Оценка качества генератора ПСП
- •Задание
- •16. Параллельные алгоритмы
- •Пример многопоточного приложения
- •Задание
- •Задание на СКР
- •Вариант 1. Клеточные автоматы
- •Вариант 2. Раскрашивание карты
- •Вариант 3. Крисс-кросс
- •Вариант 4. Лабиринт
- •Список использованной литературы
- •Приложение A. Справочник по функциям Delphi
- •Операции с порядковыми типами
- •Математические функции и процедуры
- •Генерация псевдослучайного числа
- •Преобразование типов данных
- •Работа с памятью
- •Приложение Б. Компонент-сетка TStringGrid
- •Приложение В. Компонент-диаграмма TChart
- •Приложение Д. Элементарный поток – класс TThread
24
2. Работа с последовательностями, файлы
Вид занятия – лабораторная работа Цель – исследование особенностей последовательного хранения данных
Продолжительность – 4 часа
Общее свойство структур данных, которые рассматривались на прошлом занятии, а именно массива, записи и множества, заключается в том, что их кардинальное число конечно. Это значительно упрощает процесс разработки программы.
Большинство так называемых усложненных структур: последовательности, деревья, графы и т. д.
–характеризуются тем, что их кардинальные числа бесконечны. Как следствие:
1.Объем памяти, необходимый для размещения структуры усложненного типа, неизвестен во время трансляции.
2.Объём памяти под данные может изменяться во время выполнения программы.
Если размер данных заранее неизвестен и может динамически изменяться в ходе выполнения кода, то наиболее простым способом их размещения в памяти станет последовательное хранение, будто бы это пачка листов бумаги в которую вы каждый раз докладываете очередной лист.
Последовательность, хранящая данные одного типа, работающая на основе ограниченного множества операторов и предоставляющая строго последовательный доступ к её компонентам называется последовательным файлом или просто файлом.
Смысл последовательного доступа заключается в том, что в каждый момент доступна лишь одна определённая компонента последовательности. Как следствие из этого:
1.Позиция в последовательности может меняться, определяя лишь следующую компоненту, либо первую компоненту всей последовательности (см. рис. 2.1).
2.Процессы формирования и чтения последовательности не могут выполняться совместно. Поэтому последовательность должна находиться либо в режиме записи либо в режиме чтения.
x = x1, x2 ,..., |
|
, xn−1, xn |
Рисунок 2.1.– Изменение позиции последовательности
Доступ к файлу
Сточки зрения программирования файлы можно классифицировать на:
1.Двоичные (бинарные).
2.Текстовые.
3.Типизированные.
Синтаксис объявления файла в языке Delphi выглядит следующим образом:
var F : File of <тип файла>;
Например:
var |
: file; |
//двоичный файл |
Bin_File |
||
Txt_File |
: Textfile; |
//текстовый файл |
Int_File |
: file of Integer; |
//файл целых чисел |
|
|
|
25
Real_File : |
file |
of |
Real; |
//файл вещественных чисел |
Record_File : |
file |
of |
TPoint; |
//типизированный файл |
Предлагаю вашему вниманию стандартный каркас исходного кода по работе с файлом, на который рекомендуется опираться вне зависимости от типа файла.
var F : file; begin
AssignFile(F,'C:\MyFile.dat'); //Связывание файловой переменной F с файлом
TRY
//Секция для потенциально опасных операций над файлом
FINALLY
CloseFile(F); //Закрытие файла и освобождение переменной
END; end.
Прокомментирую эти строки. Нами объявлена файловая переменная с именем F. Самая первая процедура, встретившаяся в листинге, предназначена для связывания файловой переменной F с именем файла FileName. Эту процедуру дальше станем называть процедурой инициализации базовых операций ввода-вывода.
procedure AssignFile(var F; FileName: string);
Теперь файловая переменная в состоянии держать связь с эти файлом до тех пор, пока не будет освобождена. Для разрыва связи и освобождения занятых ресурсов необходим вызов процедуры закрытия файла.
procedure CloseFile(var F);
Указанный метод завершает операции ввода-вывода. Обе процедуры всегда применяются в паре, и если в программе был осуществлён вызов AssignFile(), то в заключении позаботьтесь и об обязательном вызове CloseFile(). Однако, при работе с файлом всегда высока вероятность возникновения целого спектра самых разнообразных ошибок, которые могут привести к возникновению исключительной ситуации. Именно по этому в примере процедура закрытия вынесена в секцию finally обработчика ошибки try..finally. Такой подход гарантирует, что даже при возникновении ошибок файловая переменная гарантированно освобождается.
Операции над файлами
Все действия с последовательными файлами можно свести к 4-м операциям.
Первая операция создаёт пустую последовательность. Она реализуется с помощью процедуры:
procedure Rewrite(var F: File [; RecSize: Word ] );
Будьте осторожны! Если файловая переменная F ссылается на файл с данными, то указанный файл будет перезаписан и потеряет всю информацию!
Вторая операция увеличивает последовательность. Благодаря этому последовательность получает приращение на одно значение. На основе данной операции построен механизм записи данных в последовательный файл. Для текстовых файлов:
procedure Writeln([ var F: Text; ] V1 [, V2, ...,Vn ]);
Процедура добавит в файл F текстовую строку. Кроме того, для текстовых и типизированных файлов допускается применять процедуру:
procedure Write( [var F: Text; ] P1 [ , P2,..., Pn] );
На этот раз процедура добавит в конец последовательности одно значение. Например, если речь идёт о целочисленном файле, то добавится целое число. Для двоичных файлов подойдёт процедура:
procedure BlockWrite (var f: File; var Buf; Count: Integer);
Второй аргумент Buf служит буфером, в который мы помещаем данные. Третий аргумент Count указывает сколько байт из буфера следует передать в файл.
26
Третья операция применяется в случаях, когда мы планируем считать данные из файла, она называется “инициация просмотра”. На практике для этого потребуются услуги процедуры:
procedure Reset(var F: File; [RecSize: Word ] );
Четвёртая операция позволяет осуществлять переход к следующей компоненте файла. В Delphi, для таких целей применяется процедура:
procedure Seek(var F; N: Longint);
Первый аргумент данного метода (как, впрочем, и всех других методов ввода-вывода) требует передачи файловой переменной. Второй параметр определяет – в каком месте файла мы собираемся оказаться.
На законный вопрос: “А как узнать в каком месте находится указатель в настоящий момент?” нам ответит ещё одна функция:
function FilePos(var F): Longint;
К четвёртой операции с файлами прямое отношение имеет действие, связанное с чтением данных из файла, ведь каждая операция чтения тоже приводит к переходу к очередной компоненте последовательности.
Для чтения целой строки из текстового файла применяем процедуру:
procedure Readln([ var F: Text; ] V1 [, V2, ...,Vn ]);
Для текстовых и типизированных файлов, кроме того, подойдёт процедура:
procedure Read( [ var F: Text; ] V1 [, V2,...,Vn ] );
Она производит чтение порциями, по одному элементу.
Для двоичных файлов допускается применить операцию поблочного чтения:
procedure BlockRead (var F: File; var Buf; Count: Integer);
Параметры процедуры аналогичны параметрам, применяемым в рассмотренной выше BlockWrite(), с той лишь разницей, что сейчас мы читаем данные из файла.
Окончание файла
При просмотре последовательности важно уметь распознавать её окончание, поскольку операция чтения за пределами последовательности приводит к ошибке. Для этой цели воспользуйтесь функцией:
function Eof(var F): Boolean;
В случае если достигнуто окончание файла, функция возвратит значение true, во всех остальных случаях – false.
На законный вопрос: “А как узнать в каком месте находится указатель в настоящий момент?” нам ответит ещё один метод:
function FilePos(var F): Longint;
И если указатель ссылается на начало файла, то функция вернёт нулевое значение, а если на конец, то возвратится значение FileSize (). Этот метод проинформирует программиста о количестве записей в типизированном файле:
function FileSize(var F): Integer;
Чтобы нам не выйти за пределы типизированного файла при его чтении стоит использовать следующую заготовку кода:
while FilePos(F)<>FileSize(F) do begin
Read(F, Буферная_Переменная); //другие операции
end;
27
Пример работы с файлом
Рассмотрите два приёма работы с типизированным файлом. В первом листинге мы создаём файл типизированный типом данных Integer и заполняем его 10 элементами.
program ...; {$APPTYPE CONSOLE} uses SysUtils;
var I : INTEGER; F : File Of INTEGER; begin
AssignFile(F,'C:\int.dat'); {связывание файловой переменной с именем файла} Rewrite(F); //создание файла
TRY
For I:=1 to 10 do
Write(F,I); //внесение значений в файл
FINALLY
CloseFile(F); //закрытие файла
END; end.
Второй листинг демонстрирует процесс чтения из файла данных.
var I : INTEGER; F : File Of INTEGER; begin
AssignFile(F,'C:\int.dat'); {связывание файловой переменной с именем файла} Reset(F); //подготовка файла к чтению
TRY
WHILE EOF(F)<>TRUE do //контролируем окончание файла begin
Read(F,I); //внесение 10 значений в файл
WriteLn(I); //вывод на экран
End;
FINALLY
CloseFile(F); //закрытие файла
END;
ReadLn; end.
Задание
1.Разработайте процедуру, заполняющую файл “A” произвольным количеством случайных вещественных чисел REAL в диапазоне от -100.0 до 100.0.
2.Разработайте процедуру выводящие на экран данные из произвольного файла, типизированного типом данных REAL. Проверьте её работоспособность на файле “A”.
3.Разработайте процедуру, декомпозирующую файл из первого задания следующем образом: целая часть значений передаётся в файл “B”, дробная направляется в файл “С”.
4.Разработайте процедуру, объединяющую целую и дробную части из файлов “B” и “C” (см. задание 3) в файл “D”.
5.Разработайте процедуру, позволяющую вывести содержание файла “A” в обратной последовательности и сохраните полученные данные в файл “E”.
6.Разработайте процедуру, позволяющую конвертировать файл “A” к типизированному файлу следующего вида:
a.поле порядкового номера;
b.поле, хранящее признак отрицательного или положительного значения;
c.поле, содержащее исходное значение по модулю.
Сохраните результат в файле “F”.
Примечание: При выполнении заданий не следует пользоваться услугами массивов!