На главную
Сервис "Обмен садиками" - бесплатный инструмент поиска обмена местами в дошкольных образовательных учреждениях (ДОУ) между детьми одного возраста
Rambler's Top100   Mini-Soft Курсовые Указатели на функции
Разделы сайта:
Образование
Курсовые
  Бесплатные
  Платные
Дипломы
Рефераты
Словари
БЭМТ
БФ НГТУ
Программы
Soft
Исходники
Статьи
MSDN
Библиотека
Инфо
Ссылки
Гостевая книга
Поиск по сайту:
Добавить работу на сайт
Ваше образование
Два высших
Неполное среднее
Среднее
Средне-специальное
Неполное высшее
Высшее
Новые поступления:
Анализ и оценка эффективности использования оборотных активов организации 2011-10-11
Товарные биржи и их значение в коммерческой деятельности торговых предприятий 2011-10-11
Контрольная по ботанике 2011-09-04
Контрольная работа по ботанике 2011-09-04
RSS Все новинки...


Проверить аттестат


Мы принимаем Яндекс.Деньги
 
Курсовая работа по дисциплине "Программирование" -

Указатели на функции


Скачать архив: func_pointers.zip

СОДЕРЖАНИЕ

1. Содержание
2. Задача
3. Теоретический материал
4. Структурное описание разработки
5. Функциональное описание
6. Работа с контрольным примером, вывод
7. Приложение: исходный код программы


Задача

Для заданной в варианте структуры данных, каждый элемент которой содержит указатели на элементы произвольного типа void*, написать итератор. Проверить его работу на примере вызова итератора для структуры данных с соответствующими элементами и конкретной функцией. СД - дерево, каждая вершина которого содержит указатель на элемент данных void* и не более 4 указателей на поддеревья. Итератор поиска первого подходящего firstthat и функция включения в поддерево с минимальной длиной ветви. Проверить на примере элементов данных - строк и функции проверки на длину строки - не менее 10 символов.

Теоретический материал

Рекурсия

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

Деревья

По аналогии с рекурсивным вызовом функции существуют структуры данных, допускающие рекурсивное определение: элемент структуры данных содержит один или несколько указателей на элементы такого же типа. Формально это соответствует тому факту, что в определении структурированного типа содержится указатель на себя самого.
Определение дерева имеет исключительно рекурсивную природу. Элемент этой структуры данных называется вершиной. Дерево представляет собой либо отдельную вершину, либо вершину, имеющую ограниченное число указателей другие деревья (ветвей). Нижележащие деревья для текущей вершины называются поддеревьями, а их вершины -потомками. По отношению к потомкам текущая вершина называется предком.

Указатели на функции

В языке C сами функции не являются переменными, но имеется возможность определить указатель на функцию, который можно обрабатывать, передавать другим функциям, помещать в массивы и т.д.
Указатель на функцию -это производный тип данных, который стоит несколько обособлено от остальных. Указателем на функцию называется переменная, которая содержит адрес некоторой функции. Соответственно, косвенное обращение по этому указателю представляет собой вызов функции. "Оригинальность" такого типа данных как указателя заключается в том, что указуемым элементом является не переменная (компонента данных программы), а функция (компонента алгоритма). Но сущность указателя при этом не меняется: если обычный указатель позволяет параметризовать алгоритм обработки данных, то указатель на функцию позволяет параметризовать сам алгоритм. Так, программа, использующая указатель в качестве параметра, может быть выполнена с произвольным указуемым элементом данных. Аналогично, программа, использующая указатель на функцию в качестве одного из своих параметров, становится универсальной в том смысле, что часть ее алгоритма может быть произвольной и в каждом конкретном случае выражается функцией, передаваемой указателем.

Итераторы

Итератор - функция, которая обрабатывает структуру данных, содержащую переменные произвольного типа, но одинакового в одном экземпляре структуры данных. Действие, которое надлежит выполнить над этими переменными в рамках общего алгоритма, определяется отдельной функцией, передаваемой в итератор как формальный параметр-указатель.

Структурное описание разработки

Построение дерева

Программа запрашивает у пользователя данные, и, интерпретируя их как строки произвольной длины, заносит их в дерево. Вставка в дерево происходит в ближайший к корню свободный узел. Каждый узел имеет четырёх сыновей, если при вставке в текущий узел один из сыновей пуст, вставка произойдёт в него. Если нет - произойдёт рекурсивный спуск к сыновьям - вставка в поддерево с наименьшей высотой.

Обход дерева

Для вывода дерева производится его полный обход. При этом сначала обрабатывается (выводится) сначала текущий узел, а затем происходит рекурсивный спуск к поддеревьям, их обход в направлении от первого к четвёртому. Таким образом, узлы, находящиеся "выше" и "левее" будут выведены раньше тех, что находятся "ниже" и "правее".
По аналогичной схеме дерево обходится и при поиске элемента, первого в дереве удовлетворяющего заданному условию. В качестве условия используется функция типа bool, указатель на которую передаётся функции обхода дерева.

Функциональное описание

- Рекурсивная функция определения высоты поддерева
int depth (tree *node)
Конец рекурсивного спуска происходит, когда текущий узел не имеет сыновей. Приэтом условии функция возвращает 1. Если сыновья есть - идёт вызов функции для каждого, при этом если у какого-то поддерева высота оказалась больше остальных, она запоминается. Возвращается максимальная высота среди поддеревьев + 1.
- Рекурсивная функция вставки в дерево
void insert (tree* node, void *data)
Если у текущего узла находится NULL среди указателей на поддеревья, то указатель перенаправляется на вновь создаваемый узел. У нового узла все указатели на поддеревья приравниваются NULL, а указатель на данные приравнивается аргументу функции data. Если у текущего узла все поддеревья непустые, находится высота каждого из них, и вставка рекурсивно спускается в то поддерево, высота которого минимальна.
- Нажатие на кнопку "Вставить"
void __fastcall TForm1::Button1Click(TObject *Sender)
Происходит проверка - не пусто ли дерево. Если это так, создаётся корень дерева, указатель на него заносится в глобальную переменную-указатель на дерево. Все поддеревья корня помечаются как пустые (NULL), а указатель на данные перенаправляется на динамически созданную копию введённой строки. Если дерево не пусто, также в области динамической памяти создаётся копия введённой строки, указатель на которую передаётся функции вставки. Вставка вызывается для корня дерева.
- Рекурсивная функция вывода содержимого дерева
void print (tree *node)
Для текущего узла происходит вывод данных (строки) в поле вывода. После этого для каждого непустого поддерева рекурсивно вызывается та же функция.
- Нажатие на кнопку "Вывод дерева"
void __fastcall TForm1::Button3Click(TObject *Sender)
Поле вывода очищается, и, если дерево не пусто, вызывается функция вывода для корня дерева.
- Проверка длины строки
bool moren (void *in)
Переданный указатель рассматривается как указатель строки; если длина этой строки не меньше 10, возвращается true, иначе - false.
- Итератор FirstThat - поиск в дереве первого удовлетворяющего условию узла
void *firstthat (tree *node, bool (*condi)(void *))
Переданной с помощью указателя функции проверки выполнения условия передаётся строка из текущего узла. Если условие выполнено, функция возвращает эту строку. Если нет - происходит рекурсивный вызов функции для каждого из непустых поддеревьев. Первый найденный узел, удовлетворяющий заданному условию порождает цепочку рекурсивных возвратов, функция возвращает строку, найденную в поддереве. Если строка, удовлетворяющая условию не найдена, возвращается NULL.
- Нажатие на кнопку "Поиск 1-го"
void __fastcall TForm1::Button2Click(TObject *Sender)
Для корня вызывается итератор FirstThat, результат сохраняется во вспомогательную переменную. Если результат - строка, она выводится, если NULL - выводится сообщение о неудаче.

Работа с контрольным примером, вывод

- Поочерёдно вводятся строки:
"1", "22", "333", "xxxxxxxxxxxxx", "4444", "qqqqqqqqqqqqq", "55555", "4444", "7777777"
- Вывод содержимого дерева даёт следующий результат:
1
22
qqqqqqqqqqqqq
333
55555
xxxxxxxxxxxxx
4444
4444
7777777
- Поиск первой строки, содержащей не менее 10 символов даёт:
qqqqqqqqqqqqq

Использование указателей на функции очень удобно при реализации универсальных программ хранения и обработки данных - каждая функция (вывод, сортировка, поиск) реализуется один раз в общем виде, для каждого типа данных дописываются специфичные функции (сравнение, …). Использованная в этой программе структура данных удобна для программирования, так как имеет рекурсивную природу, экономична (минимизирует высоту дерева), вставка не перестраивает дерево, однако не позволяет эффективно реализовать такие важные функции как поиск, сортировка.

Исходный код

#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
// Структура дерева
struct tree
{
   void *data;    // Указатель на данные
   struct tree *son[4]; // Массив указателей на поддеревья
} *T;
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { }
// Рекурсивная функция определения высоты поддерева
int depth (tree *node)
{
   int cur, max = 0;
   if (!node->son[0] && !node->son[1] && !node->son[2] && !node->son[3])
      return 1;    // Если нет сыновей, высота = 1
   for (int i = 0; i < 4; i++) // Если есть - проход по сыновьям
      if (node->son[i]) // с определением их высот
         {    // и запоминанием максимальной
            cur = depth(node->son[i]);
            if (cur > max)
               max = cur;
         }
   return max + 1;       // Высота больше высоты сына
}
// Рекурсивная функция вставки в дерево
void insert (tree* node, void *data)
{
   tree *next;       // Сюда будем вставлять
   for (int i = 0; i < 4; i++) // Если есть "пустой" сын,
   {          // Вставляем на это место
      if (!node->son[i])
      {
         node->son[i] = new tree;   // Cоздание нового узла
         for (int j = 0; j < 4; j++) // У него нет сыновей
            node->son[i]->son[j] = NULL;
         node->son[i]->data = data; // Запись данных
         return;
      }
   }
   next = node->son[0];    // Начинаем поиск с первого сына
   for (int i = 1; i < 4; i++)
   {
      if (depth(node->son[i]) < depth(next))
         next = node->son[i]; // Выбираем сына с наименьшей высотой
   }
   insert(next, data);    // Рекурсивный спуск в выбранного сына
}
// Нажатие на кнопку "Вставить"
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   if(!T)       // Если дерево ещё не создано
   {       // Оно создаётся,
      T = new tree;
      for(int i = 0; i < 4; i++) // Новое дерево не имеет сыновей
         T->son[i] = NULL;
      char *str = new char[strlen(Edit1->Text.c_str())+1];
      strcpy(str, Edit1->Text.c_str());
      T->data = str; // Запись данных
      return;
   }
   char *str = new char[strlen(Edit1->Text.c_str())+1];
   strcpy(str, Edit1->Text.c_str()); // Выделение памяти и запись строки
   insert(T, (void *) str);// Если дерево есть - вставка в него указателя
}
// Рекурсивная функция вывода содержимого дерева
void print (tree *node)
{
   Form1->Memo1->Lines->Add((char *) node->data); // Вывод строки
   for (int i = 0; i < 4 && node->son[i]; i++) // Проход по сыновьям
      print(node->son[i]); // Рекурсивный спуск - вывод сыновей
}
// Нажатие на кнопку "Вывод дерева"
void __fastcall TForm1::Button3Click(TObject *Sender)
{
   Memo1->Clear();       // Очистка поля вывода
   if (T)          // Если дерево не пусто,
      print(T);    // Вывод, начиная с корня
}
// Проверка: длина строки >= len?
bool moren (void *in)       // На входе - указатель на строку
{
   if (strlen((char *) in) >= 10) // Длина строки - больше 10,
      return true;    // возврат true
   else
      return false;    // иначе - false
}
// Итератор FirstThat - поиск в дереве первого удовлетворяющего условию узла
// На входе - указатель на узел дерева и указатель на функцию-условие
void *firstthat (tree *node, bool (*condi)(void *))
{
   void *first = NULL;    // Временное хранение результата
   if ((*condi)(node->data)) // Проверка условия
      return node->data; // При выполнении - вызврат данных
   for (int i = 0; i < 4 && node->son[i]; i++)
   {          // Иначе - проход по сыновьям
      first = firstthat(node->son[i], condi);
      if (first)    // Если для одного из сыновей условие
         return first; // выполнено - возврат данных
   }
   return NULL;       // Условие не выполнено ни в одном узле
}
// Нажатие на кнопку "Поиск 1-го"
void __fastcall TForm1::Button2Click(TObject *Sender)
{
   void *first = firstthat(T, &moren); // Поиск с помощью итератора
   if (first)          // Если узел найден -
      ShowMessage((char *) first); // вывод данных
   else             // Иначе - сообщение о неудаче
      ShowMessage("Строка длиной не менее 10 символов не найдена.");
}

Вам помог данный материал: Да | Нет
Rambler's Top100   Mini-Soft Курсовые Указатели на функции
О проекте Mini-Soft.ru   Реклама на сайте
Copyright © Mini-Soft 2003-2009 mini-soft@narod.ru