Студопедия

КАТЕГОРИИ:


Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748)

Т Е Х Н О Л О Г І Ї 6 страница




Код програми 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-> insert Tenant(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:: insert Tenant(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:: insert Rent(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;

}

iter++;

} // Не знайдений

rentRow* ptrRow = new rentRow(aptNo); // Новий рядок

ptrRow->setRent(month, amount); // Занести в неї платіж

setPtrsRR. insert (ptrRow); // Занести рядок вектор

} // <------> Кінець insert Rent()

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-> insert Rent(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:: insert Exp(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-> insert Exp(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

} // <------> Кінець else if

else if (ch=='q')

return; // Вихід

cout << "Невідома функція.\n"

<< "Натискайте тільки 'i', 'd' або 'q'\n";

} // <------> Кінець while

} // <------> Кінець interact()

 

// <------> Кінець файлу landlord.cpp

24.6.3. Вимушені спрощення коду програми

Хоча код програми вийшов достатньо довгим, та все ж таки він ще містить велику кількість допущень і спрощень. Текстовий інтерфейс користувача замість меню, віконець і сучасної графічної оболонки; майже повна відсутність перевірок на помилки введення даних; підтримка даних тільки за один рік, тощо.

24.6.4. Взаємодія користувача з програмою

Ми пройшли вогонь і воду – спланували і написали програму. Тепер цікаво було б пройти і мідні труби – подивитися нашу програму "на ходу". Ось підходить до комп'ютера Степан Полатайко і натискає "i", а потім "t" для введення нового мешканця. Після відповідних запитів програми (у дужках у кінці запиту зазвичай пишуть формат даних) він вводить інформацію про мешканця.

Натисніть 'i' для введення даних.

'd' для виведення звіту

'q' для виходу: i

Натисніть 't' для додавання мешканця

'r'| для запису орендної плати

'e'| для запису витрат: t

Введіть ім'я мешканця (Тарас Редько): Анатолій Бондарчук

Введіть номер кімнати: 101

Після введення усіх мешканців домовласник зажадав проглянути їх повний перелік (скорочено обмежимося п'ятьма мешканцями з дванадцяти):

Натисніть 'i' для введення даних

'd' для виведення звіту

'q' для виходу: d

Натисніть 't' для виведення мешканців

'r' для виведення орендної плати

'e' для виведення витрат

'a' для виведення річного звіту: t

 

Apt # Ім'я мешканця

----------------

101 Анатолій Бондарчук

102 Петро Ничипорук

103 Тарас Редько

104 Валентина Петрова

201 Ігор Склярук

Для фіксації внесеної орендної плати домовласник Степан Полатайко, кум знаменитого авторитета Валерія Івановича Міщука з вулиці Левандівка Залізничного району м. Львова, натискає спочатку "i", потім "r" (далі ми не повторюватимемо пункти меню у прикладах роботи програми). Подальша взаємодія з програмою протікає так:

Введіть ім'я мешканця: Петро Ничипорук

Введіть внесену суму (345.67): 595

Введіть місяць оплати (1-12): 5

Петро Ничипорук послав домовласнику чек оплати за травень у розмірі 595 грн. Зрозуміло, ім'я мешканця повинно бути надруковано так само, як воно з'являлося в переліку мешканців. Окрім того, дещо розумніша програма, можливо, дала б гнучкіше вирішення цього питання.

Щоб побачити всю таблицю доходів від оренди приміщень, потрібно натиснути 'd', а потім "r". Ось який стан таблиці після внесення травневої орендної плати:

Apt No Січ Лют Бер Квіт Трав Черв Лип Серп Вер Жоат Лист Груд

-----------------------------------------------------

101 695 695 695 695 695 0 0 0 0 0 0 0

102 595 595 595 595 595 0 0 0 0 0 0 0

103 810 810 825 825 825 0 0 0 0 0 0 0

104 645 645 645 645 645 0 0 0 0 0 0 0

201 720 720 720 720 720 0 0 0 0 0 0 0

Зверніть увагу, оплата для Тарас Редька з березня була збільшена.

Щоб ввести значення витрат, потрібно натиснути "i" і 'e'. Наприклад:

Введіть місяць: 1

Введіть день: 15

Введіть категорію витрат (Ремонт, Податки): Комунальні послуги

Введіть отримувача (ЛьвівЕлектроЗбут): ЛЕЗ

Введіть суму платежу: 427.23

Для виведення на екран таблиці витрат необхідно натиснути 'd' і "е". Нижче показано початок такої таблиці:

Дата Отримувач Сума Категорія............ 714

-------------

1/3 УльтраМегаБанк 5187.30 Сплата за заставу

1/8 ПростоВодоканал 963.0 Комунальні послуги

1/9 Суперстрах 4840.00 Страховка

1/15 ПЭС 727.23 Комунальні послуги

1/22 Непотріб дядька Сема 54.81 Постачання

1/25 Підвал Майстра 150.00 Ремонт

2/3 УльтраМегаБанк 5187.30 Сплата за заставу

Нарешті, для виведення річного звіту користувач повинен натиснути 'd' і "е". Подивимося на звіт за перші п'ять місяців року:

Річний звіт

-------------

Доходи

Орендна плата 42610.12

Витрати

Сплата за заставу 25936.57

Комунальні послуги 7636.15

Реклама 95.10

Ремонт 1554.90

Постачання 887.22

Страховка 4840.00

Баланс 1660.18

Категорії витрат сортуються в алфавітному порядку. У реальній ситуації може бути достатньо багато бюджетних категорій, одні з яких містять податки, інші – витрати на поїздки, впорядкування ландшафтного дизайну дворової території, прибирання приміщень і т.д.

24.6.5. Труднощі написання коду програми

Процес розроблення реальних проектів може проходити зовсім не так гладко, як це було продемонстровано у нашому прикладі. Може знадобитися не одна, а декілька ітерацій кожного з розглянутих вище етапів. Програмісти можуть по-різному уявляти собі потреби користувачів, що вимагатиме повернення з середини етапу побудови на етап удосконалення. Користувачі також можуть запросто змінити свої вимоги, не дуже замислюючись над тим, які незручності вони тим самим створюють для розробників.

24.7. Резюме

Для простих програм під час їх розроблення може бути достатньо методу проб і помилок. Але під час розроблення крупних проектів потрібен більш організований підхід. У цьому розділі ми розглянули один з можливих методів розроблення ПЗ під загальною назвою уніфікований процес. Він складається з таких етапів: початок, удосконалення, побудова і впровадження. Етап удосконалення відповідає програмному аналізу, а побудова – плануванню структури програми і написанню її коду.

В уніфікованому процесі використовується прецедентний підхід до розроблення ПЗ. Ретельно вивчаються потенційні користувачі та аналізуються їх вимоги. Діаграма варіантів використання UML демонструє діючі суб'єкти і виконувані операції, що ініціюються ними (варіанти використання). Будь-який іменник з описів варіантів використання може в майбутньому стати іменем класу або атрибуту. Дієслова перетворюються на методи.

Доповненням до діаграм варіантів використання є ще багато інших UML-діаграм, що допомагають більш повною мірою досягти взаєморозуміння між користувачами і розробниками. Відносини між класами показуються на діаграмах класів, керівні потоки – на діаграмах дій, а діаграми послідовностей відображають взаємозв'язки між об'єктами під час виконання варіантів використання.

 


Додатки. Доповнення до С++

У цій частині навчального посібника будуть розглядатися такі основні теми:

Додаток А. Основи створення консольних програм у середовищі Borland C++ Builder.................................................................... 544

Додаток Б. Основи створення консольних програм у середовищі Microsoft Visual C++............................................................................... 552

Додаток В. Орієнтована С-система введення-виведення............................................................. 558




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


Дата добавления: 2014-11-29; Просмотров: 466; Нарушение авторских прав?; Мы поможем в написании вашей работы!


Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет



studopedia.su - Студопедия (2013 - 2024) год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! Последнее добавление




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