Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: очередь из разнородных элементов  (Прочитано 4644 раз)
0 Пользователей и 1 Гость смотрят эту тему.
eugrita
Помогающий

ru
Offline Offline

« : 27-05-2011 02:31 » 

Есть такая задача:
Моделировать очередь (руками), в качестве элементов которой могут использоваться числа и слова. Операции: добавление элемента, удаление элемента, печать элементов. Создать класс - потомок, который содержит процедуру сортировки слов по алфавиту. Тестировать полученную модель. В отчете представить структуру использованных классов и обосновать выбранн структуру представления данных
-------------------------------------------------------------------------------------------
Мне непонятна вообще технология подхода к ее решению. Ну скажем, очередь можно смоделировать как "руками" так и с помощью STL. Но разнородные элементы? Пытался найти в инете подходы к этому
Предлагают создать список(в нашем случае можно очередь) из указателей общего вида типа void . Код
Код:
class GenericList // список указателей общего вида void *
{
public:
    void addToList (void * newElement);
    void * firstElement();
private:
    GenericLink * firstLink;
};
class GenericLink
{
public:
    void    * value;
    GenericLink * nextLink;
};
Теперь там предлагают " определить подкласс класса общего вида и изменить типы аргумента и результата в методах, возвращающих элемент списка. В любом случае фактическую работу выполняет родительский класс."
Код C++
Код:
class WindowList : public GenericList
{
public:
    void addToList (Window * newElement)
     {
      GenericList::addToList (newElement);
     }
    Window * firstElement ()
     {
      return (Window *) GenericList::firstElement;
     }
};
Но далее в том же источнике гоаорится "Но реализация требует определения подклассов как для класса List, так и для класса Link, а также, вероятно, создания новых классов-итераторов"
Годится и наилучший ли это подход к решению сформулированной задачи в моем случае?

Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 27-05-2011 05:57 » 

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

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
eugrita
Помогающий

ru
Offline Offline

« Ответ #2 : 06-06-2011 13:06 » 

Ну что же .Вроде все что просили я как-то реализовал. Наиболее сложной и неприятной задачей явилась  сортировка строк . (дочерний класс TQueueS) .Сложности -из-за разнородных элементов контейнера. Поэтому движение от 1 строкового элемента к следующему не одним оператором a=a->nxt; а циклом while
Код:
class TElement
{ public:
TElement *nxt;
TElement() { nxt=NULL;}
 virtual ~TElement() {cout<<"Delete TElement.";}
 virtual void Print()=0;
     };
class TQueue
{
public:
  TQuue();//конструктор
  ~TQueue();  //деструктор
  TElement *First(){return cur=first;}
  TElement *Last(){return cur=last;}
  TElement *Next(){return cur=cur->nxt;}
  void addEL(TElement *val);//добавление элемента
  void delEL(); //удаление 1 элем
   void print();
private:
 TElement *first,*last,*cur;
 };
   TQueue::TQuue() //конструктор
   {first=last=cur=NULL;}
 TQueue::~TQueue()  //деструктор
 {TElement *cur1;
  cur1=first;
     while (cur!=NULL) {
     cur=cur1->nxt;
     delete(cur1);
                        }
   }
  void TQueue::addEL(TElement *e)  //добавление элемента
 {
  if (first==NULL)
   { first=last=e; e->nxt=NULL;}
   else
   { e->nxt=first;first=e;}
 }
 
 void TQueue::delEL()
  {//удаление 1 элем
   first=first->nxt;
  }

 void TQueue::print()
  {
    cur=first;
      while (cur!=NULL)
      {cur->Print(); cur=cur->nxt;}
  }
 //--------------------------------------------
 class TNum:public TElement
 {
 public:
 int num;
TNum(int n):TElement(),num(n) {}
virtual ~TNum() {cout<<"Delete TNum.";}
virtual void Print() { printf("%d ",num); }
      };
//--------------------------------------------
 class TSlovo:public TElement
 { public:
  char s[20];
TSlovo(char *S):TElement() {strcpy(s,S);}
virtual ~TSlovo() {cout<<"Delete TChar.";}
virtual void Print() { printf("%s ",s);}
 };

class TQueueS: public TQueue
{
 public:
 void sort(TElement * first);
};
void TQueueS::sort(TElement * first)
{ int i;
 TElement *a; TElement *b; char tmp[20];  TSlovo *A;TSlovo *B;
 a = first;
 while ((A =dynamic_cast<TSlovo *>(a))==0)
     a=a->nxt;//продвигаемся до 1-го элемента-строки
 while(a->nxt) // пока существует следующий элемент
 {
   b = a->nxt;
   while(b)  // для каждого элемента перебираем все оставшееся справа
      {
       while ((B=dynamic_cast<TSlovo *>(b))==0 )
          { b=b->nxt;   if (!b) return;}; //продвигаемся до 1-го элемента-строки
      if(strcmp(A->s,B->s)>0)//если порядок не тот - меняем
        { strcpy(tmp, A->s);strcpy(A->s,B->s); strcpy(B->s,tmp); }
        b = b->nxt;
      }
      while ((A =dynamic_cast<TSlovo *>(a))==0)
         a = a->nxt;  //продвигаемся до следующего элемента-строки
 }
}
Вопрос скорее философский: а на хрена вся эта конструкция? Её применение в практике?
Ну допустим, типовая задача типа загрузки БД (скажем студентов и препов) в оперативную память.
Ясно что преп описывается структурой другого типа чем скажем студент. И в БД скорее всего препы сидят в отдельной таблице по отн к студ.  Наверное логично тогда в ОП загружать в виде не одного комбинированного а двух списков, но зато однородных.
Записан
Dimka
Деятель
Команда клуба

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 06-06-2011 19:20 » 

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

Например, представь, как ты будешь моделировать работу почты (физической)? Есть письма, есть посылки, бандероли и т.п. - каждое послание обрабатывается в общем-то одинаково, с небольшими различиями по типам (т.е. "посылка", "бандероль", "письмо", "контейнер" - это классификатор первого уровня). Письма, например, бывают простыми и заказными с разным способом доставки - это классификатор второго уровня. Допустим, введём ещё цензора - тогда добавятся классификаторы по содержимому, причём они могут образовывать таксономии (т.е. одни и те же письма в разных "ортогональных" друг другу классификаторах будут иметь разные типы одновременно - см. design pattern Мост (Bridge)).

И как это всё ты будешь описывать отдельными очередями?
Записан

Программировать - значит понимать (К. Нюгард)
Невывернутое лучше, чем вправленное (М. Аврелий)
Многие готовы скорее умереть, чем подумать (Б. Рассел)
eugrita
Помогающий

ru
Offline Offline

« Ответ #4 : 06-06-2011 19:34 » 

да. Спасибо большое за такие пояснения. Заставляют думать меня, лодыря
Записан
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines