Лабораторная работа 14 / отчет 1
.docСанкт-Петербургский Государственный Электротехнический Университет им.Ульянова (Ленина)
«ЛЭТИ»
каф. МОЭВМ
Лабораторная работа №1
«Программирование контейнерных классов»
Вариант 1 и 15
Выполнила
Студентка гр. 3341
Филиппова К.С.
Проверил
доц. Спицин А.В.
2007
1. Разработка программ в среде MS Visual C++.
1.1. Настройка среды. Выполнение индивидуального задания.
Задание:
-
Найти проекты MFC Tutorial. Откомпилировать и выполнить пример TrialRun.
-
Написать классы для создания графических объектов. Классы должны иметь общий абстрактный базовый класс Shape с чистыми виртуальными функциями.
Реализуемые классы: квадрат, прямоугольник, текст, текст в прямоугольнике.Необходимо использовать множественное наследование. В классах должны быть предусмотрены виртуальные функции для вывода информации об объектах в поток, а Shape должен иметь дружественный перегруженный оператор <<.
Исходный текст должен быть разделен на три файла .h, .cpp и .cpp с тестовой программой.
Реализация:
-
Загрузив проект MSF Tutorial, и выполнив его ознакомились с настройками среды программирования MS Visual C++ для написания проекта консольного win32 приложения.
-
При реализации поставленной задачи было создано 5 классов:
Класс kvadrat
Задает параметры фигуры квадрат по значению координат одной из вершины (x и y) и длине стороны (a). Наследник класса Shape.
|
Входные данные |
Выходные данные |
Описание |
|
Атрибуты |
||
Int X |
|
|
Координата X вершины |
Int Y |
|
|
Координата Y вершины |
Int A |
|
|
Длина стороны |
|
Методы |
||
getX() |
- |
Int |
Получение атрибута X |
getY() |
- |
Int |
Получение атрибута Y |
getA() |
- |
Int |
Получение атрибута А |
Draw() |
- |
- |
Прорисовка объекта |
|
- |
- |
Вывод в поток |
Move |
Double double |
- |
Сдвиг |
Класс priam
Задает параметры фигуры прямоугольник по значению координат одной из вершины (x и y) и длине двух стороны (a и b). Наследник класса Shape.
|
Входные данные |
Выходные данные |
Описание |
|
Атрибуты |
||
Int X |
|
|
Координата X вершины |
Int Y |
|
|
Координата Y вершины |
Int A |
|
|
Длина стороны A |
Int B |
|
|
Длина стороны B |
|
Методы |
||
getX() |
- |
Int |
Получение атрибута X |
getY() |
- |
Int |
Получение атрибута Y |
getA() |
- |
Int |
Получение атрибута А |
getB() |
|
int |
Получение атрибута B |
Draw() |
- |
- |
Прорисовка объекта |
|
- |
- |
Вывод в поток |
Move |
Double Double |
- |
Сдвиг |
Класс Text
Задает параметры фигуры текст по значению координат расположения текста и самого его значения. Наследник класса Shape.
|
Входные данные |
Выходные данные |
Описание |
|
Атрибуты |
||
Int K |
|
|
Координата X вершины |
Int Z |
|
|
Координата Y вершины |
char ST |
|
|
Сам текст |
|
Методы |
||
getK() |
- |
Int |
Получение атрибута K |
getZ() |
- |
Int |
Получение атрибута Z |
getST() |
- |
char |
Получение атрибута ST |
Draw() |
- |
- |
Прорисовка объекта |
Print() |
- |
- |
Вывод в стандартный поток |
Класс text_in_priam
Задает параметры фигуры текст в прямоугольнике. Все атрибуты и метды наследуются из базовых классов Text и Priam.
|
Входные данные |
Выходные данные |
Описание |
Draw() |
- |
- |
Прорисовка объекта |
Класс Shape
Является абстрактным классом с абстрактным методом и дружественным перегруженным оператором вывода в поток (<<). Этот класс является интерфейсным для производных классов.
|
Входные данные |
Выходные данные |
Описание |
Draw() |
- |
- |
Прорисовка объекта |
Operator << |
|
|
Вывод в поток |
Изображения классов и отношений генерализации в UML в приложении.
1.2. Работа в режиме отладки.
Запустить программу и просмотреть ее работу по шагам (Build -> Start Debug -> Go)
Просмотрим иерархию классов. В окне дебаггера появляются текущие т.е. обрабатываемые в данный момент объекты и переменные. Здесь можно просмотреть их структуру.
Из рисунка видно, какую структуру имеет каждый объект и по какому адресу памяти находиться. Например, переменная KV3 класса Text_in_priam имеет сложную стуктуру множественнго наследования.
Расставим точки превывания программы (Break Points) и её работу. Для выяснения текущих значений переменных, использовать механизм "Watch variable".
В данный раздел мы можем добавлять любые переменные или объекты существующие в программе для определения их точных значений и отслеживания изменений в ходе выполнения программы.
1.3. Исследование программы при помощи Profiler.
2. Применение стандартной библиотеки STL
2.1. Составить консольные приложения, демонстрирующие основные операции с контейнерами и итераторами STL.
Заполняя 3 контейнера строками из <cstring> или другими элементами, продемонстрировать отличия - последовательностей (vector, list, dequeue);
// контейнер vector
std::cout<<"Vector: "<<std::endl;
std::vector<std::string> v;
for (int i=0;i<5;i++)
{v.push_back(std::string(i+1,'a'));
}
for (i=0;i<v.size();i++)
{std::cout<<v[i]<<std::endl;
}
std::cout<<std::endl;
// контейнер list
std::cout<<"List: "<<std::endl;
std::list<std::string> l;
for (i=0;i<5;i++)
{l.push_back(std::string(i+1,'a'));
}
std::list<std::string>::iterator lp;
while (!l.empty())
{ lp=l.begin();
std::cout<<*lp<<std::endl;
l.pop_front();
}
std::cout<<std::endl;
// контейнер deque
std::cout<<"Deque: "<<std::endl;
std::deque<std::string> de;
for (i=0;i<5;i++)
{
if (i%2==0)
{de.push_back(std::string(i+1,'a'));}
else
{de.push_front(std::string(i+1,'a'));}
}
for (i=0;i<de.size();i++)
{
std::cout<<de[i]<<std::endl;
}
std::cout<<std::endl;
- адаптеров последовательностей (stack, queue);
// контейнер stack
std::cout<<"Stack: "<<std::endl;
std::stack<std::string,std::vector<std::string> > st;
for (i=0;i<5;i++)
{
st.push(std::string(i+1,'a'));
}
while (!st.empty())
{
std::cout<<st.top()<<std::endl;
st.pop();
}
std::cout<<std::endl;
// контейнер queue
std::cout<<"Queue: "<<std::endl;
std::queue<std::string,std::list<std::string> > qu;
for (i=0;i<5;i++)
{
qu.push(std::string(i+1,'a'));
}
while (!qu.empty())
{
std::cout<<qu.front()<<std::endl;
qu.pop();
}
std::cout<<std::endl;
- ассоциативных контейнеров на базе map.
//контейнер map
std::cout<<"Map: "<<std::endl;
std::map<int,std::string> m;
for(i=0;i<10;i++)
{
m.insert(std::pair<int,std::string>(i,std::string(i+1,'a')));
}
std::map<int,std::string>::iterator mit;
for (i=0;i<m.size();i++)
{
mit=m.find(i);
std::cout<<mit->second<<std::endl;
}
std::cout<<std::endl;
// контейнер map
double points1[4][2]={{1,1},{1,2},{2,1},{2,2}};
double points2[4][2]={{1,1},{1,4},{3,1},{3,4}};
shape* KV =new kvadrat(points1);
shape* PR =new priam(points2);
shape* TX =new text("bla-la",5,8);
shape* TXPR =new text_in_priam(points1,"BLA-LA");
std::map<int,shape*> Sh_map;
Sh_map.insert(std::pair<int,shape*>(1,KV));
Sh_map.insert(std::pair<int,shape*>(2,PR));
Sh_map.insert(std::pair<int,shape*>(3,TX));
Sh_map.insert(std::pair<int,shape*>(4,TXPR));
std::map<int,shape*>::iterator Sh_mit;
for (i=1;i<Sh_map.size()+1;i++)
{
Sh_mit=Sh_map.find(i);
cout<<(Sh_mit->second)<<endl<<endl;
}
std::cout<<std::endl;
-
Аналогично протестировать ассоциативный контейнер, заполняя его указателями
на разные графические объекты из разд. 1.1. Протестировать алгоритны-методы и алгоритмы-классы на множестве графических элементов.
// тестирование контейнера vector на объектах класса shape
std::vector<shape*> Sh_v1(3);
std::vector<shape*> Sh_v2;
std::vector<shape*> Sh_v3;
std::fill(Sh_v1.begin(),Sh_v1.end(),KV);
std::fill_n(std::back_inserter(Sh_v2),2,PR);
std::cout<<"Fill: "<<std::endl;
for(i=0;i<Sh_v1.size();i++)
{std::cout<<Sh_v1[i]<<std::endl<<std::endl;}
std::cout<<std::endl<<std::endl;
std::cout<<"Fill vs inserter: "<<std::endl;
for(i=0;i<Sh_v2.size();i++)
{std::cout<<Sh_v2[i]<<std::endl<<std::endl;}
std::cout<<std::endl<<std::endl;
}
2.2. Реализовать новый шаблон контейнера и шаблон итератора для него по индивидуальному заданию.
-
По индивидуальному заданию контейнер представляет собой множество на базе списка.
Множество реализовано на базе стандартного контейнера List стандартной библиотеки языка MS Visual C++.
Дополнительные возможности контейнера это объединение 2-х контейнеров (функция Edin) и исключение (функция iskl ). Эти функции отражают соответствующие операции над множеством.
Диаграмма классов контейнеров приведена на рисунке 2.
-
Класс итератор для контейнера-множества является внешним итератором и использует функции контейнера. В качестве одного из аргументов содержит ссылку на класс списка, что исключает приведение типов и использование итератора не для того контейнера, а так же номер элемента списка, на которой ссылается итенатор.
-
Обработка исключительных ситуаций.
В программе обрабатываются один вид исключительных ситуаций: запрос несуществующего значения. Другие ошибки по сути повторяют первую.
Класс, соответствующий этой ситуации - ErInd.
При возникновении исключительной ситуации, генерируется исключительная ситуация соответствующего типа, которая перехватывается в тестирующей программе.
-
Контейнер тестируется на графических объектах. Заполняя и удаляя объекты из контейнера:
// задается класс Shape
shape* KV =new kvadrat(points1);
shape* PR =new priam(points2);
shape* TX =new text("bla-la",5,8);
shape* TXPR =new text_in_priam(points1,"BLA-LA");
//создается контейнер множества
LSet<shape *> ls1;
SetIterator<shape *> it1(ls1);
LSet<shape *> ls2;
LSet<shape *> ls3;
//заполняется контейнер множества
ls1.InsertEl(KV);
ls1.InsertEl(PR);
ls1.InsertEl(TX);
ls1.InsertEl(TXPR);
// выводиться содержимое контейнера в поток
cout<<"List 2:"<<endl;
cout<<ls1;
ls2=edin(ls1,ls);
// дополнительные функции
cout<<"List 3 OB'EDINENIE"<<endl;
cout<<ls2;
ls3=iskl(ls2, ls);
ls.dellete(20);
ls1.getElem(22);