- •Федеральное агенство по образованию
- •Оглавление
- •Массивы указателей на строки Задание 1. Текстовый редактор Задание 1.1 Динамическая память. Модульное программирование
- •Задание 1.2 Реализация таблицы на основе динамического массива
- •Задание 1.3 Специальные функции работы со строками
- •Задание 1.3 Разработка приложенияWindowsForms
- •Структуры Задание 2 Реализация текстового редактора с использованием структур данных Задание 2.1 Представления набора строк в виде структур данных
- •Задание 2.2 Реализация операций выборки, преобразования и сортировки наборов строк с использованием словаря данных
- •Задание 3. Информационная система
- •Задание 3.1 Модульное программирование
- •Задание 3.2 Работа с и динамической памятью
- •Задание 3.3 Ввод и вывод
- •Пример реализации для консольного приложения
- •Пример реализации для приложения с оконным графическим интерфейсом
- •Задание 3.4 Сравнение структур
- •Задание 3.5 Консольное приложение
- •Задание 3.5 Приложение WindowsForms
- •3.6 Пример пошаговой разработки приложение WindowsForms
- •Классы. Задание 4. Объектно-ориентированная реализация текстового редактора
- •Задание 4. 1 Разработка класса классаMyString.
- •Задание 4. 2 Разработка класса таблица.
- •Задание 5. Объектно-ориентированная реализация информационной системы Задание 5.1 Представление структуры данных записи (Record), в виде класса с конструкторами и деструкторами
- •Задание 5. 2 Разработка класса таблица для хранения объектов классаRecord.
- •Задание 5.3 Представление базовых понятий предметной области в виде классов. Разработка интерфейса и реализации. Определение конструкторов классов.
- •1. Разработать класс MyDate (дата-время)
- •3. Дополнить класс MyString (строка)
- •4. Разработать класс Title (название)
- •5 . Разработать класс Name (имя)
- •6. Разработать класс Address (Адрес)
- •7. Разработать класс Telephone ( номер телефона)
- •8. Разработать класс e_Mail (Адрес электронной почты)
- •Задание 5.2 Использование объектов классов в качестве элементов классов
- •Задание 5.3 Использование указателей на объекты классов и объекты классов в качестве элементов классов
- •Задание 5.4 Система управления данными.
- •Задание 5.5 Иерархия классов
- •Задание 5.6 Шаблоны классов
- •Приложение 1
- •Приложение 2
- •Приложение 3
- •В среде разработки Visual Studio .Net (массивы строк, структуры, классы)
Задание 3.4 Сравнение структур
В функциях поиска, удаления, замены исползуется функция сравнения на равенство двух структур. В отличие от сравнения строк для сравнения структур могут использоваться различные алгоритмы.
Пример реализации функции, определяющей совпадения структур по всем непустым полям
int equal(Record* t, Record* r)
{ return ((r->autor[0] !=0)? !strcmp(r->autor,t->autor):1) &&
((r->title && r->title[0] !=0)? !strcmp(r->title, t->title) :1) &&
((r->price !=0)? r->price ==t->price :1) &&
((r->number !=0)? r->number==t->number :1)&&
((r->day !=0)? r->day==t->day :1)&&
((r->month !=0)? r->month==t->month :1)&&
((r->year !=0)? r->year==t->year :1);
}
Функция, сравнивающая записи, используется при сортировки .
Пример реализации функции, сравнивающей структуры по первым трем полям
int cmp(Record* r, Record* t)
{int cond;
if(t->autor[0]!=0 && (cond=strcmp(r->autor,t->autor))) return cond;
else if(t->title[0] !=0 &&(cond=strcmp(r->title, t->title)) ) return cond;
else return r->number-t->number;
}
Указатели на функции
Использавание одной функции сmp для сравнения записей обладает существенным недостатком. Для проведения поиска по другим полям необходимо изменять функцию сравнения и перекомпилировать код.
Применение указателей на функцию позволяет построить более универсальную программу, поскольку указатель это переменная, которая соотвественно может принимать множество значений. В качестве значений можно использовать адреса нескольких заранее определенных функций сравнения.
Кроме того, для поиска и сортировки необходимо использовать разные функции. При поиске в качестве критерия отбора необходимо использовать булевскую функцию, аргументом которой является один элемент (предикат первого порядка)., а для сортировки – булевскую функцию , определенную на паре элементов (предикат второго порядка). Более того, эти булевские функции могут содержать аргумент, через который передаются дополнительные параметры, например данные для поиска. Для того чтобы функции не зависили от типа данных можно тип параметра определить как vod*. В языке Си использование указателей на функции совместно с типомvod* является единственным средством построения полиморфных ,т.е. независящих от типа данных, програм . В языке С++ для этих целей применяется наследование классов и фиртуальные функции, а также шаблоны.
Поиск
Определим заголовок функции поиска следующим образом
T* find(Tabl* t,Pr fun=0 ,void* param=0, T*begin=0)
Для согласование с ранее разработанным интерфейсом используются параметры по умолчанию
Функция ищет по заданному условию запись в таблице T, начиная с элемента на который указываетbegin. Введение этого параметра позволяет осуществить поиск следующего элемента. Данные для поиска передаются через аргумент с именемparam.Параметр функцииfindс именемfun– это указатель на функцию, сравнивающую запись с параметрами поиска. Тип указателя нfфункцию определяется следующим образом
typedefbool(*Pr)(Record*,void*); строка добавляется в заголовочный файл
Использование указателя на функцию сравнения и задание параметров поиска в виде void* позволяет использовать одну и ту же функцию для различных условий поиска. В качестве второго параметра можно использовать любую структуру с данными для поиска. При реализации функций необходимо явное приведения указателяvoid* к типу указателя на структуру поиска.
В приведенном ниже примере в качестве данных для поиска используется структура Record. Поля , по которым поиск не проводится остаются пустыми. По всем другим полям необходимо совпадение с данными поиска. Напишите другой вариант функции, которая ищет записи , хотя бы одно поле которых совпадает с данными поиска.
Пример функции , определяющей совпадения записей по непустым полям
bool EqualParam (Record*t, void*)
{ record*r=(Record*)r0;
return equal (t, r);
}
В другом примере в качестве параметра используется структура
struct InRange{
int MinValue,MaxValue;
};
bool InRangePrice(Record* item, void* param)
{InRange *p=(InRange *)param;
return (item->price-p->MinValue)>=0 && (item->price-p->MaxValue)<=0;
}
Cортировка
Определим заголовок функции сортировки следующим образом
void sort(Tabl* t,Cmp fun=0,void* param=0);
Параметр функции с именем fun– это указатель на функцию, сравнивающую два элемента. Тип указателя на функцию определяется следующим образом
typedefbool(*Cmp)(constT&,constT&,void*param);
Примером такой функции может служить функция, сравнивающая записи по полю , имя которого передается через параметр
int CmpField(Record* a,Record* b,char*s)
{if (!strcmp(s,"autor")) return strcmp(a->autor,b->autor);
else if(!strcmp(s,"title")) return strcmp(a->title,b->title);
else if (!strcmp(s,"price")) return a->price-b->price;
else if (!strcmp(s,"number")) return a->number-b->number;
else if (!strcmp(s,"day")) return a->day-b->day;
else if (!strcmp(s,"month")) return a->month-b->month;
else if (!strcmp(s,"year")) return a->year-b->year;
}
При вызове функции sortнеобходимо использовать приведение типа.
Sort(t, (Cmp) FieldCmp,(void*)string);
В другом примере в качестве параметра используется структура
struct ParamSort {
char* FieldName[3];
int DirectCond[3];
};
Она позволяет задавать произвольные три поля для сравнения и направление сортировки (по возрастанию или по убыванию)
int CmpParam( Record* a, Record* b,void* param)
{ParamSort*p=(ParamSort*)param;
if(CmpField(a,b,p->FieldName[0])!=0)
if(p->DirectCond[0]==1) return CmpField(a,b,p->FieldName[0])>0;
else return CmpField(a,b,p->FieldName[0])<0;
else if(CmpField(a,b,p->FieldName[1])!=0)
if(p->DirectCond[1]==1) return CmpField(a,b,p->FieldName[1])>0;
else return CmpField(a,b,p->FieldName[1])<0;
else if(CmpField(a,b,p->FieldName[2])!=0)
if(p->DirectCond[2]==1) return CmpField(a,b,p->FieldName[2])>0;
else return CmpField(a,b,p->FieldName[2])<0;
}
Функции - элементы структур
Язык С++ позволяет использовать в качестве элементов структур функции. Это делает возможным объединить данные и обрабатывающие их функции в единое целое.
Для данной программы это можно применить в функциях поиска, удаления, замены , где в качестве параметра передавать единый структурный тип данных
struct Predicate{
void* param;
Pr f;
bool fun( Record* item){return (*f)(item,param);}
};
int find( Tabl*t,int first,int last,Predicate &pred);
int remove(Tabl*t,Predicate &pred);
Изменения в реализации произойдут только в одной строке
int find( Tabl*t,int first,int last,Predicate &pred)
{T* i;
for(i=begin(t)+first;i!=begin(t)+last;i++)
if(pred.fun(*i)) return i-t->m;
return -1;
}
Аналогично для функции сортировки
struct Compare{
void* param;
Cmp f;
int cmp( Record* a, Record* b)
{return (*f)(a,b,param);}
};
void sort(Tabl*t,Compare &Comp );
Выполнение запросов.
Программа должна выполнять несколько запросов для поиска набора записей , удовлетворяющих произвольным критериям поиска. В отличии от функции поиска функция, выполняющая запрос, возвращает не одну запись, а весь набор записей, удовлетворяющих заданному условию, в виде таблицы.
Реализация функции, выполняющий запрос, выглядит следующим образом
Tabl* Query(Tabl*t, Predicate& pred)
{Tabl*rez=init(t,24);
T* i;
for( i= begin(t); i!=end(t);i++)
if(pred.fun(*i))
insert(rez,*i);
return rez;
}