- •Оглавление
- •Часть 1. Краткое описание Delphi 8
- •Часть 2. Технология ado для баз данных access 186
- •9.1. Общие сведения 289
- •Введение
- •Часть 1. Краткое описание Delphi
- •1. Работа со средой delphi
- •1.1. Ознакомление с delphi
- •1.2. Вкладка дизайнера формы (design)
- •1.3. Вкладка редактора кода программы
- •1.4. Окно object inspector
- •1.5. Окно project manager
- •1.6. Окно палитры инструментов
- •1.7. Создание первого проекта приложения
- •1.8. Сохранение проекта
- •1.8. Сохранение проекта
- •1.9. Компиляция
- •2. Основа языка delphi
- •2.1. Основные понятия языка
- •2.1.1. Элементы языка
- •2.1.2. Пример простой программы
- •2.1.3. Типы данных
- •2.1.4. Операции и выражения
- •2.1.5. Стандартные функции
- •2.1.6. Ввод и вывод на дисплей
- •2.1.7. Оператор присваивания
- •2.2. Операторы языка паскаль
- •2.2.1. Составной оператор
- •2.2.2. Условный оператор
- •2.2.3. Сложные условия
- •2.2.4. Оператор выбора case
- •2.2.5. Оператор цикла for
- •2.2.6. Оператор цикла while
- •2.2.7. Оператор цикла repeat
- •2.2.8. Вложенные циклы
- •2.2.9. Прочие операторы
- •2.3. Общая структура программы
- •2.3.1. Перечень разделов программы
- •2.4. Массивы
- •2.4.1. Одномерные массивы
- •2.4.2. Сортировка массивов и поиск элемента в массиве
- •2.4.3. Многомерные массивы
- •2.5. Функции и процедуры
- •2.5.1. Описание функций
- •2.5.2. Обращение к функции
- •2.5.3. Процедуры
- •2.5.4. Параметры-значения и параметры-переменные
- •2.5.5. Локальные и глобальные переменные
- •2.5.6. Pекурсия
- •2.6. Строки символов
- •2.6.1. Задание строк
- •Var имя: string[длина];
- •2.6.2. Функции и процедуры для обработки строк
- •2.7. Порядковые типы данных
- •2.7.1. Перечисляемый тип данных
- •2.7.2. Интервальный тип данных
- •2.7.3. Порядковые типы данных
- •2.7.4. Дополнение:тип данных tDateTime (дата-время)
- •2.8. Множества
- •2.8.1. Значения типа множество
- •2.8.2. Операции на множествах
- •2.9. Записи
- •2.9.1. Поля записи
- •2.9.2. Оператор with
- •2.9.3. Последовательный поиск в массиве записей
- •2.9.4. Двоичный поиск в массиве записей
- •2.10. Файлы
- •2.10.1. Основные свойства файлов
- •2.10.2. Типизированные файлы
- •2.10.3. Текстовые файлы
- •2.10.4. Поиск файлов
- •2.11. Динамическая память
- •2.11.1. Динамические переменные и указатели
- •2.11.2. Динамические списки
- •2.11.3. Деревья
- •2.12. Программные модули
- •2.12.1. Модули, формируемые пользователем
- •2.12.2. Стандартные модули
- •2.12.3. Примеры программ
- •3. Главная форма
- •3.1. Свойства главной формы
- •3.2. События главной формы
- •4. Описание некоторых компонентов
- •4.1. Компонент tpanel (панели)
- •4.2. Компонент tbutton (кнопка)
- •4.3. Дополнительные кнопки
- •4.4. Компонент tlabel (надписи)
- •4.5. Компонент tedit (Строки ввода)
- •4.6. Компонент тМето (многостроч. Поле ввода)
- •4.7. Свойства и методы класса tstrings
- •4.8. Компонент checkbox (флажок)
- •4.9. Компонент tradiobutton (кнопки выбора)
- •4.10. Компонент MainMenu (главное меню программы)
- •4.11. Компонент timage
- •4.12. Компонент tstringgrid (сетка)
- •4.13. Компонент ttimer(таймер)
- •5. Отладка программ
- •5.1. Типы ошибок
- •5.2. Отладка программы
- •5.2.1. Трассировка программы
- •5.2.2. Точки останова программы
- •5.2.3. Наблюдение значений переменных
- •Часть 2. Технология ado для баз данных access
- •6. Создание баз данных access
- •6.1. Определение понятия баз данных
- •6.2. Интерфейс программы access
- •6.3. Создание базы данных в access 2007
- •6.3.1. Создание двухтабличной базы данных
- •6.3.2. Создание базы данных с вычисляемыми полями
- •6.4. Выбop формата для новой базы данных
- •6.5. Создание пустой базы данных
- •6.6. Открытие и закрытие базы данных
- •6.7. Создание таблиц в режиме конструктора
- •6.7.1. Выбор первичного ключа
- •6.7.2. Изменение полей и таблиц
- •6.7.3. Копирование полей
- •6.7.4. Перемещение полей
- •6.7.5. Удаление полей
- •6.7.6. Операции с таблицами
- •6.8. Создание базы данных в access 2003
- •6.9. Установление связей между таблицами
- •6.10. Обеспечение целостности записей в базе данных
- •6.11. Редактирование и удаление связей
- •7. Система доступа к данным ado
- •7.1. Общие сведения
- •7.2. Компонент adoConnection
- •7.2.1. Свойства компонента adoConnection.
- •7.2.2. Методы компонента adoConnection
- •7.3.Компонент аdоТable
- •7.3.1. Свойства компонента tadoTable
- •7.3.2. Методы компонента tadoTable
- •7.4. Компонент adoQuery
- •7.5. Компонент adoDataSet
- •7.5.1.Свойства компонента adoDataSet
- •7.5.2. Методы компонента adoDataSet
- •7.5.3. Cобытия компонента adoDataSet
- •7.6. Компонент DataSource
- •7.7.Комнонент DataGrid
- •7.7.1 Cвойства компонента DataGrid
- •7.7.2. Методы и события компонента DataGrid
- •7.8. Компонент adocommand
- •8. Управление базами данных
- •8.1. Приложение для управления базами данных
- •8.2. Свойства полей базы данных
- •8.3. Редактирование базы данных
- •8.4. Сортировка данных
- •8.5. Поиск данных в базе
- •8.5.1. Фильтрация данных в базе
- •8.5.2. Нахождения информации методом Locate
- •9.1. Общие сведения
- •9.2. Основные операторы запроса
- •9.2.1. Агрегатные функции
- •9.2.2. Подзапросы
- •9.3. Операторы наполнения баз данных sql
- •9.3.1. Ввод значений
- •9.3.2. Удаление значений
- •9.3.3. Изменение значений
- •9.4. Операторы создания баз данных sql
- •9.4.1. Команда создания таблицы.
- •9.4.2. Первичные ключи таблицы
- •9.4.3. Индексы таблицы
- •9.4.4. Добавление в таблицу новых столбцов
- •10. Реализация sql- запросов
- •10.1. Компонент tadoQuery для sql- запросов
- •10.2. Форма для реализация sql-запроса
- •11. Генератор отчетов Quick Reports
- •11.1.Описание Quick Reports
- •11.2. Печать записи с помощью Quick Reports
- •11.3. Печать таблиц с помощью Quick Reports
- •394026 Воронеж, Московский просп., 14
2.5.6. Pекурсия
Понятие, которое частично определяется через самого себя, называется рекурсивным Например, о факториале числа. N можно сазать, что
либо
N! = 1 * 2 *.. * (N-1) * N, или 1, если N = 1;
либо
N1= 1. если N=1 или N1 = (N - 1)! * N..
Второе определение — рекурсивное,
Любое рекурсивное определение состоит из двух частей. Одна часть определяет понятие через него же. Другая часть — через иные понятия
Рекурсивный алгоритм - эти алгоритм, который при вычислениях. обращается сам. к себе. Например, вычисление функции F(M) может потребовать вычисления F(M—I) и еще каких-то операций. Иными словами, частью алгоритма вычисления функции будет вычисление этой же функции с другими аргументами.
Записать рекурсивный алгоритм на Паскале можно при помощи рекурсивной процедуры. Процедура является рекурсивной, если она обращается сама к себе прямо или косвенно:(через другие процедуры (рис 2.2).
Рис. 2.2
Заметим, что при косвенном обращении все процедуры в цепочке — рекурсивные.
Все сказанное о процедурах целиком относится и к функциям.
Вернемся к рекурсивному определению факториала. Достаточно переписать его на Паскале и получится описание рекурсивной функции.
Пример. Рекурсивное вычисление факториала.
function Factorial (М: integer): integer ;
begin
If N = 1 then
Factorial := 1 else
Factorial := Factorial (N—1) * N end;
Следует иметь в виду, что в рекурсивной процедуре обязательно должна быть предусмотрена возможность прекратить дальнейший самовызов и начать обратный процесс.
Kак правило, это делается: при помощи условного оператора.
Пример. Возведение действительного числа X в целую степень N.
procedure Power (X: real; N: integer; var Y: real);
begin
if N = O then Y:= 1
else
begin
Power (X,N-1,Y); Y:=Y*X
end;
end;
Вызов процедурой самой себя ничем не отличается от вызова другой процедуры. Проследим за процессом выполнения вызова Power (4, 3, Y).
вызывается Power(4,3,Y); вызывается Power(4,2,Y); вызывается Power(4,l,Y);
вызывается Power(4,0,Y);
завершается Power(4,0,Y); (* Y равен 1*) завершается Power(4,l,Y); (* Y равен 4*) завершается Power(4,2,Y); (* Y равен 16*) завершается Power(4,3,Y); (* Y равен 64*)
Количество вызовов процедурой самой себя называется глубиной рекурсии. Как видно из примера, сначала она растет, потом сокращается.
Если рекурсивная процедура имеет локальные переменные, то они сохраняют свои значения для каждого вызова процедурой самой себя.
Пример. Ввести строку символов и вывести ее в обратном направлении.
Program reverse_string;
procedure reserve; var ch, char;
begin
while not eoln do begin
read(ch);
reserve;
write(ch);
end;
end;
begin reserve;
end.
Здесь используется стандартная функция EOLN, которая возвращает TRUE, если при вводе с клавиатуры считаны все символы строки и FALSE - в противном случае.
Процедура RESERVE считывает один символ и если строка не закончена, то вызывает себя снова. При этом в памяти ЭВМ будет сохранено столько копий локальной переменной ch, какова глубина рекурсии.
Каждая копия ch будет хранить один символ из строки и затем, в процессе выхода из рекурсии, они будут выводиться на экран.
При этом символ, введенный последним, выведется первым, введенный предпоследним - выведется вторым и так далее.
При отсутствии рекурсии необходимо было бы иметь переменную типа string (см. далее) для хранения введенной строки, в рекурсивной процедуре в этом нет необходимости.
Применение рекурсии упрощает как алгоритм решения задачи, так и используемые структуры данных.
Таким образом, при рекурсивном вызове процедуры в памяти автоматически сохраняются все наборы локальных переменных для всех выполняемых процедур.
Это, с одной стороны, упрощает алгоритм, так как не надо явно сохранять все переменные (это происходит автоматически), а с другой - это часто ведет к избыточному расходу памяти ЭВМ.
Все рассмотренные примеры просты и легко выполняются без использования рекурсии.
Рассмотрим задачу, где применение рекурсии позволяет существенно упростить алгоритм.
Задача заключается в получении всех перестановок N элементов. Известно, что число таких перестановок равно N!. В качестве таких элементов будем рассматривать целые числа от 1 до N. Например, для N=3 нужно получить 3! = 6 перестановок
123
213
132
312
231
321
Это реализуется рекурсивной программой
program rearrangement;
type mas 1 = array [1.. 10] of integer;
var i,n: integer;
p:masl; procedure reverse(m:integer);
var i,j,tmp:integer;
begin
i:=l;j:=m;
while i<j do
begin
tmp:=p[j];
p[j]:=p[i];
p[i]:=tmp;
i:=i+l;
j:=j-i;
end;
end;
procedure rearrange(m:integer);
var i,j,tmp:integer;
begin
if m=l then
begin
for j:=l to n do write(p[i]],''); writeln;
end
else
for i:=l to m do
begin
rearrange(m-l);
if i<m then
begin
tmp:=p[m]; p[m]:=p[i]; p[i]:=tmp;
reverse(m-l);
end;
end;
end;
begin
Write ('Введите длину перестановки ');read(n);
for i:=l to n do p[i]:=i;
rearrange(n);
end.