МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
ПВНЗ ЄВРОПЕЙСЬКИЙ УНІВЕРСИТЕТ
ЧЕРКАСЬКА ФІЛІЯ
Кафедра математичних ікомп’ютерних дисциплін
КУРСОВА РОБОТА
з дисципліни: “Об’єктно-орієнтована розробкапрограмних систем”
на тему: “Об’єктно-орієнтована програма обліку продуктовогомагазину”
Черкаси 2008
Вступ
Успішна розробкаі впровадження складних програмних систем — це щось більше, ніж простопрограмування. Існує багато прийомів традиційних програмних розробок,наприклад, перегляд, що застосовні і в об'єктно-орієнтованій технології. Устабільному стані об'єктно-орієнтовані проекти вимагають менших ресурсів, а методи,необхідні для управління цими ресурсами, декілька відрізняються відтрадиційних, тому в процесі об'єктно-орієнтованої розробки не можна проводитиінтеграцію всього відразу і за один раз; структурними одиницями управління длярелізів повинні бути категорії класів і підсистеми, а не окремі файли і класи.
До позитивнихякостей об'єктно-орієнтованих програм відносяться — графік числа виявленихпомилок за певний час і щільність помилок. Існує ряд позитивних характеристик,орієнтованих на класи. Об'єктно-орієнтована розробка вимагає іншогоінструментарію в порівнянні з традиційними методами. Перехід організації наоб'єктно-орієнтовані технології — це зміна світогляду, а не просто вивченнянової мови програмування.
Завданнямкурсової роботи є вивчення предметної області «Продуктового магазину» тапрограмна реалізація даної області за допомогою об’єктно-орієнтованого напрямкупрограмування.
Програмареалізована в середовищі об’єктно-орієнтованого програмування С++ Builder 6.0, на основі мови програмування С++. Це пов’язано з тим, що даний напрямпрограмування має ряд переваг, необхідних для ведення обліку меблевого складу.Одна з переваг пов’язана з використанням віртуальних функцій, завдяки якимможна заощадити на перевірці типів і опустити багато конструкцій, що здійснюютьуправління. Згідно досвіду, код об'єктно-орієнтованої програми зазвичайкоротше, ніж інших.
Метакурсової роботи – створення об’єктно-орієнтованої програми по веденню обліку продуктовогомагазину.
Об’єктомкурсової роботи є продуктовий магазин, де здійснюється роздрібна торгівляпродовольчих товарів, певної кількості та вартості.
Курсоваробота розділена на два розділи:
- в Розділі 1 проведенодослідження предметної області «Продуктового магазину» та визначено головнінапрямки і дані, що необхідно відобразити в програмі по веденню обліку продуктовогомагазину.
- в Розділі 2 детальнорозкрито поняттямоделі в об’єктно-орієнтованих мовах програмування, реалізована побудовапрограмної моделі «Обліку продуктового магазину» та надано обґрунтування виборумови програмування для створення програми.
1. Аналізпредметної області
Продуктовиймагазин є кінцевим пунктом збуту товару. Кожний продуктовий магазин має свій асортименттовару для роздрібної торгівлі. В магазині присутні продукти загалом різноговиду. До основних належать:
· молочніпродукти (молоко, сметана, сир, ряжанка, кефір);
· хлібобулочні(хліб, батон, булочки);
· горілчані(горілка, вино, коняк, портвейн, пиво, слабоалкогольні напої);
· тютюновівироби;
· кондитерськівироби (печиво, торти, цукерки, то що);
· консервнівироби;
· продуктишвидкого приготування;
· інші продуктиширокого вжитку.
Продукт циркулює наступнимчином:
1. приход товару вмагазин – продукти поступають на склад за накладними по приходу;
2. продаж змагазину – відбувається за видатковими чеками.
Продукти зберігаютьсядо їх продажу, чи списання (останнє трапляється відносно періодично, тому щозакінчився термін вжитку товару).
Облік продуктовогомагазину передбачає наступні етапи:
· додаванняданих про товар в магазині;
· видаленняданих з магазину;
· зберіганняданих;
· сортуванняданих;
· переглядданих;
· редагуванняданих.
Кожен з цихетапів є досить важливим і необхідним для ведення обліку. Також актуальним булоб передбачати при внесенні даних реєстрацію дати приходу товару на магазин:день, місяць, рік. Для реалізації задуманого необхідним є створення програми,що буде в повному обсязі забезпечувати виконання цих етапів та відображатинаступну інформацію:
· видпродукції;
· назва товару;
· ціна (заодиницю товару);
· виробник;
· число,місяць, рік приходу на склад;
· сума всьоготовару в магазині.
2. Модель воб’єктно-орієнтованих мовах програмування
Об'єктно-орієнтованатехнологія ґрунтується на так званій об'єктній моделі. Основними її принципамиє:
· абстрагування;
· інкапсуляція;
· модульність;
· ієрархічність;
· типізація;
· паралелізмі збереження.
Кожен з цихпринципів сам по собі не новий, але в об'єктній моделі вони вперше застосованів сукупності.
Принципиоб'єктно-орієнтованого програмування створені, щоб допомогти розробникамзастосовувати могутні виразні засоби об'єктного і об'єктно-орієнтованогопрограмування, що використовує як блоки класи і об'єкти.
Оскількипобудова моделей украй важлива при проектуванні складних систем, об'єктно-орієнтованепроектування пропонує багатий вибір моделей. Об'єктно-орієнтовані моделіпроектування відображають ієрархію і класів, і об'єктів системи. Ці моделіпокривають весь спектр найважливіших конструкторських рішень, які необхіднорозглядати при розробці складної системи, і таким чином надихають на створенняпроектів, що володіють всіма п'ятьма атрибутами добре організованих складнихсистем.
Об'єктнамодель принципово відрізняється від моделей, які пов'язані з більш традиційнимиметодами структурного аналізу, проектування і програмування. Це не означає, щооб'єктна модель вимагає відмови від всіх раніше знайдених і випробуваних часомметодів і прийомів. Швидше, вона вносить деякі нові елементи, які додаються допопереднього досвіду. Об'єктний підхід забезпечує ряд істотних переваг, якііншими моделями не передбачалися. Найбільш важливо, що об'єктний підхіддозволяє створювати системи, які задовольняють п'яти ознакам добреструктурованих складних систем. Згідно досвіду, є ще п'ять переваг, які даєоб'єктна модель.
По-перше,об'єктна модель дозволяє повною мірою використовувати виразні можливостіоб'єктних і об'єктно-орієнтованих мов програмування. Істотно підвищитиефективність і якість коду можна просто за рахунок використання C++ як «покращуваного C» зелементами абстракції даних. Проте набагато значнішим досягненням є введенняієрархії класів в процесі проектування.
По-друге,використання об'єктного підходу істотно підвищує рівень уніфікації розробки іпридатність для повторного використання не тільки програм, але і проектів, щоврешті-решт веде до створення середовища розробки. Об'єктно-орієнтовані системичасто виходять компактнішими, ніж їх не об'єктно-орієнтовані еквіваленти. А цеозначає не тільки зменшення об'єму коду програм, але і здешевлення проекту зарахунок використання попередніх розробок, що дає виграш у вартості і часі.
По-третє,використання об'єктної моделі приводить до побудови систем на основі стабільнихпроміжних описів, що спрощує процес внесення змін. Це дає системі можливістьрозвиватися поступово і не приводить до повної її переробки навіть у разіістотних змін початкових вимог.
По-четверте,об'єктна модель зменшує ризик розробки складних систем, перш за все тому, щопроцес інтеграції розтягується на весь час розробки, а не перетворюється наодноразову подію. Об'єктний підхід складається з ряду добре продуманих етапівпроектування, що також зменшує ступінь риску і підвищує упевненість вправильності схвалюваних рішень
Кожна модель при реалізації використовує наступні методи розподілу пам’яті:
- за допомогою визначення змінних стандартних типів (цілі, дійсні та ін);
- за допомогою визначення змінних, визначених користувачем;
- за допомогою списків, стеків, черг, масивів, дерев тощо.
Існують ще декілька способів, наприклад, створення нового екземпляра форми чи елемента управління, але вони не дають великих можливостей при створенні складних структур даних.
Використовуючи ці методи, можна легко будувати статичні структури даних, такі як великі масиви визначених типів. Проте перерозподіл даних може бути досить складним. Наприклад, для того, щоб перемістити елемент з одного кінця масиву на інший, потрібно пере впорядкувати весь масив, зсунувши всі елементи на одну позицію, аж потім можна помістити елемент на нове місце. Крім того, масиви мають фіксований розмір, тому коли наперед не відомо про розмір створюваної програми, їх використання не доречне.
Динамічні структури даних дозволяють швидко і легко виконати такого роду зміни. Всього за кілька кроків можливо перемістити будь-який елемент в структурі даних в інше місце. До таких структур даних належать списки.
Найпростіша форма писку — це група об’єктів, до яких можна звернутись.
Зв’язане зберігання лінійного списку являється списком з двома зв’язками або двухзв’язним списком, якщо кожен елемент, що зберігається має два компонента вказівника (на попередній і на наступний елементи лінійного списку). Графічне зображення двухзв’язного списку представлене на мал.1.
/>
Мал. 1 — Схемазберігання двухзв’язного списку
В залежності відметоду доступу до елементів лінійного списку виділяють різновиди лінійнихсписків — стеки, черги, двохсторонні черги.
Стек являє собоюкінцеву послідовність деяких однотипних елементів — скалярних змінних, масивів,структур або об’єднань, серед яких можуть бути й однакові. Він відноситься додинамічних структур даних, його кількість елементів наперед не вказується і впроцесі роботи, як правило змінюється.
Допустимимиопераціями над стеком являються:
- перевірка стека напорожність;
- додавання нового елемента вкінець стека;
- видалення останнього елементазі стека;
- доступ до останньогоелемента.
Таким чином,операції додавання і видалення елемента виконується тільки в кінці списку.
Черга ж являєсобою лінійний список, у якого елементи додаються і видаляються з початкусписку (як черга в магазині).
Двохстороннячерга — лінійний список, у якого операції додавання і видалення елементів тадоступ до них можливий як на початку так і в кінці списку.
Використовуючивказівники можливо побудувати багато інших корисних різновидів зв’язнихструктур даних, таких як дерева, графи, мережі.
В реалізованій програмі використовуються списки, а точніше — двухзв’язні списки з фіктивним елементом. Їх використання є доцільним, тому що створювана програма не має визначеного розміру, що, наприклад, виключає використання в програмі масивів.
За допомогою списків в програмі проводиться сортування, додавання, видалення та деякі інші операції, що так необхідні при веденні обліку меблевого складу.
2.1 Програмнамодель
Програма,створена на мові програмування С++, в середовищі програмування Borland С++ Builder 6.0. При розробці моделі програми було створено наступні класи:
1. Table
2. Data
3. Record
4. Iterator
5. Number
6. MyTable
7. MyData
8. Main
Кожин з цих класів має свою будову. Наприклад, будовакласу Table представлена на мал.2.
/>
Мал. 2 — Клас Table
Крім цього, коженклас так чи інакше взаємодіє з іншими класами. Зв’язок класів представлений на мал.3 у вигляді діаграм Буча.
/>
Мал. 3
З діаграми видно,що кілька класів використовуються одним класом. Наприклад класи Data, Record, Iterator використовуються класом Table, і крім того, використовуються міжсобою. Стрілочки на діаграмі означають відношення “наслідування” класів, а зв’язок через рисочку, щовиходить з кружечка, означає використання одного класу іншим.
Клас зазвичайпредставляють аморфним об'єктом, на зразок хмарки. Хмарку було взято зматеріалів корпорації Intel, що документувала своюоригінальну об'єктно-орієнтовану архітектуру iAPX432. Форма цього образу натякає на розпливчатість межабстракції, від яких не очікується гладкості і простоти. Пунктирний контурсимволізує те, що клієнти оперують зазвичай з екземплярами цього класу, а не зсамим класом.
Крімкласів, програма складається з об’єктів, а разом вони утворюють модулі. Діаграмамодулів показує розподіл класів і об'єктів по модулях у фізичному проектуваннісистеми.
Кожнаокрема діаграма модулів представляє деякий ракурс структури модулів системи.
Діаграмамодулів використовується при розробці для того, щоб показати фізичне ділення архітектурипрограми по шарах і розділах.
Кожен модуль програмипо обліку товарів магазину має ім'я — це ім'я відповідного фізичного файлу вкаталозі проекту (Main.h і Main.cpp, Data.h i Data.cpp, Number.h i Number.cpp, Table.h та ін.).
Кожне ім'я файлу унікальнев програмі. Сам модуль містить або опис, або визначення класів і об'єктів, атакож інші конструкції мови. «Розкривши» значок будь-якого модуля здіаграми, потрапляємо всередину відповідного файлу. Розглядаючи структурупрограми з іншого боку, маємо наступну будову: програма містить в собі три форми.
Перша формапрограми (MаіnForm) — це форма, що відкривається зразуж при запуску програми – головна, відображає всі дані про продуктовий магазин. Крім відомостейпро товар вона також має в розпорядженні кнопки:
· Додати
· Видалити
· Очистити
· Змінити
· Сортувати
· Зберегти
· Відкрити
· Вихід
Код обробникаподій кожної з них наведений в додатку, в лістингу програми.
2.2 Вибірзасобів реалізації програми
Програмареалізована в середовищі об’єктно-орієнтованого програмування Borland С++ Builder 6.0, на основі мови програмування С++. Це пов’язано з тим, що даний напрямпрограмування має ряд переваг, необхідних для ведення обліку меблевого складу.
Відомодекілька версій C++. У версії 1.0 реалізованіосновні механізми об'єктно-орієнтованого програмування, такі як одиночненаслідування і поліморфізм, перевірка типів і перевантаження функцій. Уствореній в 1989 році версії 2.0 знайшли віддзеркалення багато додатковихвластивостей (наприклад, множинне спадкоємство), що виникли на базі широкогодосвіду застосування мови численним співтовариством користувачів. У версії 3.0(1990) з'явилися шаблони (класи, що параметризуються) і обробка виключень.Комітет ANSI з C++ (X3J16) недавно схваливпропозиції по введенню просторів імен (що відповідає нашому позначеннюкатегорій класів) і перевірки типів під час виконання.
Основніхарактеристики C++ :
· абстракції:змінні екземпляра, методи екземпляра, змінні класу, методи класу;
· інкапсуляція:змінних, методів;
· модульність:різновиди модулів;
· ієрархії:наслідування, шаблони, мета класи;
· типізація:сильна типізація, поліморфізм;
· паралельність:багатозадачність;
· збереженість:довго живучі об’єкти.
Абстрагуванняє одним з основних методів, використовуваних для вирішення складних завдань.Абстракція виділяє істотні характеристики деякого об'єкту, що відрізняють йоговід всіх інших видів об'єктів і, таким чином, чітко визначає його концептуальнімежі з погляду спостерігача. Абстрагування концентрує увагу на зовнішніхособливостях об'єкту і дозволяє відокремити найістотніші особливості поведінкивід неістотних. Вибір правильного набору абстракцій для заданої наочної областіє головним завданням об'єктно-орієнтованого проектування.
Абстракціяі інкапсуляція доповнюють один одного: абстрагування направлене на спостережувануповедінку об'єкту, а інкапсуляція займається внутрішнім устроєм. Найчастішеінкапсуляція виконується за допомогою утаєння інформації, тобто маскуваннямвсіх внутрішніх деталей, що не впливають на зовнішню поведінку. Зазвичайховаються і внутрішня структура об'єкту і реалізація його методів.Інкапсуляція, таким чином, визначає чіткі межі між різними абстракціями.
Інкапсуляціявиступає як процес відділення один від одного елементів об'єкту, що визначаютьйого структуру і поведінку; служить для того, щоб ізолювати зобов'язанняабстракції від їх реалізації.
Розділенняпрограми на модулі до деякої міри дозволяє зменшити її складність. Правильнерозділення програми на модулі є майже таким же складним завданням, як вибірправильного набору абстракцій. Модулі виконують роль фізичних контейнерів, вякі поміщаються визначення класів і об'єктів при логічному проектуваннісистеми. Для невеликих завдань допустимий опис всіх класів і об'єктів в одномумодулі. Проте для більшості програм (окрім найтривіальніших) кращим рішеннямбуде згрупувати в окремий модуль логічно зв'язані класи і об'єкти, залишившивідкритим ті елементи, які абсолютно необхідно бачити іншим модулям.
Ієрархіявиступає, як процес впорядкування абстракцій, розташування їх по рівнях.Основними видами ієрархічних структур стосовно складних систем є структуракласів (ієрархія «is-a») і структура об'єктів(ієрархія «part of»). Прикладом ієрархії є одиночне наслідування. Іншими словами, наслідуваннястворює таку ієрархію абстракцій, в якій підкласи успадковують будову відодного або декількох батьківських класів.
Типізаціяявляє собою спосіб захиститися від використання об'єктів одного класу замістьіншого, або принаймні управляти таким використанням. Типізація примушуєвиражати абстракції так, щоб мова програмування, використовувана в реалізації,підтримувала дотримання ухвалених проектних рішень. Ідея узгодження типівзаймає в понятті типізації центральне місце.
В тойчас, як об'єктно-орієнтоване програмування засноване на абстракції,інкапсуляції і наслідуванні, паралелізм головну увагу приділяє абстрагуванню ісинхронізації процесів.
Дляоб'єктно-орієнтованої розробки виділяють сім різних видів інструментів.
Першийінструмент — система з графічним інтерфейсом, що підтримує об'єктно-орієнтованусистему позначень. Такий інструмент може бути використаний при аналізі, щобзафіксувати семантику сценаріїв, на ранніх стадіях розробки, щоб передатистратегічні і тактичні рішення, прийняті при проектуванні, а також длякоординування дій проектувальників. Подібний інструмент буде корисний впродовжвсього життєвого циклу і при супроводі системи.
Другий,важливий для об'єктно-орієнтованої розробки інструмент, — браузер, який показує структуру класів іархітектуру модулів системи. Ієрархія класів може зробитися настільки складною,що важко навіть відшукати всі абстракції, які були введені при проектуванні.При вивченні фрагмента програми розробникові може знадобитися подивитисявизначення класу деякого об'єкту. Знайшовши цей клас, йому ймовірно доведетьсязаглянути в опис якого-небудь з його суперкласів. З цієї причини браузервиявляється дуже важливим інструментом об'єктно-орієнтованого аналізу іпроектування.
Третійвид інструментів, який дуже важливий — інкрементний компілятор. Методеволюційної розробки, який застосовується в об'єктно-орієнтованомупрограмуванні, потребує компілятора, який міг би компілювати окремі оголошенняі операторів. Для швидкої відладки методи і визначення полів повиннікомпілюватися інкрементно.
Укатегорію налагоджувальних засобів включається і такі інструменти, як стресовітестери, що випробовують програми в критичних умовах обмеженості ресурсів, іінструменти для аналізу пам'яті, що розпізнають порушення доступу до пам'яті(запис в недозволені ділянки пам'яті, читання з неініціалізованих ділянок,читання або запис за межами масиву).
Длявеликих проектів потрібні інструменти управління конфігурацією і контролюверсій. Для управління конфігурацією кращими одиницями є категорії класів іпідсистеми.
Іншийінструмент, який є також важливим для об'єктно-орієнтованої розробки, — цебібліотекар класів. Бібліотека в С++ швидко розростається до таких розмірів, щорозробники не можуть відшукати клас, що знадобився. Одна з причин швидкогозростання бібліотеки полягає в тому, що клас може мати декілька реалізацій зрізними тимчасовими і просторовими семантиками.
Щеодин тип інструменту — генератор графічного інтерфейсу користувача. Для систем,в яких великий об'єм взаємодії з користувачем, краще мати спеціальнийінструмент для інтерактивного створення діалогів і вікон, чим програмувати всез нуля. Код, що з генерований такою системою, може бути потім пов'язаний зрештою об'єктно-орієнтованої системи і, якщо необхідно, вручну відкоригований.
Вибірданої мови програмування зумовлений через її переваги:
· великаконкурентоспроможність завдяки передбаченості, скороченню часу на розробку івеликої гнучкості продукту;
· завдання,що розробляються, можуть бути настільки складними, що не залишаєтьсяальтернативних рішень.
Вивченнячисленних випадків з практики підкріплює ці висновки; особливо часто указуєтьсяна те, що об'єктний підхід може скоротити час розробки і розмір коду.
Дивлячисьна тіньову сторону об'єктно-орієнтованої технології (недоліки), потрібнорозглядати два питання: продуктивність і початкові витрати. В порівнянні зпроцедурними мовами, об'єктно-орієнтовані мови ясно вносять додаткові накладнівитрати на пересилку повідомлення від одного об'єкту іншому. У мовах, що строготипізуються, компілятор часто може визначати, які виклики можуть бути зв'язаністатично і згенерувати для них виклик процедури замість динамічного пошуку.
Іншапричина зниження продуктивності криється не стільки в природіоб'єктно-орієнтованих мов, скільки в способі їх використання в процесіоб'єктно-орієнтованої розробки. Об'єктно-орієнтована технологія породжує багатошаровісистеми абстракцій. Один із наслідків цього розшарування в тому, що кожен методвиявляється дуже маленьким, оскільки він будується на методах нижнього рівня.
Іншийнаслідок розшарування: іноді методи служать лише для того, щоб дістати доступдо захищених атрибутів об'єкту. В результаті відбуваються дуже багато викликів.З позитивного боку таке шарування сприяє розумінню системи; до деяких складнихсистем неможливо навіть підступитися, якщо не почати з проектування шарів.
Висновки
Впроцесі роботи було створено програму — «Облік продуктового магазину». Програмареалізована в середовищі об’єктно-орієнтованого програмування Borland С++ Builder 6.0, на основі мови програмування С++.
Булодосліджено предметну область — «Продуктовий магазин», що внесло багато ясностідля розробки програми.
Детальнийрозгляд та створення програмної моделі дало можливість більш детальноспроектувати створену програму, розбивши її на модулі так, що прискорилошвидкість її створення та внесло ясність на деякі використовувані аспектипрограми.
Створенапрограма «Облік продуктового магазину» в процесі доопрацювання може бутивикористана за основу для створення більш складної та великої бази даних пороботі в даній предметній області.
Списоквикористаних джерел
1. Гради БучОбъектно-ориентированный анализ и проектированиес примерами приложений на С++.Второе издание Rational Санта-Клара, Калифорния, перевод с английского под редакцией И. Романовского и Ф. Андреева.
2. ПавловскаяТ.А. С++. Объектно-ориентированноепрограммирование: практикум. СПб:Питер, 2005.
3. Б.С.Хусаинов. Структуры иалгоритмы обработки данных. – Примеры на языке Си: Учеб. Пособие, 2004.
4. Кнут,Дональд, Эрвин. Искуство програмирования в3-х т. М.: Вильянс, 2003.
5. Катренко А.В. Системний аналізоб’єктів та процесів комп’ютеризації. Львів: Новий світ-2000, 2007.
6. Б.С. Хусаинов. Структуры и алгоритмы обработкиданных. – Примеры на языке Си: Учеб. Пособие. Финансы и статистика, 2004.
7. Гайдаржи В.І. Основи проектуваннята використання баз даних. К.: Політехніка, ТОВ фірма Періодика, 2004.
8. Малевич Б.Я. Теория алгоритмов.М.: Машиностроение, 2004.
9. Прокудин Г.С. Основыпрограммирования и алгоритмические язики. К.: Изд-во Европейськогоуниверситета, 2003.
10. Озеров В. Советы по Delphi.Советы програмистов. СПб.: Символ-плюс,2002.
ДодатокА
Результатроботи програми «Облік продуктового магазину»
/>
Рис. 1- Форма обліку продуктового магазину
ДодатокБ
Лістингпрограми
1. Table.cpp
#include
#pragmahdrstop
#include«Table.h»
Table::Table()
{
list = newRecord;
list->next= list->prev = list;
list->id =0;
ID = 0;
}
Table::~Table()
{
Record *t,*q;
for(t=list->next;t!=list;t=q)
{
q =t->next;
deletet->data;
delete t;
}
delete list;
}
Table: Iterator Table: record()
{
Record *r =new Record;
ID++;
r->id = ID;
r->data =create();
r->next =list->next;
r->prev =list;
list->next->prev= r;
list->next= r;
returnIterator(r,this);
}
voidTable::clear()
{
Record *t,*q;
for(t=list->next;t!=list;t=q)
{
q =t->next;
deletet->data;
delete t;
}
list->next= list->prev = list;
ID = 0;
}
voidTable::save(FILE *f)
{
Fprintf (f,"%d\n", ID);
for(Record*t=list->next;t!=list;t=t->next)
{
fprintf(f,"%7d",t->id);
t->data->save(f);
fprintf(f,"\n");
}
Fprintf (f,«END»);
}
voidTable::zvit(FILE *f)
{
fprintf(f,«ЦінаНазва Виробник Вид Дата\n»);
fprintf(f,"-----------------------------------------------\n");
for(Record*t=list->next;t!=list;t=t->next)
{
t->data->zvit(f);
}
}
voidTable::load(FILE *f)
{
int id;
Record *t;
int rez =fscanf(f,"%d\n",&ID);
if((rez!=EOF)&&(rez!=0))
{
while(true)
{
t = newRecord;
rez =fscanf(f,"%d",&t->id);
if((rez==EOF)||(rez==0))
{
delete t;
break;
}
t->data =create();
rez =t->data->load(f);
if((rez==EOF)||(rez==0))
{
delete t;
break;
}
t->next =list;
t->prev =list->prev;
list->prev->next= t;
list->prev= t;
}
}
}
voidTable::Iterator::remove()
{
r->next->prev= r->prev;
r->prev->next= r->next;
deleter->data;
delete r;
}
voidTable::Iterator::operator >>(Iterator &p)
{
if((t==p.t)&&(p.r!=r)&&(p.r!=r->next)&&(p.r!=t->list))
{
p.r->next->prev= p.r->prev;
p.r->prev->next= p.r->next;
p.r->next =r->next;
p.r->prev =r;
r->next->prev= p.r;
r->next =p.r;
}
}
voidTable::Iterator::operator
{
if((t==p.t)&&(p.r!=r)&&(p.r!=r->prev)&&(p.r!=t->list))
{
p.r->next->prev= p.r->prev;
p.r->prev->next= p.r->next;
p.r->next =r;
p.r->prev =r->prev;
r->prev->next= p.r;
r->prev =p.r;
}
}
2. Table.h
#ifndef TableH
#define TableH
#include
#include
#include«Date.h»
#include«My_date.h»
class Table
{
public:
class Data
{
public:virtual ~Data(){}
virtual voidsave(FILE *f){}
virtual voidzvit(FILE *f) {}
virtual intload(FILE *f){return 1;}
};
private:
struct Record
{
int id;
Data *data;
Record *next;
Record *prev;
} *list;
int ID;
public:
classIterator;
friend classIterator;
class Iterator
{
friend classTable;
Record *r;
Table *t;
protected:
Iterator(Record*R,Table *T):r(R),t(T){}
Data* data(){return r->data;}
Iteratorthe_next() {return Iterator(r->next,t);}
Iteratorthe_prev() {return Iterator(r->prev,t);}
public:Iterator(){}
int id(){returnr->id;}// повертає номер запису в таблиці
void operator++() {r = r->next;}// переміщує ітератор на наступнийзапис
void operator--() {r = r->prev;}// переміщує ітератор на попереднійзапис
bool operator==(constIterator &p){return r==p.r;}// порівнює з іншим ітератором
bool operator!=(constIterator &p){return r!=p.r;}// порівнює з іншим ітератором
bool valid(){return r!=t->list;}// true — вказує на дійсний елемент;false — вказує нанульовий елемент
void operator>>(Iterator&p);// перемістити p після даного ітератора
void operator
void remove();// видалити запис з таблиці
};
protected:
Iteratorthe_first() {return Iterator(list->next,this);}
Iteratorthe_last() {return Iterator(list->prev,this);}
Iteratorrecord();
virtual Data*create(){return new Data;};
public:Table();
virtual~Table();
voidclear();// очистити таблицю
void save(FILE*f);// зберегти таблицю
void zvit(FILE*f);
void load(FILE*f);// завантажити таблицю
};
template class MyTable: public Table
{
public:
class Iterator: public Table::Iterator
{
friend classMyTable;
Iterator(constTable::Iterator &p):Table::Iterator(p){}
public:Iterator(){}
MyData&operator*() {return *(MyData*)data();}// доступ до полів MyData
MyData*operator->() {return (MyData*)data();}// доступ до полів MyData
Iteratornext() {return Iterator(the_next());}// повертає ітератор на наступний елемент
Iteratorprev() {return Iterator(the_prev());}// повертає ітератор на попередній елемент
};
protected:
virtual Data*create(){return new MyData;}
public:Iterator record() {return Iterator(Table::record());}// створює новий запис іповертає ітератор на нього
Iteratorfirst() {return Iterator(the_first());}// повертає ітератор на перший запис втаблиці
Iteratorlast() {return Iterator(the_last());}// повертає ітератор на останній запис втаблиці
};
3. Number.cpp
#include
#pragmahdrstop
#include«Number.h»
voidNumber::save(FILE *f)
{char s[1000];
char s1[1000];
char s2[1000];
sprintf(s,"%s",str.c_str());
sprintf(s1,"%s",str1.c_str());
sprintf(s2,"%s",str2.c_str());
for(inti=0;s[i];i++) if(s[i]==' ') s[i]='_';
fprintf(f,"%d%s %s %s %d %d %d ",d,s,s1,s2,day,month,year);
}
voidNumber::zvit(FILE *f)
{
char s[1000];
char s1[1000];
char s2[1000];
sprintf(s,"%s",str.c_str());
sprintf(s1,"%s",str1.c_str());
sprintf(s2,"%s",str2.c_str());
fprintf(f,"%5d%10s %10s %10s %2d %2d %4d ",d,s,s1,s2,day,month,year);
fprintf(f,"\n");
}
intNumber::load(FILE *f)
{ chars[1000];
char s1[1000];
char s2[1000];
int rez =fscanf(f,"%d %s %s %s %d %d%d",&d,s,s1,s2,&day,&month,&year);
if(rez==7)
{ for(inti=0;s[i];i++) if(s[i]=='_') s[i]=' ';
for(inti=0;s1[i];i++) if(s1[i]=='_') s1[i]=' ';
for(inti=0;s2[i];i++) if(s2[i]=='_') s2[i]=' ';
str =AnsiString(s);
str1 =AnsiString(s1);
str2 =AnsiString(s2);
}
return rez;
}
4. Number.h
#ifndefNumberH
#defineNumberH
#include«Table.h»
#include«Date.h»
#include«My_date.h»
class Number:public Table::Data
{
public: int d;
int day; // число випуска
int year; // год випуска
int month; // месяц випуска
AnsiString str; // название мебели
AnsiString str1; // производитель
AnsiStringstr2; // вид мебели
void save(FILE*f);
void zvit(FILE*f);
int load(FILE*f);// 0 — помилка завантаження; EOF — кінець файла; >0 — завантаженняуспішне
};
5. Date.cpp
#include
#pragmahdrstop
#include«Date.h»
boolDate::load(int d,int m,int y)
{ if(y>=1900)
{ switch(m)
{
case 1://січень 31 день
case 3:// березень 31 день
case 5:// травень 31 день
case 7:// липень 31 день
case 8:// серпень 31 день
case 10:// жовтень 31 день
case 12:// грудень 31 день
if((d31))return false;
break;
case 2://лютий 28-29 день
if(y%4)
{
if((d29))return false;
}
else
{
if((d28))return false;
}
break;
case 4:// квітень 30 день
case 6:// червень 30 день
case 9:// вересень 30 день
case 11:// листопад 30 день
if((d30))return false;
break;
default:return false;
}
Day = d;
Month = m;
Year = y;
X = d + m*100 +year*10000;
Name =StrToInt(d)+"."+StrToInt(m)+"."+StrToInt(y);
}
else returnfalse;
}
boolDate::load(const AnsiString &s)
{
int x =s.Pos(".");
if(x)
{
AnsiString str= s.SubString(1,x-1);
int d =StrToInt(str);
str =s.SubString(x+1,s.Lenth-x);
int y =str.Pos(".");
if(y)
{
str =s.SubString(x+1,y+x-1);
int m =StrToInt(str);
str =s.SubString(y+x+1,s.Lenth-x-y);
int y =StrToInt(str);
returnload(d,m,y);
}
else returnfalse;
}
else returnfalse;
}
6. Date.h
#ifndef DateH
#define DateH
class Date
{ int Day;
int Month;
int Year;
long X;
AnsiStringName;
public: boolload(int d,int m,int y);
boolload(const AnsiString &s);
intday(){return Day;}
intmonth(){return Month;}
intyear(){return Year;}
constchar& str(){return Str.c_str();}
constDate& operator=(const Date &D){Day = D.Day; Month = D.Month; Year =D.Year;}
booloperator>(const Date &D){return X>D.X;}
booloperator>=(const Date &D){return X>=D.X;}
booloperator
booloperator
booloperator==(const Date &D){return X==D.X;}
booloperator!=(const Date &D){return X==D.X;}
};
7. Main.cpp
#include
#pragmahdrstop
#include«Main.h»
#include«My_date.h»
#include«Date.h»
#pragmapackage(smart_init)
#pragmaresource "*.dfm"
TMainForm*MainForm;
__fastcallTMainForm::TMainForm(TComponent* Owner)
: TForm(Owner)
{
}
//------------------------------------------------------------------------void__fastcall TMainForm::Add(TObject *Sender)
{
Ptr p =list.record();
p->d =StrToInt(NewInt->Text);
p->day =StrToInt(Day->Text);
p->year =StrToInt(Year->Text);
p->month =StrToInt(Month->Text);
//p->x =StrToFloat(NewDouble->Text);
p->str =String->Text;
p->str1 =FirmaString->Text;
p->str2 =WidString->Text;
redraw();
}
voidTMainForm::redraw()
{ List->Clear();
StrList->Clear();
for(Ptr p =list.first();p.valid();++p)
{
List->Items->Add(IntToStr(p->d));
StrList->Items->Add(p->str);
}
}
//------------------------------------------------------------------------void__fastcall TMainForm::Del(TObject *Sender)
{ int n =List->ItemIndex;
int i;
Ptr p;
for(i=0,p=list.first();p.valid()&&(i
if((i==n)&&p.valid())
{
p.remove();
redraw();
}
}
//------------------------------------------------------------------------void__fastcall TMainForm::Find(TObject *Sender)
{ int x =StrToInt(NewInt->Text);
Ptr p;
int i;
for(i=0,p=list.first();p.valid()&&(p->d!=x);++p,++i);
if(p.valid())
{ List->ItemIndex= i;
StrList->ItemIndex= i;
NewInt->Text= IntToStr(p->d);
Day->Text =IntToStr(p->day);
Year->Text= IntToStr(p->year);
Month->Text= IntToStr(p->month);
//NewDouble->Text= FloatToStr(p->x);
String->Text= p->str;
FirmaString->Text= p->str1;
WidString->Text= p->str2;
}
elseList->ItemIndex = -1;
}
//------------------------------------------------------------------------
void__fastcall TMainForm::Sort(TObject *Sender)
{
Ptr t,p,q;
for(t=list.first().next();t.valid();t=q)
{
q = t.next();
for(p=t.prev();p.valid()&&(p->d>t->d);--p);
p>>t;
}
redraw();
}
//------------------------------------------------------------------------
void__fastcall TMainForm::Save(TObject *Sender)
{
FILE *f;
if(SaveDialog->Execute())
{
f =fopen(SaveDialog->FileName.c_str(),«w»);
if(f!=NULL)
{
list.save(f);
fclose(f);
}
}
}
//------------------------------------------------------------------------
void__fastcall TMainForm::ZvitClick(TObject *Sender)
{
FILE *f;
if(SaveDialog->Execute())
{
f=fopen(SaveDialog->FileName.c_str(),«w»);
if(f!=NULL)
{
list.zvit(f);
fclose(f);
}
}
}
void__fastcall TMainForm::Open(TObject *Sender)
{
FILE *f;
if(OpenDialog->Execute())
{
f =fopen(OpenDialog->FileName.c_str(),«r»);
if(f!=NULL)
{
list.clear();
String->Text="";
NewInt->Text="";
list.load(f);
redraw();
fclose(f);
}
}
}
//------------------------------------------------------------------------void__fastcall TMainForm::Clear(TObject *Sender)
{
list.clear();
redraw();
}
//------------------------------------------------------------------------
void__fastcall TMainForm::Select(TObject *Sender, TMouseButton Button,
TShiftStateShift, int X, int Y)
{
TPoint point;
point.x = X;
point.y = Y;
int sel =List->ItemAtPos(point,true);
int i;
Ptr t;
if(sel>=0)
{
List->ItemIndex= sel;
StrList->ItemIndex= sel;
for(t=list.first(),i=0;t.valid()&&(i
if(t.valid())
{
NewInt->Text= IntToStr(t->d);
Day->Text =IntToStr(t->day);
Year->Text= IntToStr(t->year);
Month->Text= IntToStr(t->month);
//NewDouble->Text= FloatToStr(t->x);
String->Text= t->str;
FirmaString->Text= t->str1;
WidString->Text= t->str2;
}
}
}
//------------------------------------------------------------------------
void__fastcall TMainForm::Update(TObject *Sender)
{
Ptr t;
int i;
int sel;
sel =List->ItemIndex;
if(sel>=0)
{ for(t=list.first(),i=0;t.valid()&&(i
if(t.valid())
{
t->d =StrToInt(NewInt->Text);
t->day =StrToInt(Day->Text);
t->year =StrToInt(Year->Text);
t->month =StrToInt(Month->Text);
t->str =String->Text;
t->str1 =FirmaString->Text;
t->str2 =WidString->Text;
//t->x =StrToFloat(NewDouble->Text);
redraw();
}
}
}
//------------------------------------------------------------------------
void__fastcall TMainForm::SelectStr(TObject *Sender, TMouseButton Button,
TShiftStateShift, int X, int Y)
{
TPoint point;
point.x = X;
point.y = Y;
int sel =StrList->ItemAtPos(point,true);
int i;
Ptr t;
if(sel>=0)
{
List->ItemIndex= sel;
StrList->ItemIndex= sel;
or(t=list.first(),i=0;t.valid()&&(i
if(t.valid())
{
NewInt->Text= IntToStr(t->d);
Day->Text =IntToStr(t->day);
Year->Text= IntToStr(t->year);
Month->Text= IntToStr(t->month);
String->Text= t->str;
FirmaString->Text= t->str1;
WidString->Text= t->str2;
}
}
}
//------------------------------------------------------------------------
void__fastcall TMainForm::SortNum(TObject *Sender)
{
Ptr t,p,q;
for(t=list.first().next();t.valid();t=q)
{
q = t.next();
for(p=t.prev();p.valid()&&(p->d>t->d);--p);
p>>t;
}
redraw();
}
//------------------------------------------------------------------------
void__fastcall TMainForm::SortStr(TObject *Sender)
{
Ptr t,p,q;
for(t=list.first().next();t.valid();t=q)
{
q = t.next();
for(p=t.prev();p.valid()&&(p->str>t->str);--p);
p>>t;
}
redraw();
}
//------------------------------------------------------------------------
void__fastcall TMainForm::Button1Click(TObject *Sender)
{
Close();
}
8. Main.h
#ifndef MainH
#define MainH
#include
#include
#include
#include
#include«Number.h»
#include
#include
#include
#include
#include«Date.h»
#include«My_date.h»
//------------------------------------------------------------------------
typedefMyTable Data;
typedefMyTable::Iterator Ptr;
classTMainForm: public TForm
{
__published://IDE-managed Components
TEdit *NewInt;
TLabel*NewIntLabel;
TButton*AddButton;
TListBox*List;
TButton*DelButton;
TButton*FindButton;
TButton*SortButton;
TButton*SaveButton;
TButton*OpenButton;
TButton*Button3;
TButton *Zvit;
TSaveDialog*SaveDialog;
TOpenDialog*OpenDialog;
TEdit *String;
TLabel*Label1;
TButton*ChangeButton;
TListBox*StrList;
TLabel*NumLabel;
TLabel*StrLabel;
TEdit*FirmaString;
TEdit*WidString;
TLabel*Label3;
TLabel*Label4;
TLabel*Label5;
TLabel*Label6;
TLabel*Label7;
TLabel*Label8;
TEdit *Day;
TEdit *Month;
TEdit *Year;
TButton*Button1;
TImage*Image1;
void__fastcall Add(TObject *Sender);
void__fastcall Del(TObject *Sender);
void__fastcall Find(TObject *Sender);
void__fastcall Sort(TObject *Sender);
void__fastcall Save(TObject *Sender);
oid __fastcallOpen(TObject *Sender);
void__fastcall Clear(TObject *Sender);
void__fastcall Select(TObject *Sender, TMouseButton Button,
TShiftStateShift, int X, int Y);
void__fastcall Update(TObject *Sender);
void__fastcall SelectStr(TObject *Sender, TMouseButton Button,
TShiftStateShift, int X, int Y);
void__fastcall SortNum(TObject *Sender);
void__fastcall SortStr(TObject *Sender);
void__fastcall Button1Click(TObject *Sender);
private://User declarations
Data list;
void redraw();
public:// Userdeclarations
__fastcallTMainForm(TComponent* Owner);
};
9. Magazin.cpp
#include
#include«Date.h»
#pragmahdrstop
USERES(«Magazin.res»);
USEFORM(«Main.cpp»,MainForm);
USEUNIT(«Table.cpp»);
USEUNIT(«Number.cpp»);
USEUNIT(«Date.cpp»);
USEFILE(«Date.h»);
USEUNIT(«My_date.cpp»);
USEUNIT(«data.cpp»);
//------------------------------------------------------------------------WINAPIWinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
Application->Initialize();
Application->CreateForm(__classid(TMainForm),&MainForm);
&ProgramForm);
Application->Run();
}
catch(Exception &exception)
{
Application->ShowException(&exception);
}
return 0;
}