- •79057, М. Львів, вул. Генерала Чупринки, 103/54
- •Стислий зміст
- •1.2. Основні ознаки об'єктно-орієнтованого програмування 31
- •2.2. Розроблення реальної навчальної програми 40
- •2.4. Поняття про логічну та циклічну настанови 49
- •17.1. Поняття про узагальнені функції 364
- •17.2. Узагальнені класи 371
- •1.1.1. Причини створення мови програмування с
- •1.2. Основні ознаки об'єктно-орієнтованого програмування
- •1.2.1. Поняття про інкапсуляцію
- •1.2.2. Поняття про поліморфізм
- •1.2.3. Поняття про успадкування
- •2.1.1. Введення коду програми
- •2.1.2. Компілювання програми
- •2.1.3. Виконання програми
- •2.1.4. Порядкóвий аналіз програми
- •2.1.5. Оброблення синтаксичних помилок
- •2.2. Розроблення реальної навчальної програми
- •2.2.1. Присвоєнням значень змінним
- •2.2.2. Введення даних у програму
- •2.2.3. Деякі можливості виведення даних
- •2.2.4. Введення нового типу даних
- •2.3.1. Основні поняття про функції
- •2.3.3. Передавання аргументів функції
- •2.3.4. Повернення функціями аргуметів
- •2.3.5. Спеціальна функція main()
- •2.4. Поняття про логічну та циклічну настанови
- •2.4.1. Логічна настанова if
- •2.4.2. Циклічна настанова for
- •2.5.1. Поняття про блоки програми
- •2.5.2. Використання крапки з комою і розташування настанов
- •2.5.3. Практика застосування відступів
- •2.6.1. Поняття про ключові слова
- •2.6.2. Розроблення ідентифікаторів користувача
- •2.6.3. Використання стандартної бібліотеки
- •3.1. Оголошення змінних
- •3.1.1. Локальні змінні
- •3.1.2. Формальні параметри
- •3.1.3. Глобальні змінні
- •3.2. Модифікатори типів даних
- •3.3. Поняття про літерали
- •3.3.1. Шістнадцяткові та вісімкові літерали
- •3.3.2. Рядкові літерали
- •3.3.3. Символьні керівні послідовності
- •3.4. Ініціалізація змінних
- •3.5.1. Поняття про вбудовані оператори
- •3.5.2. Арифметичні оператори
- •3.5.3. Оператори інкремента і декремента
- •3.5.5. Оператори відношення та логічні оператори
- •3.6. Запис арифметичних виразів
- •3.6.1. Перетворення типів у виразах
- •3.6.2. Перетворення, що відбуваються під час використання типу bool
- •3.6.3. Операція приведення типів даних
- •3.6.4. Використання пропусків і круглих дужок
- •4.1. Використання настанови вибору if
- •4.1.1. Умовний вираз
- •4.1.2. Вкладені if-настанови
- •4.1.3. Конструкція if-else-if
- •4.2. Використання настанови багатовибірного розгалуження switch
- •4.2.1. Особливості роботи настанови
- •4.2.2. Організація вкладених настанов багатовибірного розгалуження
- •4.3. Використання настанови організації циклу for
- •4.3.1. Варіанти використання настанови організації циклу for
- •4.3.2. Відсутність елементів у визначенні циклу
- •4.3.3. Нескінченний цикл
- •4.3.4. Цикли часової затримки
- •4.4. Використання інших ітераційних настанов
- •4.4.1. Ітераційна настанова while
- •4.4.2. Ітераційна настанова do-while
- •4.4.3. Використання настанови переходу continue
- •4.4.4. Використання настанови break для виходу з циклу
- •4.4.5. Організація вкладених циклів
- •4.5. Використання настанови безумовного переходу goto
- •4.6. Приклад використання настанов керування
- •5.1. Одновимірні|одномірні| масиви
- •5.1.1. На межах масивів "прикордонної застави" немає
- •5.1.2. Сортування масиву
- •5.2. Побудова символьних рядків
- •5.2.1. Оголошення рядкового літерала
- •5.2.2. Зчитування рядків з клавіатури
- •5.3. Застосування бібліотечних функцій для оброблення рядків
- •5.3.1. Використання функції strcpy()
- •5.3.2. Використання функції strcpy()
- •5.3.3. Використання функції strcmp()
- •5.3.4. Використання функції strlen()
- •5.3.5. Використання ознаки завершення рядка
- •5.4.1. Двовимірні масиви
- •5.4.2. Багатовимірні|багатомірні| масиви
- •5.5. Ініціалізація масивів
- •5.5.1. Ініціалізація "розмірних" масивів
- •5.5.2. "Безрозмірна" ініціалізація масивів
- •5.6. Масиви рядків
- •5.6.1. Побудова масивів рядків
- •5.6.2. Приклад використання масивів рядків
- •6.1. Основні поняття про покажчики
- •6.2. Використання|із| покажчиків з операторами присвоєння
- •6.2.1. Оператори роботи з покажчиками
- •6.2.2. Важливість застосування базового типу покажчика
- •6.2.3. Присвоєння значень за допомогою покажчиків
- •6.3. Використання покажчиків у виразах
- •6.3.1. Арифметичні операції над покажчиками
- •6.3.2. Порівняння покажчиків
- •6.4. Покажчики і масиви
- •6.4.1. Основні відмінності між індексуванням елементів масивів і арифметичними операціями над покажчиками
- •6.4.2. Індексування покажчика
- •6.4.3. Взаємозамінність покажчиків і масивів
- •6.4.4. Масиви покажчиків
- •6.4.5. Покажчики і рядкові літерали
- •6.4.5. Приклад порівняння покажчиків
- •6.5. Ініціалізація покажчиків
- •6.5.1. Домовленість про нульові покажчики
- •6.5.2. Покажчики і 16-розрядні середовища
- •6.5.3. Багаторівнева непряма адресація
- •6.6. Виникнення проблем під час використання покажчиків
- •6.6.1. Неініціалізовані покажчики
- •6.6.2. Некоректне порівняння покажчиків
- •6.6.3. Не встановлення покажчиків
- •7.1. Правила дії областей видимості функцій
- •7.1.1. Локальні змінні
- •7.1.2. Оголошення змінних в ітераційних настановах і настановах вибору
- •7.1.3. Формальні параметри
- •7.1.4. Глобальні змінні
- •7.2. Передача покажчиків і масивів як аргументів функціям
- •7.2.1. Виклик функцій з покажчиками
- •7.2.2. Виклик функцій з масивами
- •7.2.3. Передача функціям рядків
- •7.3. Аргументи функції main(): argc і argv
- •7.3.1. Передача програмі числових аргументів командного рядка
- •7.3.2. Перетворення числових рядків у числа
- •7.4. Використання у функціях настанови return
- •7.4.1. Завершення роботи функції
- •7.4.2. Повернення значень
- •7.4.3. Функції, які не повертають значень (void-функції)
- •7.4.4. Функції, які повертають покажчики
- •7.4.5. Прототипи функцій
- •7.4.7. Організація рекурсивних функцій
- •8.1. Способи передачі аргументів функціям
- •8.1.2. Використання покажчика для забезпечення виклику за посиланням
- •8.2. Посилальні параметри
- •8.2.1. Механізм дії посилальних параметрів
- •8.2.2. Варіанти оголошень посилальних параметрів
- •8.2.3. Повернення посилань
- •8.2.4. Створення обмеженого (безпечного) масиву
- •8.2.5. Поняття про незалежні посилання
- •8.2.6. Врахування обмежень під час використання посилань
- •8.2.7. Перевантаження функцій
- •8.2.8. Поняття про ключове слово overload
- •8.3. Передача аргументів функції за замовчуванням
- •8.3.1. Можливі випадки передачі аргументів функції за замовчуванням
- •8.3.2. Порівняння можливості передачі аргументів функції за замовчуванням з її перевантаженням
- •8.3.3. Особливості використання аргументів, що передаються функції за замовчуванням
- •8.4. Перевантаження функцій і неоднозначності, що при цьому виникають
- •9.1. Специфікатори типів даних
- •9.1.1. Застосування специфікатора типу даних const
- •9.1.2. Застосування специфікатора типу даних volatile
- •9.2. Специфікатори класів пам'яті
- •9.2.1. Застосування специфікатора класу пам'яті auto
- •9.2.2. Застосування специфікатора класу пам'яті extern
- •9.2.3. Статичні змінні
- •9.2.4. Регістрові змінні
- •9.2.5. Походження модифікатора register
- •9.3. Порозрядні оператори
- •9.3.1. Порозрядні оператори і, або, що виключає або і не
- •9.3.2. Оператори зсуву
- •9.4.1. Перерахунки – списки іменованих цілочисельних констант
- •9.4.2. Створення нових імен для наявних типів даних
- •9.4.3. Оператор "знак запитання"
- •9.4.4. Складені оператори присвоєння
- •9.4.5. Оператор "кома"
- •9.4.6. Декілька присвоєнь "в одному"
- •9.4.7. Використання ключового слова sizeof
- •9.5.1. Оператори динамічного розподілу пам'яті
- •9.5.2. Ініціалізація динамічно виділеної пам'яті
- •9.5.3. Динамічне виділення пам'яті для масивів
- •9.5.4. Функції виділення та звільнення пам'яті у мові програмування с
- •10.1. Робота зі структурами
- •10.1.1. Основні положення
- •10.1.2. Доступ до членів структури
- •10.1.3. Масиви структур
- •10.1.4. Приклад застосування структури
- •10.1.5. Присвоєння структур
- •10.1.6. Передача структури функції як аргументу
- •10.1.7. Повернення функцією структури як значення
- •10.2. Використання покажчиків на структури і оператора "стрілка"
- •10.2.1. Особливості використання покажчиків на структури
- •10.2.2. Приклад використання покажчиків на структури
- •10.3. Посилання на структури
- •10.3.1. Використання структур під час передачі функції параметрів за посиланням
- •10.3.2. Використання як членів структур масивів і структур
- •10.4. Бітові поля структур
- •10.5. Особливості використання об'єднань
- •10.5.1. Оголошення об'єднання
- •10.5.2. Анонімні об'єднання
- •10.5.3. Використання оператора sizeof для гарантії переносності коду програми
- •11.1. Потреба об'єктно-орієнтованого програмування
- •11.1.1. Процедурні мови програмування
- •11.1.2. Поділ програми на функції
- •11.1.3. Недоліки структурного програмування
- •11.1.4. Неконтрольований доступ до даних
- •11.1.5. Відображення картини реального світу
- •11.2. Поняття про об'єктно-орієнтований підхід
- •11.2.1. Виробнича аналогія
- •11.3. Основні компоненти об'єктно-орієнтованої мови програмування
- •11.3.1. Поділ програми на об'єкти
- •11.3.2. Визначення класу
- •11.3.3. Поняття про успадкування в класах
- •11.3.4. Повторне використання коду
- •11.3.5. Поняття про типи даних користувача
- •11.3.6. Поняття про поліморфізм і перевантаження операторів
- •11.5. Вивчення основ створення об'єктно-орієнтованих програм
- •11.6. Поняття про універсальну мову моделювання
- •12.1. Базові поняття класу
- •12.2. Конструктори і деструктори
- •12.2.1. Параметризовані конструктори
- •12.2.2. Альтернативний варіант ініціалізації членів-даних об'єкта
- •12.3. Доступ до членів класу
- •12.4. Класи і структури – споріднені типи
- •12.5. Об'єднання і класи – споріднені типи
- •12.6. Вбудовувані функції
- •12.7. Створення масивів об'єктів
- •12.8. Покажчики на об'єкти
- •13.1. Поняття про функції-"друзі" класу
- •13.2. Перевантаження конструкторів
- •13.3. Динамічна ініціалізація конструктора
- •13.4. Присвоєння об'єктів
- •13.5. Передача об'єктів функціям
- •13.5.1. Конструктори, деструктори і передача об'єктів
- •13.5.2. Потенційні проблеми під час передачі параметрів
- •13.6. Повернення об'єктів функціями
- •13.7. Створення і використання конструктора копії
- •13.7.1. Використання конструктора копії для ініціалізації одного об'єкта іншим
- •13.7.2. Використання конструктора копії для передачі об'єкта функції
- •13.7.3. Використання конструктора копії під час повернення функцією об'єкта
- •13.7.4. Конструктори копії – а чи не можна знайти щось простіше?
- •13.8. Ключове слово this
- •14.1. Перевантаження операторів з використанням функцій-членів класу
- •14.1.3. Особливості реалізації механізму перевантаження операторів
- •14.1.4. Значення порядку слідування операндів
- •14.2. Перевантаження операторів з використанням функцій-не членів класу
- •14.2.1. Використання функцій-"друзів" класу для перевантаження бінарних операторів
- •14.2.2. Використання функцій-"друзів" класу для перевантаження унарних операторів
- •14.2.3. Перевантаження операторів відношення та логічних операторів
- •14.3. Особливості реалізації оператора присвоєння
- •14.4. Перевантаження оператора індексації масивів ([])
- •14.5. Перевантаження оператора "()"
- •14.6. Перевантаження інших операторів
- •14.6.1. Приклад перевантаження операторів класу рядків
- •15.1. Поняття про успадкування
- •15.2. Керування доступом до членів базового класу
- •15.3. Використання захищених членів класу
- •15.3.1. Використання специфікатора доступу protected для надання членам класу статусу захищеності
- •15.3.2. Використання специфікатора protected для успадкування базового класу
- •15.3.3. Узагальнення інформації про використання специфікаторів public, protected і private
- •15.4. Успадкування декількох базових класів
- •15.5. Використання конструкторів і деструкторів під час реалізації механізму успадкування
- •15.5.1. Прядок виконання конструкторів і деструкторів
- •15.5.2. Передача параметрів конструкторам базового класу
- •15.6. Повернення успадкованим членам початкової специфікації доступу
- •15.7. Віртуальні базові класи
- •16.1. Покажчики на похідні типи – підтримка динамічного поліморфізму
- •16.2. Віртуальні функції
- •16.2.1. Поняття про віртуальні функції
- •16.2.2. Успадкування віртуальних функцій
- •16.2.3. Потреба у застосуванні віртуальних функцій
- •16.2.4. Приклад застосування віртуальних функцій
- •16.2.5. Суто віртуальні функції та абстрактні класи
- •16.2.6. Порівняння раннього зв'язування з пізнім
- •16.2.7. Поняття про поліморфізм і пуризм
- •17.1. Поняття про узагальнені функції
- •17.1.1. Шаблонна функція з одним узагальненим типом
- •17.1.2. Шаблонна функція з двома узагальненими типами
- •17.1.3. Безпосередньо задане перевантаження узагальненої функції
- •17.1.4. Перевантаження шаблону функції
- •17.1.5. Використання стандартних параметрів у шаблонних функціях
- •17.1.6. Обмеження, які застосовуються під час використання узагальнених функцій
- •17.1.7. Приклад створення узагальненої функції abs()
- •17.2. Узагальнені класи
- •17.2.1. Створення класу з одним узагальненим типом даних
- •17.2.2. Створення класу з двома узагальненими типами даних
- •17.2.3. Створення узагальненого класу для організації безпечного масиву
- •17.2.4. Використання в узагальнених класах аргументів, що не є типами
- •17.2.5. Використання в шаблонних класах аргументів за замовчуванням
- •17.2.6. Безпосередньо задані спеціалізації класів
- •18.1. Основи оброблення виняткових ситуацій
- •18.1.1. Системні засоби оброблення винятків
- •18.1.2. Використання функцій exit() і abort() для завершення роботи програми
- •18.1.3. Перехоплення винятків класового типу
- •18.1.4. Використання декількох catch-настанов
- •18.2. Варіанти оброблення винятків
- •18.2.1. Перехоплення всіх винятків
- •18.2.2. Обмеження, що накладаються на тип винятків, які генеруються функціями
- •18.2.3. Повторне генерування винятку
- •18.3. Оброблення винятків, згенерованих оператором new
- •18.4. Перевантаження операторів new і delete
- •19.2.3. Класи потоків
- •19.3. Перевантаження операторів введення-виведення даних
- •19.3.1. Створення перевантажених операторів виведення даних
- •19.3.2. Використання функцій-"друзів" класу для перевантаження операторів виведення даних
- •19.3.3. Створення перевантажених операторів введення даних
- •19.4. Форматоване введення-виведення даних
- •19.4.1. Форматування даних з використанням функцій-членів класу ios
- •19.4.2. Встановлення ширини поля, точності та символів заповнення
- •19.4.3. Використання маніпуляторів введення-виведення даних
- •19.4.4. Створення власних маніпуляторних функцій
- •19.5. Файлове введення-виведення даних
- •19.5.1. Відкриття та закриття файлу
- •19.5.2. Зчитування і запис текстових файлів
- •19.5.3. Неформатоване введення-виведення даних у двійковому режимі
- •19.5.4. Зчитування і запис у файл блоків даних
- •19.5.6. Приклад порівняння файлів
- •19.5.7. Використання інших функцій для двійкового введення-виведення
- •19.5.8. Перевірка статусу введення-виведення
- •19.6. Використання файлів довільного доступу
- •19.6.1. Функції довільного доступу
- •19.6.2. Приклади використання довільного доступу до вмісту файлу
- •19.7. Використання перевантажених операторів введення-виведення даних під час роботи з файлами
- •20.1. Динамічна ідентифікація типів (rtti)
- •20.1.1. Отримання типу об'єкта у процесі виконання програми
- •20.1.2. Приклад rtti-застосування
- •20.1.3. Застосування оператора typeid до шаблонних класів
- •20.2. Оператори приведення типів
- •20.2.1. Оператор приведення поліморфних типів dynamic_cast
- •20.2.2. Оператор перевизначення модифікаторів const_cast
- •20.2.3. Оператор неполіморфного приведення типів static_cast
- •20.2.4. Оператор перетворення типу reinterpret_cast
- •20.2.5. Порівняння звичайної операції приведення типів з новими чотирма cast-операторами
- •21.1. Простори імен
- •21.1.1. Поняття про простори імен
- •21.1.2. Застосування настанови using
- •21.1.3. Неіменовані простори імен
- •21.1.4. Застосування простіру імен std
- •21.2. Застосування покажчиків на функції
- •21.2.1. Передача покажчиком на функцію її адреси іншій функції
- •21.2.2. Пошук адреси перевантаженої функції
- •21.3. Поняття про статичні члени-даних класу
- •21.5. Застосування до функцій-членів класу модифікаторів const і mutable
- •21.6. Використання explicit-конструкторів
- •21.7. Синтаксис ініціалізації членів-даних класу
- •21.8. Використання ключового слова asm
- •21.9. Специфікатор компонування функцій
- •21.11. Створення функцій перетворення
- •22.1. Огляд стандартної бібліотеки шаблонів
- •22.2. Поняття про контейнерні класи
- •22.3. Робота з векторами
- •22.3.1. Доступ до вектора за допомогою ітератора
- •22.3.2. Вставлення та видалення елементів з вектора
- •22.3.3. Збереження у векторі об'єктів класу
- •22.3.4. Доцільність використання ітераторів
- •22.4. Робота зі списками
- •22.4.1. Використання базових операцій для роботи зі списком
- •22.4.2. Сортування списку
- •22.4.3. Об'єднання одного списку з іншим
- •22.4.4. Зберігання у списку об'єктів класу
- •22.5. Поняття про відображення
- •22.5.1. Робота з відображеннями
- •22.5.2. Зберігання у відображенні об'єктів класу
- •22.6. Алгоритми оброблення контейнерних даних
- •22.6.1. Підрахунок кількості елементів
- •22.6.2. Видалення і заміна елементів
- •22.6.3. Реверсування послідовності
- •22.6.4. Перетворення послідовності
- •22.6.5. Дослідження алгоритмів
- •22.7. Використання класу string
- •22.7.1. Огляд функцій-членів класу string
- •22.7.2. Зберігання рядків у інших контейнерах
- •23.1.1. Директива #define
- •23.1.2. Директива #error
- •23.1.3. Директива #include
- •23.2. Директиви умовного компілювання
- •23.2.1. Директиви #if, #else, #elif і #endif
- •23.2.2. Директиви #ifdef і #ifndef
- •23.2.3. Директива #undef
- •23.2.4. Використання оператора defined
- •23.2.5. Про значення препроцесора
- •23.2.6. Директива #line
- •23.2.7. Директива #pragma
- •23.3. Оператори препроцесора "#" і "##"
- •23.4. Зарезервовані макроімена
- •23.5. Деякі поради студентам
- •24.1. Удосконалення процесу розроблення програмного забезпечення
- •24.1.1. Безпосередній процес розроблення пз
- •24.1.2. Каскадний процес розроблення пз
- •24.1.3. Використання ооп
- •24.1.4. Сучасні підходи до розроблення пз
- •24.2. Моделювання варіантів використання
- •24.2.1. Поняття про діючі суб'єкти
- •24.2.2. Поняття про варіанти використання
- •24.2.3. Поняття про сценарії
- •24.2.4. Застосування діаграм варіантів використання
- •24.2.5. Описи варіантів використання
- •24.2.6. Перехід від варіантів використання до класів
- •24.3. Предметна область програмування
- •24.3.1. Рукописні форми
- •24.3.2. Прийняття допущень і спрощень
- •24.4. Програма landlord: етап удосконалення
- •24.4.1. Встановлення діючих суб'єктів
- •24.4.2. З'ясування варіантів використання
- •24.4.3. Опис варіантів використання
- •24.4.4. Передбачення додаткових сценаріїв
- •24.4.5. Використання діаграм дій uml
- •24.5. Перехід від варіантів використання до класів
- •24.5.1. Аналіз переліку іменників з опису варіантів використання
- •24.5.2. Уточнення переліку іменників
- •24.5.3. Визначення атрибутів
- •24.5.4. Перехід від дієслів до повідомлень
- •24.5.5. Побудова діаграм класів
- •24.5.6. Побудова діаграм послідовностей
- •24.6. Кроки написання коду програми
- •24.6.1. Написання заголовного файлу
- •24.6.2. Створення початкових *.Срр файлів
- •24.6.3. Вимушені спрощення коду програми
- •24.6.4. Взаємодія користувача з програмою
- •24.6.5. Труднощі написання коду програми
- •24.7. Резюме
24.6.2. Створення початкових *.Срр файлів
У початкових файлах містяться тіла методів, які були оголошені в заголовному файлі. Написання коду програми цих методів має починатися тільки на цьому етапі розроблення ПЗ і ні кроком раніше, тому що тільки зараз ми знаємо ім'я кожної функції, її призначення і навіть, можливо, можемо передбачити аргументи, що передаються їй.
Ми відокремили зерна від полови: main() зберігаємо в одному коротенькому файлі lordApp.cpp, а визначення функцій, оголошених у заголовному файлі, – в іншому. У секції main() створюється об'єкт userInterface і викликається метод interact(). Наведемо файл, у якому зберігається main().
Код програми 24.2. Програма lordApp.cpp
// lordApp.cpp
// Файл, що постачається клієнту.
#include "landlord.h"
int main()
{
userInterface theUserInterface;
theUserInterface.interact();
getch(); return 0;
}
// <------> Кінець файлу lordApp.cpp
Ну і нарешті, розглянемо файл landlord.cpp, у якому містяться всі визначення методів.
Код програми 24.3. Програма landlord.cpp
void getaLine(string& inStr) // Отримання рядка тексту
{
char temp[21];
cin.get(temp, 20, '\n');
cin.ignore(20, '\n');
inStr = temp;
} // <------> Кінець getaLine()
char getaChar() // Отримання символу
{
char ch = cin.get();
cin.ignore(80, '\n');
return ch;
} // <------> Кінець getaChar()
// >------> Методи класу tenant
tenant::tenant(string n, int aNo) : name(n), aptNumber(aNo)
{ /* тут порожньо */ }
//---------------------------------------------------------
tenant::~tenant()
{ /* тут також порожньо */ }
//---------------------------------------------------------
int tenant::getAptNumber()
{ return aptNumber; }
//---------------------------------------------------------
bool operator < (const tenant& t1, const tenant& t2)
{ return t1.name < t2.name; }
//---------------------------------------------------------
bool operator == (const tenant& t1, const tenant& t2)
{ return t1.name == t2.name; }
//---------------------------------------------------------
ostream& operator << (ostream& s, const tenant& t)
{ s << t.aptNumber << '\t' << t.name << endl; return s; }
//---------------------------------------------------------
// >------> Методи класу tenantInputScreen
void tenantInputScreen::getTenant() // Отримання даних про мешканцях
{
cout << "Введіть ім'я мешканця (Тарас Редько): ";
getaLine(tName);
cout << "Введіть номер кімнати (101): ";
cin >> aptNo;
cin.ignore(80, '\n'); // Створити мешканця
tenant* ptrTenant = new tenant(tName, aptNo);
ptrTenantList->insertTenant(ptrTenant); // Занести перелік мешканців
}
bool compareTenants::operator () (tenant* ptrT1, tenant* ptrT2) const
{ return *ptrT1 < *ptrT2; }
//---------------------------------------------------------
// >------> Методи класу tenantList
tenantList::~tenantList() // Оголошення деструктора
{
while( !setPtrsTens.empty() ) { // Видалення усіх мешканців
// Видалення покажчиків з множини
iter = setPtrsTens.begin();
delete *iter;
setPtrsTens.erase(iter);
}
} // <------> Кінець ~tenantList()
void tenantList::insertTenant(tenant* ptrT)
{
setPtrsTens.insert(ptrT); // Вставка
}
//---------------------------------------------------------
int tenantList::getAptNo(string tName) // Ім'я присутнє у переліку?
{
int aptNo;
tenant dummy(tName, 0);
iter = setPtrsTens.begin();
while( iter != setPtrsTens.end() ) {
aptNo = (*iter)->getAptNumber(); // Пошук мешканця
if(dummy == **iter++) // В переліку?
return aptNo; // Так
}
return -1; // Немає
} // <------> Кінець getAptNo()
void tenantList::display() // Виведення переліку мешканців
{
cout << "\nApt#\tІм'я мешканця\n-------------------\n";
if( setPtrsTens.empty() )
cout << "***Нема мешканців***\n";
else {
iter = setPtrsTens.begin();
while( iter != setPtrsTens.end() ) cout << **iter++;
}
} // <------> Кінець display()
// >------> Методи класу rentRow
rentRow::rentRow(int an) : aptNo(an) // Однопараметризований конструктор
{ fill( &rent[0] &rent[12], 0); }
//---------------------------------------------------------
void rentRow::setRent(int m, float am)
{ rent[m]= am; }
//---------------------------------------------------------
float rentRow::getSumOfRow() // Сума орендних платежів у рядку
{ return accumulate( &rent[0] &rent[12], 0); }
//---------------------------------------------------------
bool operator < (const rentRow& t1, const rentRow& t2)
{ return t1.aptNo < t2.aptNo; }
//---------------------------------------------------------
bool operator == (const rentRow& t1, const rentRow& t2)
{ return t1.aptNo == t2.aptNo; }
//---------------------------------------------------------
ostream& operator << (ostream& s, const rentRow& an)
{
s << an.aptNo << '\t'; // Вивести номер кімнати
for(int j=0; j<12; j++) { // Вивести 12 орендних платежів
if(an.rent[j] == 0) s << " 0 ";
else s << an.rent[j] << " ";
}
s << endl;
return s;
} // <------> Кінець operator <<
bool compareRows::operator () (rentRow* ptrR1, rentRow* ptrR2) const
{ return *ptrR1 < *ptrR2; }
// >------> Методи класу rentRecord
rentRecord::~rentRecord() // Оголошення деструктора
{
while( !setPtrsRR.empty() ) { // Видалити рядки з платежами
// Видалити покажчики з множини
iter = setPtrsRR.begin();
delete *iter;
setPtrsRR.erase(iter);
}
} // <------> Кінець ~rentRecord()
void rentRecord::insertRent(int aptNo, int month, float amount)
{
rentRow searchRow(aptNo); // Тимчасовий рядок з тим самим aptNo
iter = setPtrsRR.begin(); // Пошук setPtrsRR
while( iter != setPtrsRR.end() ) {
if(searchRow==**iter) { // rentRow знайдений?
// так, заносимо
(*iter)->setRent(month, amount); // Рядок у перелік
return;
}
else
iter++;
} // Не знайдений
rentRow* ptrRow = new rentRow(aptNo); // Новий рядок
ptrRow->setRent(month, amount); // Занести в неї платіж
setPtrsRR.insert(ptrRow); // Занести рядок вектор
} // <------> Кінець insertRent()
void rentRecord::display()
{
cout << "\nAptNo\tСіч Лют Бер Квіт Трав Черв "
<< "Лип Серп Вер Жовт Лист Груд\n"
<< "---------------------------------"
<< "---------------------------------\n";
if( setPtrsRR.empty() )
cout << "***Нема платежів!***\n";
else {
iter = setPtrsRR.begin();
while( iter != setPtrsRR.end() )
cout << **iter++;
}
} // <------> Кінець display()
float rentRecord::getSumOfRents() // Сума усіх платежів
{
float sumRents = 0.0;
iter = setPtrsRR.begin();
while( iter != setPtrsRR.end() ) {
sumRents += (*iter)->getSumOfRow();
iter++;
}
return sumRents;
} // <------> Кінець getSumOfRents()
// >------> Методи класу rentInputScreen
void rentInputScreen::getRent()
{
cout << "Введіть ім'я мешканця: ";
getaLine(renterName);
aptNo = ptrTenantList->getAptNo(renterName);
if(aptNo > 0) { // Якщо ім'я знайдене
// Отримати суму платежу
cout << "Введіть суму платежу (345.67): ";
cin >> rentPaid;
cin.ignore(80, '\n');
cout << "Введіть номер місяця оплати (1-12): ";
cin >> month;
cin.ignore(80, '\n');
month--; // (внутрішня нумерація 0-11)
ptrRentRecord->insertRent(aptNo, month, rentPaid);
}
else // Повернення
cout << "Такого мешканця немає.\n";
} // <------> Кінець getRent()
// Методи класу expense
bool operator < (const expense& e1, const expense& e2)
{ // Порівнює дати
if(e1.month == e2.month) // Якщо той же місяць
return e1.day < e2.day; // Порівняти дні
else // Інакше
return e1.month < e2.month; // Порівняти місяці
}
//---------------------------------------------------------
bool operator == (const expense& e1, const expense& e2)
{ return e1.month == e2.month && e1.day == e2.day; }
//---------------------------------------------------------
ostream& operator << (ostream& s, const expense& exp)
{
s << exp.month << '/' << exp.day << '\t' << exp.payee << '\t' ;
s << exp.amount << '\t' << exp.category << endl;
return s;
}
//---------------------------------------------------------
bool compareDates::operator () (expense* ptrE1, expense* ptrE2) const
{ return *ptrE1 < *ptrE2; }
//---------------------------------------------------------
bool compareCategories::operator ()(expense* ptrE1, expense* ptrE2) const
{ return ptrE1->category < ptrE2->category; }
//---------------------------------------------------------
// >------> Методи класу expenseRecord
expenseRecord::~expenseRecord() // Оголошення деструктора
{
while( !vectPtrsExpenses.empty() ){ // Видалити об'єкти expense
// Видалити покажчики на вектор
iter = vectPtrsExpenses.begin();
delete *iter;
vectPtrsExpenses.erase(iter);
}
} // <------> Кінець ~expenseRecord()
void expenseRecord::insertExp(expense* ptrExp)
{ vectPtrsExpenses.push_back(ptrExp); }
//---------------------------------------------------------
void expenseRecord::display()
{
cout << "\nДата\tОтримувач\t\tСума\tКатегорія\n"
<< "----------------------------------------\n";
if( vectPtrsExpenses.size() == 0 )
cout << "*** Витрат немає ***\n";
else {
sort( vectPtrsExpenses.begin(), // Сортування за датою
vectPtrsExpenses.end(), compareDates() );
iter = vectPtrsExpenses.begin();
while( iter != vectPtrsExpenses.end() ) cout << **iter++;
}
} // <------> Кінець display()
float expenseRecord::displaySummary() // Використовується при
// складанні річного звіту
{
float totalExpenses = 0; // Сума, всі категорії
if( vectPtrsExpenses.size() == 0 ) {
cout << "\tВсі категорії\t0\n";
return;
}
// Сортувати за категоріями
sort( vectPtrsExpenses.begin(),
vectPtrsExpenses.end(), compareCategories() );
// По кожній категорії сума записів
iter = vectPtrsExpenses.begin();
string tempCat = (*iter)->category;
float sumCat = 0.0;
while( iter != vectPtrsExpenses.end() ) {
if(tempCat == (*iter)->category)
sumCat += (*iter)->amount; // Та ж категорія
else { // Інша
cout << '\t' << tempCat << '\t' << sumCat << endl;
totalExpenses += sumCat; // Додати попередню категорію
tempCat = (*iter)->category;
sumCat = (*iter)->amount; // Додати кінцеве значення суми
}
iter++;
} // <------> Кінець while
totalExpenses += sumCat; // Додати суму кінцевої категорії
cout << '\t' << tempCat << '\t' << sumCat << endl;
return totalExpenses;
} // <------> Кінець displaySummary()
// >------> Методи класу expenseInputScreen
expenseInputScreen::expenseInputScreen(expenseRecord* per) :
ptrExpenseRecord(per)
{ /*пусто*/ }
//------------------------------------------------------
void expenseInputScreen::getExpense()
{
int month, day;
string category, payee;
float amount;
cout << "Введіть місяць (1-12): ";
cin >> month;
cin.ignore(80, '\n');
cout << "Введіть день (1-31): ";
cin >> day;
cin.ignore(80, '\n');
cout << "Введіть категорію витрат (Ремонт, Податки): ";
getaLine(category);
cout << "Введіть отримувача " << "(ЛьвівЕлектроЗбут): ";
getaLine(payee);
cout << "Введіть суму (39.95): ";
cin >> amount;
cin.ignore(80, '\n');
expense* ptrExpense = new
expense(month, day, category, payee, amount);
ptrExpenseRecord->insertExp(ptrExpense);
} // <------> Кінець getExpense()
// >------> Методи класу annualReport
annualReport::annualReport(rentRecord* pRR,
expenseRecord* pER) : ptrRR(pRR), ptrER(pER)
{ /* порожньо */ }
//---------------------------------------------------------
void annualReport::display()
{
cout << "Річний звіт\n--------------\n";
cout << "Доходи\n";
cout << "\tОрендна плата\t\t";
rents = ptrRR->getSumOfRents();
cout << rents << endl;
cout << "Витрати\n";
expenses = ptrER->displaySummary();
cout << "\nБаланс\t\t\t" << rents - expenses << endl;
} // <------> Кінець display()
// >------> Методи класу userInterface
userInterface::userInterface()
{ // Це життєво важливо для програми
ptrTenantList = new tenantList;
ptrRentRecord = new rentRecord;
ptrExpenseRecord = new expenseRecord;
} // <------> Кінець userInterface()
userInterface::~userInterface() // Оголошення деструктора
{
delete ptrTenantList;
delete ptrRentRecord;
delete ptrExpenseRecord;
} // <------> Кінець ~userInterface()
void userInterface::interact()
{
while(true) {
cout << "Для введення даних натисніть 'i'\n"
<< " 'd' для виведення звіту\n"
<< " 'q' для виходу: ";
ch = getaChar();
if(ch=='i') { // Введення даних
cout << " 't' для додавання мешканця\n"
<< " 'r' для запису орендної плати\n"
<< " 'e' для запису витрат: ";
ch = getaChar();
switch(ch){
// Екрани введення існують тільки під час їх використання
case 't': ptrTenantInputScreen =
new tenantInputScreen(ptrTenantList);
ptrTenantInputScreen->getTenant();
delete ptrTenantInputScreen;
break;
case 'r': ptrRentInputScreen =
new rentInputScreen(ptrTenantList, ptrRentRecord);
ptrRentInputScreen->getRent();
delete ptrRentInputScreen;
break;
case 'e': ptrExpenseInputScreen =
new expenseInputScreen(ptrExpenseRecord);
ptrExpenseInputScreen->getExpense();
delete ptrExpenseInputScreen;
break;
default: cout << "Невідома функція\n";
break;
} // <------> Кінець секції switch
} // <------> Кінець умови if
else if(ch=='d') { // Виведення даних
cout << " 't' для виведення мешканців\n"
<< " 'r' для виведення орендної плати\n"
<< " 'e' для виведення витрат\n"
<< " 'a' для виведення річного звіту: ";
ch = getaChar();
switch(ch) {
case 't': ptrTenantList->display();
break;
case 'r': ptrRentRecord->display();
break;
case 'e': ptrExpenseRecord->display();
break;
case 'a':
ptrAnnualReport = new annualReport(ptrRentRecord,
ptrExpenseRecord);
ptrAnnualReport->display();
delete ptrAnnualReport;
break;
default: cout << "Невідома функція виведення\n";
break;
} // <------> Кінець switch
} // <------> Кінець elseif
else if(ch=='q')
return; // Вихід
else
cout << "Невідома функція.\n"
<< "Натискайте тільки 'i', 'd' або 'q'\n";
} // <------> Кінець while
} // <------> Кінець interact()
// <------> Кінець файлу landlord.cpp
