русс | укр

Языки программирования

ПаскальСиАссемблерJavaMatlabPhpHtmlJavaScriptCSSC#DelphiТурбо Пролог

Компьютерные сетиСистемное программное обеспечениеИнформационные технологииПрограммирование

Все о программировании


Linux Unix Алгоритмические языки Аналоговые и гибридные вычислительные устройства Архитектура микроконтроллеров Введение в разработку распределенных информационных систем Введение в численные методы Дискретная математика Информационное обслуживание пользователей Информация и моделирование в управлении производством Компьютерная графика Математическое и компьютерное моделирование Моделирование Нейрокомпьютеры Проектирование программ диагностики компьютерных систем и сетей Проектирование системных программ Системы счисления Теория статистики Теория оптимизации Уроки AutoCAD 3D Уроки базы данных Access Уроки Orcad Цифровые автоматы Шпаргалки по компьютеру Шпаргалки по программированию Экспертные системы Элементы теории информации

ДВУНАПРАВЛЕННЫЙ НЕОДНОРОДНЫЙ СПИСОК С ОДНОРОДНЫМИ ПОДСПИСКАМИ


Дата добавления: 2014-09-29; просмотров: 2535; Нарушение авторских прав


 

Введение

Список является структурой хранения данных. Если список – динамическая структура данных, то в простейшем случае – это линейный связный список, состоящий из элементов (узлов), каждый из которых содержит как собственные данные, так и одну (или две) ссылки на следующий (и предыдущий) узел. Принципиальным преимуществом перед массивом является структурная гибкость: порядок элементов связного списка может не совпадать с порядком расположения элементов данных в памяти компьютера, количество элементов не нужно задавать заранее, порядок обхода списка всегда явно задается его внутренними связями.

Существует несколько разновидностей связного списка. Однонаправленный список – каждый элемент содержит данные и указатель на следующий элемент. В кольцевом списке последний элемент содержит указатель на первый элемент. Двунаправленный связный список – в этом списке каждый элемент содержит указатели как на следующий, так и на предыдущий элементы. В таком списке, в отличие от однонаправленного списка, можно перемещаться в двух направлениях. В однородном списке все элементы имеют один и тот же тип. Неоднородный (гетерогенный) список имеет разнотипные элементы, причем однотипные элементы в нем объединяют в однородные подсписки.

Целью данной лабораторной работе является изучение приложения для работы с двунаправленным неоднородным списком с однородными подсписками, представленным на рис.7.1. Из структуры списка видно, что основной список состоит из взаимосвязанных первых элементов подсписков. Ссылка на начало списка находится в указателе first, а ссылка на конец списка – в указателе last.

 

Классы

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



class link

{

public:

link* prev; // указатель на предыдущий элемент основного списка

link* next; // указатель на следующий элемент основного списка

link* down; // указатель на следующий элемент подсписка

types type;

link(){prev=next=down=0;}//конструктор с умолчанием

};

 

Рис.7.1 – структура двунаправленного неоднородного списка

с n однородными подсписками

 

Примем также, что список предназначен для контроля товаров в спортивноммагазине, группируемых в подсписки по наименованию и фирме-производителю. Пусть товарами будут «велосипеды» и «роликовые коньки». Тогда в списке они должны быть представлены элементами подсписков - объектами соответствующих классов. Эти классы будут производными классами от базового класса. Для определения объекта производного класса в базовый класс введен элемент type типа-перечисление: enum types{Roll, Bike}.

 

//---------------------------------------------------------------------------

//производный класс для элемента подсписка - роликовые коньки

class TRoll:public link

{

public:

char* date; //дата поступления

char* comp; //производитель

int diam; //диаметр колес (в мм)

int count; //количество (штук)

TRoll(); //конструктор

~TRoll(); //деструктор

};

//--------------------------------------------------------------------------

//производный класс для элемента подсписка - велосипед

class TBike:public link

{

public:

char* date; //дата поступления

char* comp; //производитель

int diam; //диаметр колес (в мм)

int count; //количество (штук)

float weight; //вес (в кг)

int speeds; //количество скоростей

TBike(); //конструктор

~TBike(); //деструктор

};

//--------------------------------------------------------------------------

При создании объектов классов TRoll и TBike – элементов подсписков – в конструкторах этих классов в данное-элемент базового класса type подставляется значение (Roll, Bike), позволяющее идентифицировать создаваемые объекты. Доступ к type – через указатель на базовый класс link.

Теперь создадим класс, объединяющий созданные выше классы для элементов подсписков и предназначенный для создания объекта «список».

 

//--------------------------------------------------------------------------

//класс для списка

class list

{

public:

link* first; //указатель на начало списка

link* last; //указатель на конец списка

int count_dsp; //количество подсписков

int count_elem_sp; //количество элементов в списке

bool is_empty; //флаг "список пуст"

list(); //конструктор

~list(); //деструктор

void append_bike(TBike*);//добавление элемента-велосипеда в список

void append_roll(TRoll*);//добавление элемента-роликовые коньки

// в список

void del(int); //удаление элемента из списка

void out_list(); //вывод списка в таблицу

void clear_down(int); //удаление подсписка из списка

void clear(); //уничтожение списка

};

//--------------------------------------------------------------------------

Комментарии в объявлении последнего класса содержат перечень большинства операций при работе со списком. Следует отметить, что все элементы списка имеют по три указателя (prev, next, down), но только в элементах основной части списка, т.е. в первых элементах подсписков, используются все три указателя, а в остальных элементах подсписков – один указатель (down). При удалении первого элемента подсписка на его место ставится второй, что потребует в нем инициализации указателей prev и next адресами предыдущего и последующего элементов соответственно в основной части списка.

 

Проектирование приложения.

Выбор, размещение и задание свойств компонентов.

Коды классов, функций и обработчиков событий

 

Сохраните модуль главной формы под именем LR_7, а проект – под именем PR_LR_7.

Для размещения классов в проекте использован модуль, не связанный с формой. Чтобы создать такой модуль, нужно выполнить команду Файл/Новый/Другое… и открывшемся окне Новые элементы на странице Новый щелкнуть на пиктограмме Модуль. Модулю дано имя f_7. В заголовочном файле этого модуля f_7.h находятся приведенные выше объявления типа-перечисление и классов, а в файле реализации модуля f_7.cpp – реализации классов (определения функций-элементов классов). Чтобы получить возможность отладки модуля, перенесем на форму со страницы Дополнительно компонент StringGrid1 и директивой #include "LR_7.h" подключим модуль формы к файлу f_7.cpp.

 

Заголовочный файл f_7.h модуля f_7 (без формы)

//---------------------------------------------------------------

 

#ifndef f_7H

#define f_7H

//---------------------------------------------------------------------------

//тип-перечисление для идентификации элементов списка

enum types{Roll, Bike};

//---------------------------------------------------------------------------

//класс указателей - базовый класс для элементов подсписков

class link

{

public:

link* prev; // указатель на предыдущий элемент основного списка

link* next; // указатель на следующий элемент основного списка

link* down; // указатель на следующий элемент подсписка

types type;

link(){prev=next=down=0;}//конструктор с умолчанием

};

//---------------------------------------------------------------------------

//производный класс для элемента подсписка - роликовые коньки

class TRoll:public link

{

public:

char* date; //дата поступления

char* comp; //производитель

int diam; //диаметр колес (в мм)

int count; //количество (штук)

TRoll(); //конструктор

~TRoll(); //деструктор

};

//--------------------------------------------------------------------------

//производный класс для элемента подсписка - велосипед

class TBike:public link

{

public:

char* date; //дата поступления

char* comp; //производитель

int diam; //диаметр колес (в мм)

int count; //количество (штук)

float weight;//вес (в кг)

int speeds; //количество скоростей

TBike(); //конструктор

~TBike(); //деструктор

};

//--------------------------------------------------------------------------

//класс для списка

class list

{

public:

link* first; //указатель на начало списка

link* last; //указатель на конец списка

int count_dsp; //количество подсписков

int count_elem_sp; //количество элементов в списке

bool is_empty; //флаг "список пуст"

list(); //конструктор

~list(); //деструктор

void append_bike(TBike*);//добавление элемента-велосипеда в список

void append_roll(TRoll*);//добавление элемента-роликовые коньки в

//список

void del(int); //удаление элемента из списка

void out_list(); //вывод списка в таблицу

void clear_down(int); //удаление подсписка из списка

void clear(); //уничтожение списка

};

//--------------------------------------------------------------------------

#endif

 

Файл реализации f_7.cpp модуля f_7 (без формы)

//---------------------------------------------------------------------------

 

 

#pragma hdrstop

 

#include "f_7.h"

#include "LR_7.h"

 

//---------------------------------------------------------------------------

 

#pragma package(smart_init)

//---------------------------------------------------------------------------

 

//конструктор класса роликовые коньки

TRoll::TRoll()

{

type=Roll;

date=new char[50];

comp=new char[50];

diam=count=0;

}

//---------------------------------------------------------------------------

 

//деструктор класса роликовые коньки

TRoll::~TRoll()

{

delete[]date;

delete[]comp;

}

//---------------------------------------------------------------------------

 

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

TBike::TBike()

{

type=Bike;

date=new char[50];

comp=new char[50];

diam=count=weight=speeds=0;

}

//---------------------------------------------------------------------------

 

//деструктор класса велосипед

TBike::~TBike()

{

delete[]date;

delete[]comp;

}

//---------------------------------------------------------------------------

 

//конструктор класса список

list::list()

{

first=last=0;

count_dsp=count_elem_sp=0;

is_empty=true;

}

//-------------------------------------------------------------------------

 

//деструктор класса список

list::~list()

{

clear();

}

//------------------------------------------------------------------------

 

//добавление элемента-велосипеда в список

void list::append_bike(TBike*bike)

{

if(is_empty)//если список пуст

{//в список заносится первый элемент

//первый элемент образует первый подсписок

first=bike;

last=bike;

bike->prev=0;

bike->next=0;

bike->down=0;

bike->count=1;

count_dsp=1;

count_elem_sp=1;

is_empty=false;

return;

}

//список не пуст

bool f=false; //подсписок для добавляемого элемента не определен

 

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

//ставим указатель на начало списка

link* current=first;

 

//просматриваем основную часть списка для поиска подсписка,

//в который нужно добавить элемент

while(current)

{

if(current->type==Bike&&

strcmp(((TBike*)current)->comp,bike->comp)==0)

{f=true;break;} //подсписок для добавления элемента найден

current=current->next;

} //подсписок для добавления элемента не найден

 

if(!f)//добавляем элемент в конец списка, образуя новый подсписок

{

bike->prev=last;

last->next=bike;

last=bike;

bike->next=0;

bike->down=0;

bike->count=1;

count_dsp++;

count_elem_sp++;

}

else //добавляем элемент в конец найденного подсписка

{

link *curr=current;

while(curr->down)

curr=curr->down;

curr->down=bike;

bike->down=0;

((TBike*)current)->count++;

count_elem_sp++;

}

}

//--------------------------------------------------------------------------

 

//добавление элемента-роликовые коньки в список

void list::append_roll(TRoll*roll)

{

if(is_empty) //если список пуст

{ //в список заносится первый элемент

//первый элемент образует первый подсписок

last=roll;

last->next=0;

first=roll;

first->prev=0;

roll->down=0;

roll->count++;

count_dsp=1;

count_elem_sp=1;

is_empty=false;

return;

}

//список не пуст

bool f=false;//подсписок для добавляемого элемента не определен

 

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

//ставим указатель на конец списка

link* current=last;

 

//просматриваем основную часть списка для поиска подсписка,

//в который нужно добавить элемент

while(current)

{

if(current->type==Roll&&

strcmp(((TRoll*)current)->comp,roll->comp)==0)

{f=true; break;} //подсписок для добавления элемента найден

current=current->prev;

} //подсписок для добавления элемента не найден

 

if(!f)//добавляем элемент в конец списка, образуя новый подсписок

{

roll->prev=last;

last->next=roll;

last=roll;

roll->next=0;

roll->down=0;

roll->count=1;

count_dsp++;

count_elem_sp++;

}

else //добавляем элемент в конец найденного подсписка

{ link *curr=current;

while(curr->down)

curr=curr->down;

curr->down=roll;

roll->down=0;

((TRoll*)current)->count++;

count_elem_sp++;

}

}

//--------------------------------------------------------------------------

 

//вывод списка в таблицу StringGrid1

void list::out_list()

{

if(is_empty)//если список пуст

{

MessageBox(NULL,"Список пуст!","",0);

}

 

//число строк в таблице увеличиваем на количество

//элементов в списке

Form1->StringGrid1->RowCount=1+count_elem_sp;

 

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

//ставим указатель на начало списка

link *current=first;

 

int j=1; //вывод списка начнем с первой строки таблицы

 

//просматриваем основную часть списка,

//или первые элементы подсписков

for(int i=1; i<=count_dsp; i++)

{

if(current->type==Roll)//если в подсписке - ролик. коньки

{

//создаем текущий указатель подсписка и ставим его

//на первый элемент подсписка

TRoll* curr=(TRoll*)current;

 

//выводим элементы подсписка в таблицу

while(curr)

{ //выводим элемент подсписка в строку таблицы

Form1->StringGrid1->Cells[0][j]=IntToStr(j);

Form1->StringGrid1->Cells[1][j]="Roll";

Form1->StringGrid1->Cells[2][j]=IntToStr(curr->count);

Form1->StringGrid1->Cells[3][j]=curr->date;

Form1->StringGrid1->Cells[4][j]=curr->comp;

Form1->StringGrid1->Cells[5][j]=IntToStr(curr->diam);

 

j++; //переходим на следующую строку таблицы

 

//ставим указатель подсписка на следующий элемент подсписка

curr=(TRoll*)curr->down;

}

}

else if(current->type==Bike)//если в подсписке - велосипеды

{

//создаем текущий указатель подсписка и ставим его

//на первый элемент подсписка

TBike* curr=(TBike*)current;

 

//выводим элементы подсписка в таблицу

while(curr)

{ //выводим элемент подсписка в строку таблицы

Form1->StringGrid1->Cells[0][j]=IntToStr(j);

Form1->StringGrid1->Cells[1][j]="Bike";

Form1->StringGrid1->Cells[2][j]=IntToStr(curr->count);

Form1->StringGrid1->Cells[3][j]=curr->date;

Form1->StringGrid1->Cells[4][j]=curr->comp;

Form1->StringGrid1->Cells[5][j]=IntToStr(curr->diam);

Form1->StringGrid1->Cells[6][j]=FloatToStr(curr->weight);

Form1->StringGrid1->Cells[7][j]=IntToStr(curr->speeds);

 

j++; //переходим на следующую строку таблицы

 

//ставим указатель подсписка на следующий элемент подсписка

curr=(TBike*)curr->down;

}

}

current=current->next;//переходим на следующий подсписок

}

 

//вывод информации о списке

Form1->StatusBar1->SimpleText="Количество подсписков - "+

IntToStr(count_dsp)+" "+"Количество элементов в списке - "+

IntToStr(count_elem_sp);

}

//-------------------------------------------------------------------------

 

//удаление из списка элемента, выделенного в строке r

//таблицы вывода списка

void list::del(int r)

{

if(r==1&&count_elem_sp==1)//в списке только один элемент

{

link *current=first;

delete first;

first=last=0;

if(current->type==Roll) ((TRoll*)current)->count--;

else ((TBike*)current)->count--;

count_elem_sp--;//количество элементов в списке уменьшаем на один

count_dsp--;

is_empty=true;

MessageBox(NULL,"Список из одного элемента уничтожен!","",0);

return;

}

 

link *curr, *current=first;

int j;

if(current->type==Roll) j=((TRoll*)current)->count;

else j=((TBike*)current)->count;

 

bool f1=false,

f2=false;

 

while(current)//ищем подсписок с удаляемым элементом

{

if(j==r) {f1=true; break;}//удаляемый элемент - последний в подсписке

if(j>r) {f2=true; break;} //удаляемый элемент - внутри подсписка

current=current->next;//переход на следующий подсписок

if(current->type==Roll) j+=((TRoll*)current)->count;

else j+=((TBike*)current)->count;

}

 

//удаляемый элемент - последний в подсписке из нескольких элементов

if(f1&&current->down)

{

curr=current;

while(curr->down->down)//ищем предпоследний элемент в подсписке

curr=curr->down;

delete curr->down; //удаление последнего элемента в подсписке

curr->down=0;

//количество элементов в подсписке уменьшаем на один

if(current->type==Roll) ((TRoll*)current)->count--;

else ((TBike*)current)->count--;

count_elem_sp--;//количество элементов в списке уменьшаем на один

MessageBox(NULL,"Элемент удален!","",0);

return;

}

 

//удаляемый элемент - в первом подсписке из одного элемента

if(f1&&!current->down&&current->next&&!current->prev)

{

first=current->next;//переносим начало списка на следующий элемент

first->prev=0;

delete current; //удаление единственного элемента в подсписке

count_dsp--; //количество подсписков в списке уменьшаем на один

count_elem_sp--; //количество элементов в списке уменьшаем на один

MessageBox(NULL,"Элемент удален!","",0);

return;

}

 

//удаляемый элемент - в последнем подсписке из одного элемента

if(f1&&!current->down&&!current->next&&current->prev)

{

last=current->prev;//переносим конец списка на предыдущий элемент

last->next=0;

delete current; //удаление единственного элемента в подсписке

count_dsp--; //количество подсписков в списке уменьшаем на один

count_elem_sp--; //количество элементов в списке уменьшаем на один

MessageBox(NULL,"Элемент удален!","",0);

return;

}

 

//удаляемый элемент - в одноэлементном подсписке

//внутри основной части списка

if(f1&&!current->down&&current->next&&current->prev)

{

current->prev->next=current->next;//выключаем одноэлементный

// подсписок

current->next->prev=current->prev;//из списка

delete current; //удаление единственного элемента в подсписке

count_dsp--; //количество подсписков в списке уменьшаем на один

count_elem_sp--; //количество элементов в списке уменьшаем на один

MessageBox(NULL,"Элемент удален!","",0);

return;

}

 

//удаляемый элемент - первый в подсписке из нескольких элементов

int k;

if(current->type==Roll) k =((TRoll*)current)->count;

else k =((TBike*)current)->count;

if(f2&&(j-k+1==r))

{

//на место первого ставим второй элемент подсписка

//удаляемый элемент - первый в единственном

//подсписке из нескольких элементов

if(current==first&&current==last)

{

first=current->down;

last=current->down;

}

 

//удаляемый элемент - первый в первом

//подсписке из нескольких элементов

if(current==first)

{

current->next->prev=current->down;

current->down->next=current->next;

}

 

//удаляемый элемент - первый в последнем

//подсписке из нескольких элементов

if(current==last)

{

current->prev->next=current->down;

current->down->prev=current->prev;

}

 

//удаляемый элемент - первый во внутреннем

//подсписке из нескольких элементов

if(current->prev&&current->next)

{

current->next->prev=current->down;

current->down->next=current->next;

current->prev->next=current->down;

current->down->prev=current->prev;

}

 

//количество элементов в подсписке уменьшаем на один

if(current->type==Roll) ((TRoll*)current->down)->count=k-1;

else ((TBike*)current->down)->count=k-1;

 

//если подсписок первый - переносим first на второй элемент подсписка

if(current==first) first=current->down;

 

// если подсписок последний - переносим last на второй элемент

// подсписка

if(current==last) last=current->down;

delete current;

count_elem_sp--;

MessageBox(NULL,"Элемент удален!","",0);

return;

}

 

//удаляемый элемент - внутри подсписка из нескольких элементов

j=j-k;//количество элементов в списке до подсписка

//с удаляемым элементом

curr=current;

link *pr;//указатель на предыдущий по отношению к текущему (curr)

// элементу подсписка

while(j<r) //поиск элемента в подсписке

{

pr=curr;

curr=curr->down;

j++;

}

 

pr->down=curr->down;//выключение элемента из подсписка

 

delete curr; //удаление элемента

 

//количество элементов в подсписке уменьшаем на один

if(current->type==Roll) ((TRoll*)current)->count--;

else ((TBike*)current)->count--;

 

count_elem_sp--;//количество элементов в списке уменьшаем на один

 

MessageBox(NULL,"Элемент удален!","",0);

return;

}

//-------------------------------------------------------------------------

 

//удаление подсписка с выделенным в строке rd

//таблицы вывода списка элементом

void list::clear_down(int rd)

{

if(is_empty)

{

// MessageBox(NULL,"Список пуст!","",0);

return;

}

link *current=first;//указатель на текущий элемент списка

if(!current->next) //список состоит из одного подсписка

{

link *pr;//указатель на предыдущий по отношению

//к текущему (current) элементу подсписка

while(current)

{

pr=current;

current=current->down;

delete pr;

}

first=last=0;

count_dsp=0;

count_elem_sp=0;

is_empty=true;

MessageBox(NULL,"Список из одного подсписка уничтожен!","",0);

return;

}

int j;//номер текущей строки в таблице вывода списка

if(current->type==Roll) j=((TRoll*)current)->count;

else j=((TBike*)current)->count;

while(j<rd) //поиск подсписка с выделенным в таблице элементом

{

current=current->next;//переход на следующий подсписок

if(current->type==Roll) j+=((TRoll*)current)->count;

else j+=((TBike*)current)->count;

}

//выключение подсписка из списка

//выключаемый подсписок - первый в списке

if(!current->prev)

{

current->next->prev=0;

//перенос начала списка па следующий подсписок

first=current->next;

}

//выключаемый подсписок - последний в списке

else if(!current->next)

{

current->prev->next=0;

//перенос конца списка на предыдущий подсписок

last=current->prev;

}

//выключаемый подсписок - внутри списка

else

{

current->prev->next=current->next;

current->next->prev=current->prev;

}

count_dsp--;//количество подсписков в списке уменьшаем на один

//количество элементов в списке уменьшаем на подсписок

if(current->type==Roll)

count_elem_sp-=((TRoll*)current)->count;

else count_elem_sp-=((TBike*)current)->count;

//освобождение памяти, занимаемой подсписком

link *pr;//указатель на предыдущий по отношению

//к текущему (current) элементу подсписка

while(current)

{

pr=current;

current=current->down;

delete pr;

}

MessageBox(NULL,"Подсписок удален!","",0);

return;

}

//------------------------------------------------------------------------

 

//уничтожение списка

void list::clear()

{

if(is_empty)

{

MessageBox(NULL,"Список пуст!","",0);

return;

}

link *pr,*curr,*current=first;

int k;

while(current)

{

curr=current;

if(current->type==Roll) k=((TRoll*)current)->count;

else k=((TBike*)current)->count;

count_elem_sp-=k;

current=current->next;//переход на следующий подсписок

while(curr)

{

pr=curr;

curr=curr->down;

delete pr;

}

count_dsp--;

}

if(!count_dsp&&!count_elem_sp)

{

is_empty=true;

first=0;

last=0;

}

if(is_empty)

{

MessageBox(NULL,"Список уничтожен!","",0);

return;

}

}

//------------------------------------------------------------------------

Достаточно полную информацию для размещения остальных компонентов на форме и задания их свойств можно получить из представленных ниже рис.7.2, рис.7.3 и заголовочного файла модуля LR_7.

 

Рис.7.2 – форма по окончании проектирования

 

Рис.7.3 – дерево объектов


Заголовочный файл LR_7.h модуля LR_7

//---------------------------------------------------------------------------

#ifndef LR_7H

#define LR_7H

//---------------------------------------------------------------------------

#include <Classes.hpp>

#include <Controls.hpp>

#include <StdCtrls.hpp>

#include <Forms.hpp>

#include <Grids.hpp>

#include <ComCtrls.hpp>

#include <ExtCtrls.hpp>

#include "CSPIN.h"

#include <ActnList.hpp>

#include <ActnMan.hpp>

#include <ImgList.hpp>

#include <StdActns.hpp>

#include <ActnCtrls.hpp>

#include <ActnMenus.hpp>

#include <ToolWin.hpp>

#include <Dialogs.hpp>

//---------------------------------------------------------------------------

class TForm1 : public TForm

{

__published: // IDE-managed Components

TStringGrid *StringGrid1;

TStatusBar *StatusBar1;

TGroupBox *GroupBox1;

TLabeledEdit *LabeledEdit1;

TLabeledEdit *LabeledEdit2;

TLabeledEdit *LabeledEdit3;

TRadioButton *RadioButton1;

TRadioButton *RadioButton2;

TCSpinEdit *CSpinEdit1;

TDateTimePicker *DateTimePicker1;

TButton *Button1;

TLabel *Label1;

TLabel *Label2;

TImageList *ImageList1;

TActionManager *ActionManager1;

TAction *FileSave1;

TAction *Add;

TAction *Del;

TAction *Clear_down;

TAction *Clear;

TAction *A_exit;

TActionMainMenuBar *ActionMainMenuBar1;

TAction *Out;

TSaveDialog *SaveDialog1;

TCheckBox *CheckBox1;

TAction *FileSaveAs1;

TAction *FileOpen1;

TActionToolBar *ActionToolBar2;

TActionToolBar *ActionToolBar1;

void __fastcall FormCreate(TObject *Sender);

void __fastcall RadioButton1Click(TObject *Sender);

void __fastcall RadioButton2Click(TObject *Sender);

void __fastcall AddExecute(TObject *Sender);

void __fastcall A_exitExecute(TObject *Sender);

void __fastcall OutExecute(TObject *Sender);

void __fastcall StringGrid1SelectCell(TObject *Sender, int ACol,

int ARow, bool &CanSelect);

void __fastcall DelExecute(TObject *Sender);

void __fastcall Clear_downExecute(TObject *Sender);

void __fastcall ClearExecute(TObject *Sender);

void __fastcall FileSave1Execute(TObject *Sender);

void __fastcall FileOpen1Execute(TObject *Sender);

void __fastcall FileSaveAs1Execute(TObject *Sender);

private: // User declarations

public: // User declarations

__fastcall TForm1(TComponent* Owner);

};

//---------------------------------------------------------------------------

extern PACKAGE TForm1 *Form1;

//---------------------------------------------------------------------------

#endif

Перенесем на форму остальные компоненты и зададим их свойствам значения. Со страницы Стандарт - контрольный индикатор с флажком CheckBox1 (Caption – добавлять и удалять с выводом в таблицу, Checked – false), две радиокнопки – RadioButton1 (Caption - Велосипед, Checked – true, Enabled - true) и RadioButton2 (Caption - Ролик. коньки, Checked – false, Enabled - true), GroupBox1 (Caption – Велосипед), Label1 (Caption – Дата поступления), Label2 (Caption – Кол-во скоростей), Button1 (Caption – Добавить элемент), со страницы Win32 – окно ввода дат и времени DateTimePicker1, StatusBar1, ImageList1, со страницы Дополнительно – LabeledEdit1 (EditLabel->Caption – Производитель:), LabeledEdit2 (EditLabel->Caption – Колеса (мм):), LabeledEdit3 (EditLabel->Caption – Вес (кг):), диспетчер действий ActionManager1 и полосу главного меню ActionMainMenuBar1, со страницы Примеры – CSpinEdit1, со страницы Диалоги – SaveDialog1.

По умолчанию полоса главного меню расположится вверху, на всю ширину формы. Задайте её свойство Align = alNone, чтобы придать ей нужные размеры и расположить в нужном месте.

 

Диспетчеризация действий на основе компонентов ActionManager, ActionMainMenuBar, ActionToolBar

Диспетчер действий ActionManager не только создает и хранит набор действий, как и ActionList, но и управляет полосами действий – визуальными компонентами, на которых располагаются элементы пользовательского интерфейса. К таким компонентам относятся ActionMainMenuBar – полоса главного меню и ActionToolBar – инструментальная панель. Во время проектирования эти компоненты могут вводиться в приложение непосредственно из палитры компонентов, или создаваться простым перетаскиванием на них необходимых действий из окна Редактора Действий ActionManager. Компонент ActionManager запоминает информацию о составе набора действий и конфигурации полос действий в текстовом или двоичном файле на диске.

Рассмотрим основной компонент всей этой системы – ActionManager. Свойство Images компонента ActionManager указывает на компонент ImageList, содержащий пиктограммы, используемые для обозначения действий.

Загрузим в компонент ImageList1 пиктограммы из файлов fldropen, filesave, floppy, insert, show, delete, arrow1u, erase, dooropen. В компоненте ActionManager1 установим свойство Images равным ImageList1, связав тем самым диспетчер действий со списком изображений.

Свойство State определяет реакцию на действия пользователя. Значение asNormal соответствует нормальной рабочей реакции: при щелчке пользователя на доступных интерфейсных компонентах действий выполняются соответствующие действия.

Свойство FileName задает имя файла, в котором ActionManager хранит информацию о составе связанных с ним полос действий. В начале выполнения приложения ActionManager читает информацию из этого файла и в соответствии с ней формирует полосы действий. А при любых изменениях настройки в процессе выполнения ActionManager записывает в этот файл проведенные изменения. Так что при следующем сеансе работы состав полос действий будет таким, каким сделал его пользователь в предыдущем сеансе.

Примечание. При изменении полос действий в процессе проектирования нужно задавать значение FileName по окончании проектирования, так как в противном случае в файле будет сохранено состояние полос действий предыдущего сеанса. Если же потребовалось изменить полосы действий после того, как было задано значение FileName, то нужно предварительно удалить с диска файл, в котором запоминается состояние. В этом случае при очередном выполнении приложения этот файл создастся заново.

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

Перейдем к рассмотрению и использованию основного инструмента проектирования – Редактора Действий компонента ActionManager1. Двойным щелчком на компоненте вызывается окно Редактора Действий (Редактирование Form1->ActionManager1) на странице Действия с пустыми панелями Категории: и Действия:. Щелкнем правой кнопкой мыши и в появившемся контекстном меню выберем команду Новое действие. Повторим команду Новое действие еще два раза. После этого в панели Действия: появятся имена Action1, Action2, Action3 объектов этих действий, а в панели Категории: – их категории. Выделим Action1. В Инспекторе Объектов будут видны свойства, которые можно изменить: Caption, Hint, ShortCut и другие. Строка свойства Hint отображается в окне Редактора Действий в панели Описание. Можно изменить также категории действий – их свойства Category. Если в компоненте ActionList понятия категорий лишены определенного смысла, то здесь – при создании меню названия категорий станут надписями головных разделов меню.

Зададим свойства объектов действий. Для Action1: Caption – Сохранить, Category - Файл, Hint – сохранить список в файле, Name - FileSave1, ShortCat - F2. Для Action2: Caption – Сохранить как, Category - Файл, Hint – сохранить список в файле как…, Name - FileSaveAs1, ShortCat – Ctrl+K. Для Action3: Caption – Открыть, Category - Файл, Hint – вывести список из файла, Name - FileOpen1, ShortCat - Ctrl+O. В свойство ImageIndex заносим соответствующие значения.

В дальнейшем действия будут связаны с соответствующими компонентами, например, разделами меню. Щелчок пользователя на разделе будущего меню инициализирует соответствующее действие, что вызывает событие OnExecute. Для перехода в обработчик этого события действия Сохранить сделайте на нем двойной щелчок. Занесите в обработчик соответствующий код (см. файл реализации модуля LR_7). Подобным же образом заполните обработчики для действий Сохранить как и Открыть. Затем для всех действий задайте свойство Enabled = true.

Описанным выше образом командой Новое действие создайте действия Action1, Action2, Action3, Action4, Action5, Action6. Для всех этих действий в свойство Category внесите Действия. Задайте остальные свойства новых объектов действий. Для Action1: Caption – Добавить элемент, Hint – добавить элемент в список, Name - Add, ShortCat - Ctrl+A. Для Action2: Caption – Вывести список, Hint – вывести список в таблицу, Name - Out, ShortCat – Ctrl+T. Для Action3: Caption – Удалить элемент, Hint – удалить элемент из списка, Name - Del, ShortCat - Ctrl+B. Для Action4: Caption – Удалить подсписок, Hint – удалить подсписок из списка, Name - Clear_down, ShortCat - Ctrl+C. Для Action5: Caption – Уничтожить список, Hint – уничтожить список, Name - Clear, ShortCat – Ctrl+D. Для Action6: Caption – Выход, Hint – Выход/Завершение работы, Name - A_exit, ShortCat - Ctrl+E. В свойство ImageIndex заносите соответствующие значения.

В обработчики события OnExecute этих шести действий внесите коды из файла реализации модуля LR_7. Убедитесь, что для всех шести действий свойство Enabled = true.

Теперь выбор категории (Файл, Действия) означает выбор соответствующего списка действий. Порядок действий можно изменить перетаскиванием мышью.

Поочередно перетащите мышью категории на полосу главного меню. При этом все действия перенесутся в меню, а названия категорий станут надписями головных разделов меню (см. рис.7.4). Действия также можно перетаскивать в меню поодиночке и там изменять порядок их следования.

Перейдите на страницу Панели окна Редактора Действий. Кнопкой Новый…добавьте на форму первую инструментальную панель ActionToolBar1. (Отметим, что компонент ActionToolBar можно также добавлять на форму переносом из палитры компонентов.) По умолчанию панель расположится вверху, на всю ширину формы. Задайте её свойство Align = alNone, чтобы придать ей нужные размеры и расположить в нужном месте. Здесь и в дальнейшем может оказаться полезным задание свойству Orientation значения boTopToBottom или boBottomToTop. Полезно также воспользоваться свойством Constraints. В свойство Hint занесите инструментальная панель 1, в ShowHint – true.

Перейдите на страницу Действия окна Редактора Действий. Перетащите из Редактора Действий на панель категорию Файл. При этом все действия категории перенесутся на панель. Действия также можно перетаскивать на панель поодиночке и там изменять порядок их следования.

Описанным выше образом добавьте на форму вторую инструментальную панель ActionToolBar2, задайте в ней свойства и перетащите на неё категорию Действия.

Выделите одну из полос действий на странице Панели окна Редактора Действий и просмотрите в Инспекторе Объектов ее свойства. В свойствах Caption (надпись) измените значения полос действий соответственно на Главное меню, Инструментальная панель 1, Инструментальная панель 2.

Выделите компонент ActionManager1 и задайте значение свойства FileName в окне Инспектора Объектов, т.е. имя файла, в котором ActionManager1 хранит информацию о составе связанных с ним полос действий.

Выделите кнопку Добавить элемент и в её свойство Action занесите Add, чтобы связать кнопку с одноименным действием.

Дополните файл реализации модуля LR_7 обработчиками событий: создания формы, где размещается код для создания заголовка таблицы, и щелчков на компонентах RadioButton1 и RadioButton2, в которых реализуется подготовка компонентов для ввода данных элементов списка.

Удаление элемента и подсписка из списка осуществляется по ячейке, выделенной в таблице вывода списка. При этом используется событие OnSelectCell компонента StringGrid1. В обработчик этого события передаются целые параметры ACol и ARow – столбец и строка выделенной ячейки и булев параметр CanSelect – допустимость выбора.

 

int r; //переменная для номера строки выделенной ячейки в таблице

bool flag=true; //флаг - нет выделенной ячейки в таблице

void __fastcall TForm1::StringGrid1SelectCell(TObject *Sender, int ACol,

int ARow, bool &CanSelect)

{

r=ARow; //номер строки выделенной ячейки сохранен в переменной r

flag=false; //ячейка в таблице выделена

}

Для удаления элемента и подсписка из списка используется параметр ARow – номер строки выделенной ячейки.

На этом проектирование приложения завершается.

 

Рис.7.4 – меню

 

Тестирование и использование приложения

1.Запустите приложение на выполнение, нажав быстрые кнопки Сохранить все и Запуск.

2.Выполните тестирование по рис.7.5. Рекомендуется добавлять и удалять элементы с включенным индикатором. Команда Вывести список необходима при отладке и тестировании приложения.

3.Составьте и выполните тесты, которые проверят правильность всех случаев добавления и удаления элементов подсписков (см. комментарии в файлах f_7.cpp и LR_7.cpp).

4.Убедитесь в правильности сохранения списка в файле.

5.Модифицируйте код, переместив данные-элементы классов TRollи TBike в закрытые части классов. Выполните отладку. Результаты продемонстрируйте преподавателю.

 

Рис.7.5 – форма с результатами тестирования

 

 

Файл реализации LR_7.cpp модуля LR_7

 

//---------------------------------------------------------------------------

 

#include <vcl.h>

#pragma hdrstop

 

#include "LR_7.h"

#include "f_7.h"

#include<string.h>

#include<fstream.h>

//---------------------------------------------------------------------------

 

#pragma package(smart_init)

#pragma link "CSPIN"

#pragma resource "*.dfm"

TForm1 *Form1;

//---------------------------------------------------------------------------

 

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

}

//---------------------------------------------------------------------------

 

//при создании формы создаем заголовок таблицы

void __fastcall TForm1::FormCreate(TObject *Sender)

{

StringGrid1->FixedRows=1;

StringGrid1->RowCount=1;

StringGrid1->FixedCols=0;

StringGrid1->ColCount=8;

StringGrid1->Cells[0][0]="номер";

StringGrid1->Cells[1][0]="изделие";

StringGrid1->Cells[2][0]="кол-во(шт) в п/сп";

StringGrid1->Cells[3][0]="дата поступления";

StringGrid1->Cells[4][0]="производитель";

StringGrid1->Cells[5][0]="диам колес(мм)";

StringGrid1->Cells[6][0]="вес(кг)";

StringGrid1->Cells[7][0]="кол-во скоростей";

}

//---------------------------------------------------------------------------

 

//активация компонентов для ввода данных элемента списка - велосипед

void __fastcall TForm1::RadioButton1Click(TObject *Sender)

{

GroupBox1->Caption="Велосипед";

DateTimePicker1->SetFocus();

LabeledEdit3->Enabled=true;

CSpinEdit1->Enabled=true;

Label2->Enabled=true;

}

//---------------------------------------------------------------------------

//подготовка компонентов для ввода данных элемента

// списка - ролик. коньки

void __fastcall TForm1::RadioButton2Click(TObject *Sender)

{

GroupBox1->Caption="Ролик. коньки";

DateTimePicker1->SetFocus();

LabeledEdit3->Enabled=false;

CSpinEdit1->Enabled=false;

Label2->Enabled=false;

}

//---------------------------------------------------------------------------

 

list spisok;//создаем объект класса - список

 

void __fastcall TForm1::AddExecute(TObject *Sender)

{

if(RadioButton1->Checked)

{ //создаем элемент списка - велосипед

TBike *bike=new TBike;

strcpy(bike->date,(DateToStr(DateTimePicker1->Date)).c_str());

 

if(LabeledEdit1->Text=="")

{

MessageBox(NULL,"Введите название производителя!","Ошибка", 0);

LabeledEdit1->SetFocus();

return;

}

strcpy(bike->comp,(LabeledEdit1->Text).c_str());

if(LabeledEdit2->Text==""||!isdigit(LabeledEdit2->Text[1]))

{

MessageBox(NULL,"Введите диаметр колес!","Ошибка",0);

LabeledEdit2->SetFocus();

return;

}

bike->diam=StrToInt(LabeledEdit2->Text);

if(LabeledEdit3->Text==""||!isdigit(LabeledEdit3->Text[1]))

{

MessageBox(NULL,"Введите вес!","Ошибка",0);

LabeledEdit3->SetFocus();

return;

}

bike->weight=StrToFloat(LabeledEdit3->Text);

bike->speeds=CSpinEdit1->Value;

//созданный элемент добавляем в список

spisok.append_bike(bike);

}

 

if(RadioButton2->Checked)

{ //создаем элемент списка - роликовые коньки

TRoll *roll=new TRoll;

strcpy(roll->date,(DateToStr(DateTimePicker1->Date)).c_str());

if(LabeledEdit1->Text=="")

{

MessageBox(NULL,"Введите название производителя!","Ошибка",0);

LabeledEdit1->SetFocus();

return;

}

strcpy(roll->comp,(LabeledEdit1->Text).c_str());

if(LabeledEdit2->Text==""||!isdigit(LabeledEdit2->Text[1]))

{

MessageBox(NULL,"Введите диаметр колес!","Ошибка",0);

LabeledEdit2->SetFocus();

return;

}

roll->diam=StrToInt(LabeledEdit2->Text);

//созданный элемент добавляем в список

spisok.append_roll(roll);

}

MessageBox(NULL,"Элемент добавлен!","",0);

 

//если индикатор включен - список выводится в таблицу

if(CheckBox1->Checked)spisok.out_list();

 

//вывод информации о списке

Form1->StatusBar1->SimpleText="Количество подсписков - "+

IntToStr(spisok.count_dsp)+" "+"Количество элементов в списке - "+

IntToStr(spisok.count_elem_sp);

}

//---------------------------------------------------------------------------

 

void __fastcall TForm1::A_exitExecute(TObject *Sender)

{

Close();

}

//---------------------------------------------------------------------------

 

//вывод списка в таблицу

void __fastcall TForm1::OutExecute(TObject *Sender)

{

spisok.out_list();

}

//---------------------------------------------------------------------------

 

int r; //переменная для номера строки выделенной ячейки в таблице

bool flag=true; //флаг - нет выделенной ячейки в таблице

 

void __fastcall TForm1::StringGrid1SelectCell(TObject *Sender, int ACol,

int ARow, bool &CanSelect)

{

r=ARow; //номер строки выделенной ячейки сохранен в переменной r

flag=false; //ячейка в таблице выделена

}

//---------------------------------------------------------------------------

 

//удаляем из списка элемент, соответствующий номеру

//строки выделенной в таблице ячейки

void __fastcall TForm1::DelExecute(TObject *Sender)

{

if(spisok.is_empty)//если список пуст

{

MessageBox(NULL,"Список пуст!","",0);

return;

}

 

if(flag) //если ячейка в таблице не выделена

{

MessageBox(NULL,"Выделите элемент в таблице!","Ошибка",0);

return;

}

//удаляем из списка элемент, соответствующий значению переменной r

spisok.del(r);

 

//если индикатор включен - список выводится в таблицу

if(CheckBox1->Checked)spisok.out_list();

 

flag=true;//можно снова выделять ячейку в таблице

}

//---------------------------------------------------------------------------

 

//удаляем из списка подсписок, соответствующий номеру

// строки выделенной в таблице ячейки

void __fastcall TForm1::Clear_downExecute(TObject *Sender)

{

if(spisok.is_empty) //если список пуст

{

MessageBox(NULL,"Список пуст!","",0);

return;

}

if(flag) //если ячейка в таблице не выделена

{

MessageBox(NULL,"Выделите элемент в таблице!","Ошибка",0);

return;

}

//удаляем из списка подсписок, соответствующий значению переменной r

spisok.clear_down(r);

 

//если индикатор включен - список выводится в таблицу

if(CheckBox1->Checked)spisok.out_list();

 

flag=true; //можно снова выделять ячейку в таблице

}

//---------------------------------------------------------------------------

 

//уничтожаем список

void __fastcall TForm1::ClearExecute(TObject *Sender)

{

if(spisok.is_empty) //если список пуст

{

MessageBox(NULL,"Список пуст!","",0);

return;

}

 

//для объекта - список вызывается функция уничтожения списка

spisok.clear();

 

//уничтожение списка контролируется выводом в таблицу

spisok.out_list();

}

//---------------------------------------------------------------------------

 

AnsiString fn=""; //строка для имени файла

 

//вспомогательная строка для вывода списка из таблицы в файл

char str[50];

 

int s;//вспомогательная переменная для вывода в файл

//количества элементов в списке

 

//---------------------------------------------------------------------------

 

//сохраняем список в файле

void __fastcall TForm1::FileSave1Execute(TObject *Sender)

{

if(fn!="") //если есть имя файла со списком

{

ofstream outfile(fn.c_str(),ios::out);//открываем файл для записи

 

//в переменную s заносим количество элементов в списке

s=spisok.count_elem_sp;

//выводим в файл число из переменной s побайтно

outfile.write((char*)&s,sizeof(s));

 

//из таблицы список выводим в файл

for(int i=1; i<=s; i++)

{

for(int j=0;j<8;j++)

{ //преобразовав элемент из таблицы к типу char*,

//копируем его в вспомогательную строку str

strcpy(str,Form1->StringGrid1->Cells[j][i].c_str());

//выводим побайтно содержимое str в файл

outfile.write((char*)&str,50);

}

}

outfile.close();//закрываем файл

}

else //если файл со списком отсутствует

//открывается диалог сохранения в файле и пользователь

//выбирает имя файла

if(SaveDialog1->Execute())

{ //выбранное имя файла сохраняется в строке fn

fn=SaveDialog1->FileName;

//создается и открывается для записи файл с выбранным именем

ofstream outfile(fn.c_str(),ios::out);

//в переменную s заносим количество элементов в списке

s=spisok.count_elem_sp;

//выводим в файл число из переменной s побайтно

outfile.write((char*)&s,sizeof(s));

//из таблицы список выводим в файл

for(int i=1; i<=s; i++)

{

for(int j=0;j<8;j++)

{ //преобразовав элемент таблицы к типу char*,

//копируем его во вспомогательную строку str

strcpy(str,Form1->StringGrid1->Cells[j][i].c_str());

//выводим побайтно содержимое str в файл

outfile.write((char*)&str,50);

}

}

outfile.close();//закрываем файл

}

}

//---------------------------------------------------------------------------

 

//выводим список из файла в таблицу

//по данным таблицы формируем список в оперативной памяти

void __fastcall TForm1::FileOpen1Execute(TObject *Sender)

{

spisok.clear();//уничтожаем список в оперативной памяти

 

//открываем файл на чтение с выбранным при сохранении именем

ifstream infile(fn.c_str(),ios::in);

if(!infile) //проверка, удалось ли открыть файл

{

MessageBox(NULL,"Файл не удается открыть!","Ошибка",0);

return;

}

 

//в переменную s читаем из файла количество элементов в списке

infile.read((char*)&s,sizeof(s));

 

//читаем файл в таблицу

for(int i=1; i<=s; i++)

{

Form1->StringGrid1->RowCount++;//добавляем строку в таблице

for(int j=0;j<8;j++)

{ //читаем в строку str из файла очередную запись в 50 байт

infile.read((char*)&str,50);

 

//из строки str переносим запись в элемент таблицы

Form1->StringGrid1->Cells[j][i]=(AnsiString)str;

}

}

 

infile.close();//закрываем файл, открытый на чтение

//из данных строк таблицы формируем элементы списка

//элементы списка добавляем в список

 

for(int i=1; i<=s; i++)

{

if(StringGrid1->Cells[1][i]=="Bike")

{ //формируем элемент списка - велосипед

TBike* bike=new TBike;

strcpy(bike->date,StringGrid1->Cells[3][i].c_str());

strcpy(bike->comp,StringGrid1->Cells[4][i].c_str());

bike->diam=StrToInt(StringGrid1->Cells[5][i]);

bike->weight=StrToFloat(StringGrid1->Cells[6][i]);

bike->speeds=StrToInt(StringGrid1->Cells[7][i]);

spisok.append_bike(bike);//добавляем в список

}

 

if(StringGrid1->Cells[1][i]=="Roll")

{ //формируем элемент списка - роликовые коньки

TRoll* roll=new TRoll;

strcpy(roll->date,StringGrid1->Cells[3][i].c_str());

strcpy(roll->comp,StringGrid1->Cells[4][i].c_str());

roll->diam=StrToInt(StringGrid1->Cells[5][i]);

spisok.append_roll(roll);//добавляем в список

}

}

 

spisok.out_list(); //выводим прочитанный список в таблицу

//вывод информации о прочитанном списке

StatusBar1->SimpleText="Количество подсписков - "+

IntToStr(spisok.count_dsp)+" "+

"Количество элементов в списке - "+

IntToStr(spisok.count_elem_sp);

}

//---------------------------------------------------------------------------

 

//сохраняем как...

void __fastcall TForm1::FileSaveAs1Execute(TObject *Sender)

{

//выбранное ранее имя файла заносится в свойство FileName

//компонента SaveDialog1 и предлагается пользователю по умолчанию

SaveDialog1->FileName=fn;

 

//если при открытии диалога пользователь выбрал новое имя

if(SaveDialog1->Execute())

{ //то новое имя файла сохраняется в строке fn

fn=SaveDialog1->FileName;

 

//создается и открывается для записи файл с новым именем

ofstream outfile(fn.c_str(),ios::out);

 

if(!outfile) //проверка, удалось ли создать и открыть файл

{

MessageBox(NULL,"Файл не удается создать!","Ошибка",0);

return;

}

 

//в переменную s заносим количество элементов в списке

s=spisok.count_elem_sp;

 

//выводим в файл число из переменной s побайтно

outfile.write((char*)&s,sizeof(s));

 

//из таблицы список выводим в файл

for(int i=1; i<=s; i++)

{

for(int j=0;j<8;j++)

{ //преобразовав элемент таблицы к типу char*,

//копируем его в вспомогательную строку str

strcpy(str,Form1->StringGrid1->Cells[j][i].c_str());

//выводим побайтно содержимое str в файл

outfile.write((char*)&str,50);

}

}

outfile.close(); //закрываем файл

}

}

//---------------------------------------------------------------------------


Контрольные вопросы

1.Расскажите о назначении базового класса.

2.Объясните содержание класса link, TBike, TRoll, list.

3.Как выполняется конструктор класса link, TBike, TRoll, list?

4.Как выполняется деструктор класса link, TBike, TRoll, list?

5.Укажите в коде точки, где вызывается конструктор класса link, TBike, TRoll, list.

6.Укажите в коде точки, где вызывается деструктор класса link, TBike, TRoll, list.

7.Как нужно изменить остальное содержание класса link, TBike, TRoll, list, если данные-элементы класса из открытой части класса перенести в закрытую часть класса?

8.Объясните, как в список заносится первый элемент.

9.Объясните, как в список добавляется второй и последующие элементы с разными типами, отличающимися от типа первого элемента.

10.Объясните, как добавляется элемент в подсписок.

11.Как добавляется в список новый подсписок?

12.Когда и как переназначаются указатели на начало и конец списка?

13.Как удалить элемент из первого подсписка (элемент – единственный в подсписке, первый в подсписке, последний в подсписке, находится внутри подсписка)?

14.Как удалить элемент из последнего подсписка (элемент – единственный в подсписке, первый в подсписке, последний в подсписке, находится внутри подсписка)?

15.Как удалить элемент из внутреннего подсписка (элемент – единственный в подсписке, первый в подсписке, последний в подсписке, находится внутри подсписка)?

16.Как удалить подсписок (первый, последний, внутренний, из одного элемента, из нескольких элементов)?

17.Как уничтожить список?

18.Как вывести список из ОП в таблицу?

19.Расскажите, как список сохранить в файле.

20.Как вывести список из файла в таблицу?

21.Как ввести список в ОП из таблицы? из файла, минуя таблицу?

22.Как по выделенной в таблице ячейке определить положение удаляемого элемента? подсписка?

23.Расскажите о назначении и возможностях диспетчера действий ActionManager. Что относится к полосам дествий ActionManager?

24.Расскажите об использовании Редактора Действий ActionManager.

25.Как создать меню, инструментальную панель с помощью ActionManager?

26.Как связать меню, инструментальную панель с ImageList?

27.Как сохранить настройки полос действий ActionManager?

Задания

1.Используя двунаправленный список, написать и протестировать функции, реализующие отдельные действия при игре в “новое домино”, в котором кроме традиционных правил игрок может на каждом ходу заменить любую конечную кость на свою. Необходимы следующие функции: а)проверить, можно ли сделать ход; б)сделать ход; в)проверить, можно ли сделать замену, г)заменить кость; д)определить, закончена ли игра.

2.Написать программу сложения двух длинных целых чисел, представленных в виде строк, используя круговой список.

3.Автоматизированная информационная система на железнодорожном вокзале содержит сведения об отправлении поездов дальнего следования. Для каждого поезда указывается: номер поезда, станция назначения, время отправления. Данные в информационной системе организованы в виде линейного списка. Составить программу, которая: 1)обеспечивает первоначальный ввод данных в информационную систему и формирование линейного списка; 2)производит вывод всего списка; 3)вводит номер поезда и выводит все данные об этом поезде; 4)вводит название станции назначения и выводит данные обо всех поездах, следующих до этой станции. Программа должна обеспечивать диалог с помощью меню и контроль ошибок при вводе.

4.На междугородной телефонной станции картотека абонентов, содержащая сведения о телефонах и их владельцах, организована как линейный список. Составить программу, которая: 1)обеспечивает начальное формирование картотеки в виде линейного списка; 2)производит вывод всей картотеки; 3)вводит номер телефона и время разговора; 4)выводит извещение на оплату телефонного разговора. Программа должна обеспечивать диалог с помощью меню и контроль ошибок при вводе.

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

6.Составить программу, которая содержит текущую информацию о книгах в библиотеке. Сведения о книгах содержат: номер УДК, фамилию и инициалы автора, название, год издания, количество экземпляров данной книги в библиотеке. Программа должна обеспечивать: а)начальное формирование данных о всех книгах в библиотеке в виде списка; б)добавление данных о книгах, вновь поступающих в библиотеку; в)удаление данных о списываемых книгах; г)по запросу выдавать сведения о наличии книг в библиотеке, упорядоченные по годам издания.

7.Используя представление многочлена в виде списка в порядке убывания степеней x, по многочлену S(x) построить его производную - многочлен P(x).

8.Картотека в бюро обмена квартир организована как линейный список. Сведения о каждой квартире содержат: количество комнат, этаж, площадь, адрес. Составить программу, которая обеспечивает: а)начальное формирование картотеки; б)ввод заявки на обмен; в)поиск в картотеке подходящего варианта: при равенстве количества комнат и этажа и различии площадей в пределах 10% выводится соответствующая карточка и удаляется из списка, в противном случае поступившая заявка включается в список; г)вывод всего списка. Программа должна обеспечивать диалог с помощью меню и контроль ошибок при вводе.

9.Перемножить два многочлена, задав их в виде списков.

10.Анкета для опроса населения содержит две группы вопросов. Первая группа содержит сведения о респонденте: возраст, пол, образование (начальное, среднее, высшее). Вторая группа содержит собственно вопрос анкеты, ответ на который либо ДА, либо НЕТ. Составить программу, которая: 1)обеспечивает начальный ввод анкет и формирует из них линейный список; 2)на основе анализа анкет выдает ответы на следующие вопросы: а)сколько мужчин старше 40 лет, имеющих высшее образование, ответили ДА на вопрос анкеты; б)сколько женщин моложе 30 лет, имеющих среднее образование, ответили НЕТ на вопрос анкеты; в)сколько мужчин моложе 25 лет, имеющих начальное образование, ответили ДА на вопрос анкеты; 3)производит вывод всех анкет и ответов на вопросы. Программа должна обеспечивать диалог с помощью меню и контроль ошибок при вводе.

11.Представить в виде списка распорядок рабочего дня. Написать функции для справок, изменения распорядка.

12.Написать и протестировать функции для включения, исключения и поиска элемента кругового списка для: а)списка без заголовка; б)списка с заголовком (заголовок может содержать некоторую информацию о списке, например, число элементов списка).

13.Написать программу, которая а)сцепляет два списка данных символьного типа; б)объединяет упорядоченные списки данных целого типа в единый упорядоченный список.

14.Написать программу, которая помещает заданное количество случайных целых чисел в диапазоне от 0 до 100 в упорядоченный список. Вычислить сумму элементов и среднее арифметическое.

15.Написать программу, которая создает связный список из заданного количества символов, а затем создаёт второй список - копию, но в обратной последовательности.

16.Написать программу, беспорядочно смешивающую буквы слова для создания слова-путаницы. Каждый символ в строке произвольно помещается либо в начало, либо в конец списка. Например, с вводом jumble последовательность случайных чисел 011001 создаёт lbjume.

17.Написать программу, которая содержит динамическую информацию о наличии автобусов в автобусном парке. Сведения о каждом автобусе содержат: номер автобуса, фамилию водителя, номер маршрута. Программа должна обеспечивать: а)начальное формирование данных о всех автобусах в парке в виде списка; б)при выезде каждого автобуса из парка вводится номер автобуса, и программа удаляет данные об этом автобусе из списка автобусов, находящихся в парке, и записывает эти данные в список автобусов, находящихся на маршруте; в)при въезде каждого автобуса в парк вводится номер автобуса, и программа удаляет данные об этом автобусе из списка автобусов, находящихся на маршруте, и записывает эти данные в список автобусов, находящихся в парке; г)по запросу выдаются сведения об автобусах, находящихся в парке, или об автобусах, находящихся на маршруте.

18.Составить программу, которая содержит текущую информацию о заявках на авиабилеты. Каждая заявка содержит: пункт назначения, номер рейса, фамилию и инициалы пассажира, желаемую дату вылета. Программа должна обеспечивать: а)хранение всех заявок в виде списка; б)добавление заявок в список; в)удаление заявок; г)вывод заявок по заданному номеру рейса и дате вылета; д)вывод всех заявок.

19.Составить программу, которая содержит текущую информацию о книгах в библиотеке. Сведения о книгах содержат: номер УДК, фамилию и инициалы автора, название, год издания, количество имеющихся экземпляров. Программа должна обеспечивать: а)начальное формирование данных о всех книгах в библиотеке в виде списка; б)при взятии каждой книги вводится номер УДК, и программа уменьшает значение количества книг на единицу или выдает сообщение о том, что требуемой книги в библиотеке нет или требуемая книга находится на руках; в)при возвращении каждой книги вводится номер УДК, и программа увеличивает значение количества книг на единицу; г)по запросу выдаются сведения о наличии книг в библиотеке.

20.Написать программу, которая содержит динамическую информацию о наличии автобусов в автобусном парке. Сведения о каждом автобусе содержат: номер автобуса, фамилию и инициалы водителя, номер маршрута, признак того, где находится автобус – на маршруте или а парке. Программа должна обеспечивать: а)начальное формирование данных о всех автобусах в виде списка; б)при выезде каждого автобуса из парка вводится номер автобуса, и программа устанавливает значение признака “автобус на маршруте”; в)при въезде каждого автобуса в парк вводится номер автобуса, и программа устанавливает значение признака “автобус в парке”; г)по запросу выдаются сведения об автобусах, находящихся в парке, или об автобусах, находящихся на маршруте.

21.Составить программу, моделирующую заполнение гибкого диска. Общий объём памяти на диске 1,44 Мбайта. Файлы имеют произвольную длину от 72 байт до 128 Кбайт. В процессе работы файлы либо записываются на диск, либо удаляются с него. В начале работы файлы записываются подряд друг за другом. После удаления файла на диске образуется свободный участок памяти, и вновь записываемый файл размещается на свободном участке, либо, если файл не вмещается в свободный участок, размещается после последнего записанного файла. В случае, когда файл превосходит длину самого большого свободного участка, выдается аварийное сообщение. Требование на запись или удаление файла задается в командной строке, которая содержит имя файла, его длину в байтах, признак записи или удаления. Программа должна выдавать по запросу сведения о занятых и свободных участках памяти на диске. Указание: следует создать список занятых участков и список свободных участков памяти на диске.

22.В файловой системе каталог файлов организован как линейный список. Для каждого файла в каталоге содержатся следующие сведения: имя файла, дата создания, количество обращений к файлу. Составить программу, которая обеспечивает: а)начальное формирование каталога файлов; б)вывод каталога файлов; в)удаление файлов, дата создания которых меньше заданной; г)выборку файла с наибольшим количеством обращений. Программа должна обеспечивать диалог с помощью меню и контроль ошибок при вводе.

23.Предметный указатель организован как линейный список. Каждая компонента указателя содержит слово и номера страниц, на которых это слово встречается. Количество номеров страниц, относящихся к одному слову, от одного до десяти. Составить программу, которая обеспечивает: а)начальное формирование предметного указателя; б)вывод предметного указателя; в)вывод номеров страниц для заданного слова. Программа должна обеспечивать диалог с помощью меню и контроль ошибок при вводе.

24.Текст помощи для некоторой программы организован как линейный список. Каждая компонента текста помощи содержит термин (слово) и текст, содержащий пояснения к этому термину. Количество строк текста, относящихся к одному термину, от одной до пяти. Составить программу, которая обеспечивает: а)начальное формирование текста помощи; б)вывод текста помощи; в)вывод поясняющего текста для заданного термина. Программа должна обеспечивать диалог с помощью меню и контроль ошибок при вводе.

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

26.По введенной безошибочной записи многочлена от x построить его представление в виде списка, элемент которого содержит поля: коэффициент при x, степень x, указатель на следующий элемент ( в последнем - NULL).

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

28.В целочисленной точке x вычислить значение многочлена S(x), представленного в виде списка в порядке убывания степеней x..

29.Распечатать многочлен, заданный в виде списка, в обычном виде (например, так: 52y^3-6y^2+y).

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

 


ЛАБОРАТОРНАЯ РАБОТА 8



<== предыдущая лекция | следующая лекция ==>
ОЧЕРЕДЬ ПРИОРИТЕТОВ | БИНАРНОЕ УПОРЯДОЧЕННОЕ ДЕРЕВО


Карта сайта Карта сайта укр


Уроки php mysql Программирование

Онлайн система счисления Калькулятор онлайн обычный Инженерный калькулятор онлайн Замена русских букв на английские для вебмастеров Замена русских букв на английские

Аппаратное и программное обеспечение Графика и компьютерная сфера Интегрированная геоинформационная система Интернет Компьютер Комплектующие компьютера Лекции Методы и средства измерений неэлектрических величин Обслуживание компьютерных и периферийных устройств Операционные системы Параллельное программирование Проектирование электронных средств Периферийные устройства Полезные ресурсы для программистов Программы для программистов Статьи для программистов Cтруктура и организация данных


 


Не нашли то, что искали? Google вам в помощь!

 
 

© life-prog.ru При использовании материалов прямая ссылка на сайт обязательна.

Генерация страницы за: 0.741 сек.