Работа с иерархическими структурами (бинарные деревья)



Цель работы: Получение навыка работы с иерархическими структурами.

 

Домашнее задание

1.1. Тщательно изучите листинг программ №1. Нарисуйте блок-схему функции iTakeOut.

1.2. Составьте произвольный  список из учеников вашей группы с вашей фамилией в начале списка. Нарисуйте дерево, использую составленный список.

 

Лабораторное задание

2.1. Наберите программу №1 (комментарии можно не набирать).

#include "stdafx.h"

#include <stdlib.h>

# include <string.h>

# include <stdio.h>

# include <malloc.h>

# include <conio.h>

 

 

# define STAFF struct sStaffType

STAFF // Учебно-вспомогательный персонал

{

int iYearsOfService; // Время работы (лет)

float fHourlyWage; // Почасовая оплата

};

# define STUDENT struct sStudentType

STUDENT

{

float fGradePtAverage; // Средний рейтинг

int iLevel;         // Год обучения

};

# define PROFESSOR struct sProfType

PROFESSOR

{

int iDepartmentNumber; // Номер кафедры

float fAnnualSalary;   // Годовая зарплата

};

# define NODE_TYPE enum eNodeType

typedef NODE_TYPE {student, professor, staff};

# define TREE struct sTree

TREE

{

char sLastName[15]; // Фамилия

char sFirstName[15]; // Имя

int iAge;        // Возраст

TREE *Left, *Right; // Указатели на левый и правый листья (ветви)

NODE_TYPE tag;   // описатель типа узла - студент или профессор или УВП

union

{

   STUDENT student;

   PROFESSOR professor;

   STAFF staff;

} uNodeTag;            // Обьединение, содержащее информацию по

};                        // студенту или сотруднику университета

extern void Insert(TREE **root, TREE *item); // Вставить в дерево новый элемент item

extern void Display(TREE *root); // Показать содержимое дерева

extern int iIsPresent(TREE *root, TREE *item); // Содержится ли информация item в дереве?

extern int iTakeOut(TREE **root, TREE *item); // Удалить элемент item из дерева

extern void Destroy(TREE *root); // Уничтожить дерево

static TREE* CreateNode(TREE* item) // Создать элемент item

{

TREE* node;

node = (TREE*) malloc(sizeof(TREE));

*node = *item;

return node;

}

void Destroy(TREE* root) // Уничтожить дерево

{

if (root) // Обратите особое внимание на рекурсивную работу этой функции

{

   Destroy(root->Left);

   Destroy(root->Right);

   free(root); // Освободить память, которая была выделена для узла дерева

}

root = 0;

}

int iTakeOut(TREE** root, TREE* item) // Удалить элемент item из дерева

{

TREE *previous = 0, // Предыдущий узел дерева

     *present = *root, // Текущий узел дерева

     *replace, // Вспомогательные узлы,

     *s,   // используемые для перемещения элементов

     *parent; // дерева после удаления найденного узла

     int iFound = 0;

while (present && !iFound) // Пока не будет найден элемент item

{

    if(strcmp(item->sLastName, present->sLastName) == 0)

       iFound = 1; // Информация по человеку с таким именем и фамилией есть в дереве

    else

     {

       previous = present;

       // Если ASCII представление фамилии из item меньше ASCII кода фамилии

       // из текущего узла дерева (present), то перейти к просмотру левого

       // узла (листа) относительно present, иначе - правого

       if(strcmp(item->sLastName, present->sLastName) < 0)

            present = present->Left;

       else

            present = present->Right;

     }

}

if (iFound) // если item присутствует в дереве

{

    if (present->Left == 0) // Если найденный элемент не имеет ветви слева

       replace = present->Right;

    else

    {

       if (present->Right == 0) // Если найденный элемент не имеет ветви справа

            replace = present->Left;

       else // Если удаляемый элемент имеет и левую и правую ветвь (листья)

       {

             parent = present;

             replace = present->Right;

             s = replace->Left;

             // Теперь необходимо подвинуть все элементы ветви, чтобы избежать разрыва

             // дерева при удалении найденного элемента (present)

             while (s != 0) // Пока не будет достигнут крайний левый лист в рассматриваемой ветви

             { // Спускаемся вниз дерева по левой ветви

                   parent = replace;

                   replace = s;

                   s = replace->Left;

             }

             if (parent != present) // Есть левая ветвь от правой ветви от найденного элемента

             {

                   parent->Left = replace->Right; // Правую подветвь переносимого элемента сделать левой подветвью предыдущего

                   replace->Right = present->Right; // Переместить элемент на место удаляемого

             }

             replace->Left = present->Left; // Переместить левую ветвь

       }

    }

    if (previous == 0) // Элемент лежит сразу же за корнем дерева

       *root = replace;

    else

       if(present == previous->Left) // Предыдущий спуск был по левой ветви

            previous->Left = replace;

       else                     // Предыдущий спуск был по правой ветви

            previous->Right = replace;

    free (present); // Удалить найденный элемент

}

return iFound; // 1 - если элемент был удален, 0 - если такого элемента в дереве не было

}

void Insert(TREE **root, TREE *item ) // Вставить элемент item в дерево

{

TREE *parent = 0,

// current (текущий) указатель на дерево указывает на его вершину (корень)

*current = *root;

TREE *new_node; // Новый узел

int iFound = 0;

while (current && !iFound) // Пока элемент item не найден

{

   if (strcmp(item->sLastName, current->sLastName) == 0) iFound = 1;

   else

   {

      parent = current;

      if (strcmp(item->sLastName, current->sLastName) < 0)

           current = current->Left; // перемещаться по левой ветви

      else

           current = current->Right; // перемещаться по правой ветви

   }

}

if (iFound == 0)

{

   if (parent == 0) // в дереве нет еще элементов - создаем его

   {

      *root = CreateNode(item); // создать узел

      (*root)->Left = (*root)->Right = 0;

   }

   else // Вставить узел в дерево

   {

      new_node = CreateNode(item);

      new_node->Left = new_node->Right = 0;

      if (strcmp(item->sLastName, parent->sLastName) < 0)

           parent->Left = new_node;

      else

           parent->Right = new_node;

   }

}

}

void Display(TREE *root) // Показать дерево

{

if(root) // Обратите внимание также на рекурсивный обход дерева

{

   Display(root->Left);// показать вначале левую ветвь (лист) дерева

   printf("\n%s, %s", root->sLastName, root->sFirstName);

   printf("\n Old - %d", root->iAge);

   switch(root->tag) // Обратите внимание на использование в

   {             // конструкции switch элементов перечислимого

      case student:   // (enum) типа

        printf("\nReyting: %.2f",

                        root->uNodeTag.student.fGradePtAverage);

        printf("\nKurs: %d\n", root->uNodeTag.student.iLevel);

      break;

      case professor:

        printf("\nNumber of kafedra: %d",

                       root->uNodeTag.professor.iDepartmentNumber);

        printf("\nYear selary: %.2f\n",

                      root->uNodeTag.professor.fAnnualSalary);

      break;

      case staff:

        printf("\n Time of work(year): %d",

                      root->uNodeTag.staff.iYearsOfService);

        printf("\nSelary of oure: %.2f\n",

                       root->uNodeTag.staff.fHourlyWage);

    }

   Display(root->Right); // Вывести информацию о содержимом правого узла

}

}

int iIsPresent(TREE *root, TREE *item)

{

TREE *current = root; // Устанавливаем указатель на вершину (корень) дерева

int iFound = 0;

while (current && !iFound) // пока элемент item не найден

{

   if (strcmp(item->sLastName, current->sLastName) == 0) iFound = 1;

   else

   { // Если ASCII код фамилии из item меньше ASCII кода из текущего узла (current)

      if (strcmp(item->sLastName, current->sLastName) < 0)

           current = current->Left; // то перейти к рассмотрению левого узла

      else

           current = current->Right; // иначе перейти к рассмотрению правого узла

   }

}

return iFound; // Если не найден - 0, если найден - 1

}

TREE* sMyTree;

void main()

{

// Выделяем память на три узла дерева

TREE* item1 = (TREE*) malloc(sizeof(TREE));

TREE* item2 = (TREE*) malloc(sizeof(TREE));

TREE* item3 = (TREE*) malloc(sizeof(TREE));

// Инициализация первого элемента

strcpy(item1->sLastName, "Fyfikov");

strcpy(item1->sFirstName, "Ziberman");

item1->iAge = 32;

item1->tag = staff;

item1->uNodeTag.staff.iYearsOfService = 3;

item1->uNodeTag.staff.fHourlyWage = 5.25;

// Вставить элемент в дерево

Insert(&sMyTree, item1);

strcpy(item2->sLastName, "Vibigalo");

strcpy(item2->sFirstName, "Ivanov");

item2->iAge = 56;

item2->tag = professor;

item2->uNodeTag.professor.iDepartmentNumber = 7;

item2->uNodeTag.professor.fAnnualSalary = 15321.0;

Insert(&sMyTree, item2);

strcpy(item3->sLastName, "Sidorov");

strcpy(item3->sFirstName, "Antonov");

item3->iAge = 18;

item3->tag = student;

item3->uNodeTag.student.iLevel = 1;

item3->uNodeTag.student.fGradePtAverage = 0.75;

Insert(&sMyTree, item3);

Display(sMyTree); // Показать дерево

getchar();

if(iIsPresent(sMyTree, item2))

printf("\n 2- element out of tree\n");

else

printf("\n element out of tree\n");

getchar();

iTakeOut(&sMyTree, item1);

Display(sMyTree);

getchar();

iTakeOut(&sMyTree, item2);

Display(sMyTree);

getchar();

iTakeOut(&sMyTree, item3);

Display(sMyTree);

getchar();

printf("\n");

}

 

2.3. Запустите программу и проанализируйте результаты ее работы.

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

2.5 Измените программу так, чтобы в дерево можно было вставлять однофамильцев.

2.6 Модифицируйте класс sTree так, чтобы его объекты можно было вставлять в контейнер set библиотеки STL. Продемонстрируйте примеры вставки.

 

Содержание отчета

  1. Титульный лист отчета должен содержать название, цель лабораторной работы, группу и фамилию студента, выполнившего её, и фамилию преподавателя, проверившего отчет.
  2. Выполненное домашнее задание.
  3. Тексты программ, написанных при выполнении 2.4, 2.5 и 2.6 пунктов лабораторного задания.

 

 

Вопросы к защите

3.1. Использую библиотеку STL, напишите класс вектор целых чисел.

3.2. Использую библиотеку STL, напишите класс очередь вещественных чисел.

3.3. Использую библиотеку STL, напишите класс список символьных переменных.

3.4. Использую библиотеку STL, напишите класс множество символьных переменных.

3.5. Использую библиотеку STL, напишите класс мультимножество символьных переменных.

3.6. Нарисуйте пример двоичного дерева поиска и покажите, как изменяется его структура при удалении из него элемента.

3.7. Нарисуйте пример двоичного дерева поиска и покажите, как изменяется его структура при вставке в него элемента.

3.8. Напишите функцию сохранения и восстановления дерева из файла.

3.9. Напишите функцию, позволяющую найти и отредактировать содержимое любого узла в дереве.

3.10. Напишите функцию, выводящую на экран информацию о узлах дерева удовлетворяющих заданному с клавиатуры пользователем диапазону (например, вывести все узлы начинающиеся с букв от В до Е).

3.11. Модифицируйте программу так, чтобы фамилия и имя в узле дерева заносились не в статический, а динамический массив памяти.

 

Лабораторная работа N 10

Наследование классов в языке С++

Цель работы: Получение навыка работы с наследованием классов в языке С++

 

Домашнее задание

1.1. Тщательно изучите листинг программ №1. Постройте графы иерархии классов.

1.2 Письменно поясните термины инкапсуляция и интерфейс, наследование интерфейса и наследование реализации, композиция и агрегация в языке С++. С помощью каких средств языка они реализованы.

 

Лабораторное задание

2.1. Наберите программу №1.

// Figura.cpp:

#include "stdafx.h"

#include "afxwin.h"

#include "iostream"

using namespace std ;

 

class Figure{

  static HWND hwnd;

protected:

  static HDC hdc;

public:

  Figure(){/*cout<<"\n Figure()";*/}

  void show(){}

  void hide(){}

  void move(int x, int y){}

  static void InitGraphic(){hwnd=FindWindow(_T("ConsoleWindowClass"),_T("C:\\Windows\\system32\\cmd.exe"));hdc=GetWindowDC(hwnd);}

  static void CloseGraphic(){ReleaseDC(hwnd, hdc); CloseHandle(hwnd);}

  ~Figure(){/*cout<<"\t ~Figure()";*/}

};

HWND Figure::hwnd = 0;

HDC Figure::hdc = 0;

 

class Square: public Figure {

  POINT pt[5];

public:

  Square(POINT* p){

         for(int i =0 ; i <5; i++){pt[i].x = p[i].x;pt[i].y = p[i].y;}

  }

  void show(){

         CPen pen(PS_SOLID,2,RGB(255,0,0));

         SelectObject(hdc,pen);

         Polyline(hdc,pt,5 );

  }

  void hide(){

         CPen pen(PS_SOLID,2,RGB(0,0,0));

         SelectObject(hdc,pen);

         Polyline(hdc,pt,5 );

  }

  void move(int x, int y){for(int i = 0; i<5;i++){ pt[i].x+=x;pt[i].y+=y;} }

  ~Square(){/*cout<<"\t ~Square()";*/}

};

 

class ClsEllipse: public Figure {

      

      

public:

  CPoint pt1,pt2;

  ClsEllipse(){/*cout<<"\t ClsEllipse()";*/

         pt1.x=100;      pt1.y=100;

         pt2.x=200;      pt2.y=200;

  }

  void show(){

         CPen pen(PS_SOLID,2,RGB(0,255,0));

         SelectObject(hdc,pen);

         Arc(hdc,pt1.x,pt1.y,pt2.x,pt2.y,100,200,0,100);

  }

  void hide(){

         CPen pen(PS_SOLID,2,RGB(0,0,0));

         SelectObject(hdc,pen);

         Arc(hdc,pt1.x,pt1.y,pt2.x,pt2.y,100,200,0,100);

  }

  void move(int x, int y){ pt1.x+=x,pt1.y+=y,pt2.x+=x,pt2.y+=y; }

  ~ClsEllipse(){/*cout<<"\t ~ClsEllipse()";*/}

};

//Включение объектов

class MyObject{

  Square sq1, sq2; //Композиция (агрегирование по значению)

  ClsEllipse& elp; //Агрегация (агрегирование по ссылке)

public:      

  MyObject(const Square& p1,const Square& p2,ClsEllipse& el):sq1(p1),sq2(p2), elp(el){/*cout<<"\t MyObject()";*/}

  void show(){sq1.show(); sq2.show();elp.show();}

  void move(int x, int y){sq1.move(x,y); sq2.move(x,y);elp.move(x,y);}

  void hide(){sq1.hide(); sq2.hide(); elp.hide();}

  ~MyObject(){/*cout<<"\n ~MyObject()";*/}

};

//Множественное наследование

class Heir: Square, ClsEllipse{

public:

  Heir(POINT *p):Square(p),ClsEllipse(){/*cout<<"\t Heir()";*/ }

  void show(){Square::show(); ClsEllipse::show();}

  void move(int x, int y){Square::move(x,y); ClsEllipse::move(x,y);}

  void hide(){Square::hide(); ClsEllipse::hide();}

  ~Heir(){/*cout<<"\n ~Heir()";*/}

};

 

void ShowMyObject(MyObject obj){

  for(int i = 0 ; i <100 ; i++){obj.show(); Sleep(24); obj.hide(); obj.move(4,0);}

}

void main(){

  POINT pt1[5];

  pt1[0].x = 40;pt1[0].y=40;

  pt1[1].x = 40;pt1[1].y=140;      

  pt1[2].x = 140;pt1[2].y=140;     

  pt1[3].x = 140;pt1[3].y=40;

  pt1[4].x = 40;pt1[4].y=40;

             

  Figure::InitGraphic();

  {

         Square sq1(pt1); ClsEllipse elp;

         for(int i = 0 ; i <100 ; i++){ sq1.show();elp.show(); Sleep(24); sq1.hide(); elp.hide(); sq1.move(1,1); elp.move(2,2);}

  }

  ClsEllipse elp;

  Square sq2(pt1);

  sq2.move(20,20);

  MyObject obj(pt1, sq2, elp);

  getchar();

  ShowMyObject(obj);

  {

         Heir hr(pt1);

         getchar();

         for(int i = 0 ; i <100 ; i++){hr.show(); Sleep(24); hr.hide(); hr.move(0,3);}

  }

  Figure::CloseGraphic();

}

 

 2.2. Определите классы линия, треугольник, трапеция.

2.3. Получите у преподавателя рисунок и, используя разработанные классы, нарисуйте его на экране, применив множественное наследование и включение.

2.4 Переопределить один из классов с помощью указателей.

 

Содержание отчета

3.1 Титульный лист отчета должен содержать название, цель лабораторной работы, группу и фамилию студента, выполнившего её, и фамилию преподавателя, проверившего отчет.

3.2 Выполненное домашнее задание.

3.3 Тексты программ, написанные при выполнении 2.2, 2.3 и 2.4 пунктов лабораторного задания.

 

 

Вопросы к защите

4.1. Расскажите о методах декомпозиции системы.

4.2. Приведите примеры иерархичных систем.

4.3. Расскажите о переопределении данных и методов базового класса в производном классе.

4.4. Раскройте понятия инкапсуляция и интерфейс класса. С помощью каких средств языка они реализованы.

4.5. Реализуйте класс Square, используя динамическую память.

4.6.  Реализуйте класс ClsEllipse, используя динамическую память.

4.7. Реализуйте класс MyObject, используя динамическую память.

4.8. Напишите классы абитуриент и производный от него студент. Поясните механизм наследования.

4.9. Напишите классы университет и факультет и на их примере поясните, что такое композиция.

4.10. Напишите классы преподаватель и факультет и на их примере поясните, что такое агрегация.

 

Лабораторная работа N 11

Абстрактные классы и виртуальные функции С++

Цель работы: Получение навыка работы с виртуальными функциями и абстрактными классами в языке С++

 

Домашнее задание

1.1. Тщательно изучите листинг программ №1. Постройте граф иерархии классов.

1.2 Поясните письменно термины: инкапсуляция, интерфейс, наследование, полиморфизм, агрегирование, делегирование в отношении классов языка С++. С помощью каких средств языка они реализованы.

 

Лабораторное задание

2.1. Наберите программу №1.

 

// В свойствах проекта в опциях по C/С++ ->Библиотека времени выполнения; установить /MTd

//В свойствах проекта Компоновщик->Ввод->Дополнительные зависимости; поставьте  на первое место uafxcwd.lib

#include "stdafx.h"

#include "afxwin.h"

#include "iostream"

using namespace std ;

 

HWND hwnd = 0;

HDC hdc = 0;

void InitGraphic(){

system("mode con cols=168 lines=55"); system("pause >> void");

hwnd=FindWindow(_T("ConsoleWindowClass"),_T("C:\\Windows\\system32\\cmd.exe"));hdc=GetWindowDC(hwnd);

}

void CloseGraphic(){ReleaseDC(hwnd, hdc); CloseHandle(hwnd);}

 

//-------------------------------------------------------------------------- IFigure

class IFigure{ //интерфейсный класс

protected:

  int fMove; //0 - фигура двигается; 1 - фигура мигает на месте; 2 - фигура стоит на месте;

  int fClr; //0 - фигура цвет не меняет; 1 - фигура меняет цвет

public:

  IFigure(): fMove(0), fClr(0){/*cout<<"\n IFigure()";*/}

  virtual void show()=0;

  virtual void hide()=0;

  virtual void move(int x, int y)=0;

};

 

//-------------------------------------------------------------------------Square

class Square:virtual public IFigure {

  POINT pt[5];

  COLORREF color;

public:

  Square(POINT* p): color(RGB(255,0,0)){ for(int i =0 ; i <5; i++) pt[i] = p[i]; }

  void SetColor(COLORREF cl){color = cl;}

  void show(){

         CPen pen(PS_SOLID,2,color);

         SelectObject(hdc,pen);

         Polyline(hdc,pt,5 );

  }

  void hide(){

         CPen pen;

         pen.CreatePen(PS_SOLID,2,RGB(0,0,0));

         SelectObject(hdc,pen);

         Polyline(hdc,pt,5 );

  }

  void move(int x, int y){for(int i = 0; i<5;i++){ pt[i].x+=x;pt[i].y+=y;} }

  virtual ~Square(){/*cout<<"\t ~Square()";*/}

};

//---------------------------------------------------------------------------ClsEllipse

class ClsEllipse: virtual public IFigure {

  CPoint pt1,pt2;

public:

  ClsEllipse():pt1(100,100),pt2(200,200) {}

  virtual void show() {

         CPen pen(PS_SOLID,2,RGB(0,255,0));

         SelectObject(hdc,pen);

         Arc(hdc,pt1.x,pt1.y,pt2.x,pt2.y,100,200,0,100);

  }

  virtual void hide() {

         CPen pen(PS_SOLID,2,RGB(0,0,0));

         SelectObject(hdc,pen);

         Arc(hdc,pt1.x,pt1.y,pt2.x,pt2.y,100,200,0,100);

  }

  virtual void move(int x, int y) { pt1.x+=x,pt1.y+=y,pt2.x+=x,pt2.y+=y; }

  virtual ~ClsEllipse(){/*cout<<"\t ~ClsEllipse()";*/}

};

//-------------------------------------------------------------------------Rectan

class Rectan: public IFigure {

  Square* pSq;

public:

  //дописать operator=

  virtual void show(){pSq->show();}//Делегирование

  virtual void move(int x, int y){pSq->move(x,y);}//Делегирование

  virtual void hide(){pSq->hide();}//Делегирование

  void SetColor(COLORREF cl){pSq->SetColor(cl);}

  Rectan (Square& p){pSq = new Square(p);}

  virtual ~Rectan(){delete pSq;}

};

//-------------------------------------------------------------------------DrowTxt

class DrowTxt{

  CString str;

public:

  DrowTxt(CString s):str(s){}

  void show(){

         CDC* pCDC = CDC::FromHandle(hdc);

         pCDC->SetTextColor(RGB(255,0,0));

    pCDC->SetBkColor(RGB(0,0,0));

         pCDC->TextOutW(300,100,str); pCDC->TextOutW(0,0," ");

  }

};

 

//-------------------------------------------------------------------------Heir

class Heir: public Square, public ClsEllipse{ //Виртуальный базовый класс

public:                                   //(Множественное наследование)

  Heir(POINT *p):Square(p),ClsEllipse(){/*cout<<"\t Heir()";*/ }

  void show(){Square::show(); ClsEllipse::show();}

  void move(int x, int y){Square::move(x,y); ClsEllipse::move(x,y);}

  void hide(){Square::hide(); ClsEllipse::hide();}

  virtual ~Heir(){/*cout<<"\n ~Heir()";*/}

};

 //------------------------------------------------------------------------RecordPlayer

class RecordPlayer{ //Чтобы воспользоваться классом, объекты должны поддерживать интерфейс IFigure

  IFigure**pFig;//Массив указателей IFigure*

  int n; //Текущее количество указателей в массиве

  int N; //Размерность массива

public:      

  void Insert(IFigure* pF){if (n<N) pFig[n++] =pF; }

  RecordPlayer(int Nfig): N(Nfig), n(0) { pFig = new IFigure*[N]; }

  virtual void show(){ for(int i = 0; i < n; i++) pFig[i]->show(); }//Полиморфизм

  virtual void hide(){ for(int i = 0; i < n; i++) pFig[i]->hide(); }//Полиморфизм

  virtual void move(int x, int y){ for(int i = 0; i < n; i++) pFig[i]->move(x,y); }//Полиморфизм

  void PlayMyObject(int x, int y){ for(int i = 0; i <150 ; i++){show();Sleep(24);hide(); move(x,y);} show();}

  virtual ~RecordPlayer(){delete []pFig;}

};

 

void main(){

      

  POINT pt1[5];

  pt1[0].x = 40;pt1[0].y=40;

  pt1[1].x = 40;pt1[1].y=140;      

  pt1[2].x = 140;pt1[2].y=140;     

  pt1[3].x = 140;pt1[3].y=40;

  pt1[4].x = 40;pt1[4].y=40;

 

  InitGraphic();

 

  DrowTxt dtxt("Привет");

  dtxt.show();

  getchar();

 

  Heir hr(pt1);

  for(int i = 0 ; i <100 ; i++){hr.show(); Sleep(24); hr.hide(); hr.move(0,3);}

  getchar();

 

  ClsEllipse elp;

  Square sq1(pt1), sq2(pt1), sq3(pt1);

  sq1.SetColor(RGB(255,255,0)); sq2.SetColor(RGB(0,255,0));

  sq3.SetColor(RGB(0,0,255)); hr.SetColor(RGB(0,255,255));

  sq2.move(20,20); sq3.move(40,30); hr.move(0,-150);   

  Rectan rec(sq3);

  RecordPlayer RPlayer(5);

  RPlayer.Insert(&elp);

  RPlayer.Insert(&sq1);

  RPlayer.Insert(&sq2);

  RPlayer.Insert(&rec);

  RPlayer.Insert(&hr);

  RPlayer.PlayMyObject(3,0);

 

  getchar();

  CloseGraphic();

}

2.2 Доопределите класс Rectan.

2.3 Модифицируйте класс ClsEllipse так, чтобы параметры эллипса можно было задавать через конструктор, и объекты этого класса могли менять свой цвет.

2.4 Модифицируйте класс DrowTxt так, чтобы он мог быть использован классом RecordPlayer для воспроизведения на экране.

2.5 Напишите класс «текст в прямоугольнике» так, чтобы он мог быть использован классом RecordPlayer для воспроизведения на экране.

2.6 Модифицируйте программу так, чтобы объекты на экране с помощью класса RecordPlayer могли двигаться, оставаться неподвижными, мигать, изменять свой цвет.

2.7 Получите рисунок у преподавателя и напишите программу, рисующую его на экране с помощью класса RecordPlayer.

 

Содержание отчета

3.1 Титульный лист отчета должен содержать название, цель лабораторной работы, группу и фамилию студента, выполнившего её, и фамилию преподавателя, проверившего отчет.

3.2 Выполненное домашнее задание.

3.3 Тексты классов, написанных при выполнении 2.2 – 2.7 пунктов лабораторного задания.

 

Вопросы к защите

4.1. Расскажите о виртуальных функциях и полиморфизме.

4.2. Что такое абстрактные классы, для чего они нужны?

4.3. Расскажите о переопределении данных и методов базового класса в производном классе.

4.4. Раскройте понятия инкапсуляция и интерфейс класса. С помощью каких средств языка они реализованы.

4.5. Реализуйте класс круг, вписанный в квадрат, и выведите его на экран с помощью класса RecordPlayer.

4.6.  Реализуйте класс ClsEllipse, используя динамическую память.

4.7. Реализуйте класс Square, используя динамическую память.

4.8. Напишите класс «магазин», который работает с объектами абстрактного класса «товар». Определите 2-3 класса, производных от класса «товар». Продемонстрируйте примеры полиморфного поведения.

4.9. Напишите класс «вагон», который работает с объектами абстрактного класса «груз». Определите 2-3 класса, производных от класса «груз». Продемонстрируйте примеры полиморфного поведения.

Лабораторная работа N 12

Библиотека STL

Цель работы: Получение навыка работы с библиотекой STL

 

Домашнее задание

1.1. Тщательно изучите листинг программ №1. Опишите, что делает класс CountedPtr.  

1.2 Письменно в отчёте приведите все компонентные функции одной из коллекций из библиотеки STL.

 

Лабораторное задание

2.1. Наберите программу №1.

 

 

#include "stdafx.h"

#include <iostream>

#include <list>

#include <deque>

# include <set>

#include <algorithm>

using namespace std;

 

/* Класс, обеспечивающий семантику подсчёта ссылок.

* Объект, на который ссылается указатель, автоматически

* уничтожается при удалении последнего экземпляра CountedPtr

* для данного объекта.

*/

template <class T>

class CountedPtr {

private:

  T* ptr;         // Указатель на значение

  long* count; // Количество владельцев (общие данные)

  public:

  // Инициализация объекта существующим указателем

  // - указатель p должен быть получен в результате вызова new

  explicit CountedPtr(T* p = 0)

         : ptr(p), count(new long(1)) {

  }

 

  // Копирующий указатель (увеличивает счётчик владельцев)

  CountedPtr(const CountedPtr<T>& p) throw()

         : ptr(p.ptr), count(p.count) {

         ++*count;

  }

  // Деструктор (уничтожает объект, если владелец был последним)

  ~CountedPtr() throw() {

         dispose();

  }

  // Присваивание (перевод указателя на новый объект)

  CountedPtr<T>& operator= (const CountedPtr<T>& p) throw() {

         if (this != &p) {

                dispose();

                ptr = p.ptr;

                count = p.count;

                ++*count;

         }

         return *this;

  }

      

  // Доступ к объекту, на который ссылается указатель

  T& operator*() const throw() {

         return *ptr;

  }

  T* operator->() const throw() {

         return ptr;

  }

private:

  void dispose() {

         if (--*count == 0) {

                delete count;

                delete ptr;

         }

  }

};

 

 

struct comp {

  int* Re, *Im;

  comp() { Re = new int; Im = new int; ;*Re = 0; *Im = 0; }

  comp(int r, int i) { Re = new int; Im = new int;*Re = r; *Im = i; }

  ~comp() { delete Re; delete Im; }

  const comp& operator=(const comp& T) { // оператор функция=

         *Re = *T.Re; *Im = *T.Im; return *this;

  }

  const comp& operator-() { // оператор функция-

         *Re = -*Re; *Im = -*Im; return *this;

  }

  comp(comp& T) { Re = new int; Im = new int; *Re = *T.Re; *Im = *T.Im;}

  const comp operator*(const comp& T) { // оператор функция*

         comp Rez(0,0);

         *Rez.Re =*Re * *T.Re - *Im * *T.Im;

         *Rez.Im = *Re * *T.Im + *Im * *T.Re;

          return Rez;

  }

  double modComp()const {return sqrt(*Re**Re + *Im**Im); }

  bool operator<(const comp T) { // оператор функция<

         if( modComp() < T.modComp()) return 0;//х<х всегда ложно

         return 1;

  }

  void comp::display() const

  {

         cout << "\n Re = " << *Re << "\t Im = " << *Im;

  }

 

};

 

bool operator< (const CountedPtr<comp> p1, const CountedPtr<comp> p2) {

  if (*p1 < *p2) return 0;

  return 1;

}

 

void printCountedPtr(CountedPtr<comp> elem)

{

  (*elem).display();

}

 

int main()

{

      

  // Три разные коллекции

  typedef CountedPtr<comp> IntPtr;

  deque<IntPtr> coll1;

  list<IntPtr> coll2;

  set<IntPtr> coll3;

 

  /* Вставка общих объектов в коллекции*/

      

  for (int i = 0; i<5; ++i) {

         IntPtr ptr(new comp(i,i));

coll1.push_back(ptr); //coll1.push_back(comp(i,i));

         coll2.push_front(ptr);

         coll3.insert(ptr);

  }

 

  // Вывод содержимого коллекций

  cout<<"\n deque";

  for_each(coll1.begin(),coll1.end(), printCountedPtr);

  cout << "\n list";

  for_each(coll2.begin(), coll2.end(), printCountedPtr);

  cout << "\n set";

  for_each(coll3.begin(), coll3.end(), printCountedPtr);

  cout << endl << endl;

  /* Модификация значений в разных коллекциях

  * - возведение в квадрат значения в coll1

  * - изменение знака первого значения в coll2

  */

  *coll1[1] = *coll1[1] * *coll1[1];

// *coll2.front() = - (*coll2.front());

 

  // Повторный вывод содержимого коллекций

  cout << "\n\n deque";

  for_each(coll1.begin(), coll1.end(), printCountedPtr);

  cout << "\n list";

  for_each(coll2.begin(), coll2.end(), printCountedPtr);

  cout << "\n set";

  for_each(coll3.begin(), coll3.end(), printCountedPtr);

  cout << endl;

}

 

 

 

 

2.2. Упростите программу. Перейдите от ссылочной семантики к семантике по значению (класс CountedPtr не нужен). Сравните данные, выводимые на экран, упрощённой программой и исходной.

2.3. Определите свой собственный класс (например: запись в базе данных, строка, вектор, квадрат, круг) и сформируйте коллекции из объектов вашего класса.

 

 

Содержание отчета

3.1 Титульный лист отчета должен содержать название, цель лабораторной работы, группу и фамилию студента, выполнившего её, и фамилию преподавателя, проверившего отчет.

3.2 Выполненное домашнее задание.

3.3 Тексты программ, написанные при выполнении 2.2 и 2.3 пунктов лабораторного задания.

 

Вопросы к защите

4.1. Какие типы коллекций вы знаете?

4.2. Сравните коллекции между собой. Какие у каждой из них имеются достоинства и недостатки?

4.3. Что такое итератор? Какие типы итераторов вы знаете?

4.4. Напишите программу реализующую список элементов типа квадрат.

4.5. Напишите программу, реализующую вектор комплексных чисел.

4.6. Напишите программу, реализующую набор строк.

4.7. Напишите программу, реализующую дек элементов типа эллипс.

4.8. Напишите класс «круг» вписанный в «квадрат», используя классы ClsEllipse и Square.

4.9. Напишите класс «текст» вписанный в «круг», используя классы ClsEllipse и DrowTxt.

4.10. Напишите класс «магазин», который работает с объектами абстрактного класса «товар». Определите 2-3 класса, производных от класса «товар». Продемонстрируйте примеры полиморфного поведения.

4.11. Напишите класс «вагон», который работает с объектами абстрактного класса «груз». Определите 2-3 класса, производных от класса «груз». Продемонстрируйте примеры полиморфного поведения.

 

 

Литература

 

1. Подбельский В. В. Стандартный Си++ [Текст] : учеб. пособие для студ. вузов. - М. : Финансы и статистика, 2008. - 687 с. : ил.. -  Библиогр.: с. 667-669 (31 назв.). - ISBN 978-5-279-03243-3

2. Максимов М. Н. Язык Си++ как инструмент для моделирования радиотехнических цепей и сигналов [Текст] : курс лекций : для студ. радиотехн. спец. всех форм обуч.. Ч. 1 / ТТИ ЮФУ, РТФ, Каф. ТОР. - Таганрог : Изд-во ТРТУ, 2007. - 159 с.. - Библиогр.: с. 159 (5 назв.)  

3. Библиотека STL


Дата добавления: 2021-04-05; просмотров: 63; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!