Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Приклад виконання Завдання 1

Поиск

Варіант 1. Похідний клас містить метод (функцію) копіювання заданої кількості символів з заданої позиції.

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

Структура класів має такий вигляд:

class main_class {

char c;

int Num,UK,KIL;

 

protected:

FILE* stream;

public:

main_class();

~main_class();

void Quantity_of_chars();

void Number_of_space();

void Number_of_words();

void Delete_wrong_space();

};

class successor: public main_class {

public:

successor():main_class(){}

void Copy_to_file();

};

Лістинг програми:

#include <cstring>

#include <cstdio>

#include <cstdlib>

class main_class {

char c;

int Num,UK,KIL;

protected:

FILE* stream;

public:

main_class();

~main_class();

void Quantity_of_chars();

void Number_of_space();

void Number_of_words();

void Delete_wrong_space();

};

class successor: public main_class {

public:

successor():main_class(){}

void Copy_to_file();

};

int main (){

successor problem;

problem.Quantity_of_chars();

problem.Number_of_space();

problem.Number_of_words();

problem.Delete_wrong_space();

problem.Copy_to_file();

system("pause");

return 0;

}

main_class::main_class()

{

stream = fopen("Dat.txt", "r+");

}

main_class::~main_class()

{

fclose(stream);

}

void main_class::Quantity_of_chars()

{

Num = 0;

while ((c = getc(stream))!= EOF) {

Num++;

}

printf("Quantity of chars=%i\n", Num);

}

void main_class::Number_of_space()

{

stream = fopen("Dat.txt", "r+");

int i = 0;

while ((c = getc(stream))!= EOF) {

if (c == ' ')

i++;

}

printf("Quantity of space symbols=%i\n", i);

}

void main_class::Number_of_words()

{

stream = fopen("Dat.txt", "r+");

char *Mas = new char[Num];

int i = 0;

while ((c = getc(stream))!= EOF){

Mas[i]=c;

i++;

}

UK=0;

KIL = 0;

for(i=0; i<=Num; i++) {

if((Mas[i] == ' ')||(Mas[i] == '\n'))

UK++;

 

if(((Mas[i]!= ' ')&&(Mas[i]!= '\n')) && (UK >= 1)) {

KIL++;

UK = 0;

}

}

printf("Quantity of words=%i\n", KIL+1);

delete Mas;

}

void main_class::Delete_wrong_space()

{

UK=0;

stream = freopen("Dat.txt", "r+",stream);

char *Mas = new char[Num];

int i = 0;

while ((c = getc(stream))!= EOF){

if(c== ' '){

UK++;

}else{

Mas[i]=c;

UK=0;

 

}

if((c == ' ')&&(UK==1)){

Mas[i]=c;

}

if((c== ' ')&&(UK >1)){

i--;

}

 

i++;

}

UK=i;

printf("\n");

for(i=0; i<UK; i++){

printf("%c",Mas[i]);

}

printf("\n");

}

void successor::Copy_to_file(){

int pos=0,kil=0;

printf("\nInput position and number of symbols\n ");

scanf("%i %i",&pos,&kil);

char c;

int i=0,j=0;

FILE *stream2;

stream = freopen("Dat.txt","r+",stream);

stream2 = fopen("Dat2.txt", "w");

while ((c = getc(stream))!= EOF) {

i++;

if((i>=pos)&&(j<kil)){

putc(c,stream2);

j++;

}

}

}

Тестування:

Для перевірки правильності роботи програми створимо файл такого виду:

Aaa bb ccccc

Ffff

Ggggggg

 

Перевіримо, який результат видасть програма:

Quantity of chars=32

Quantity of space symbols=8

Quantity of words=5

Aaa bb ccccc

Ffff

Ggggggg

Input position and number of symbols

7 2

Press any key to continue...

 

Зміст файлу Dat2.txt буде наступним:

bb

Контрольні запитання

1. У чому полягає просте спадкування?

2. У чому полягає множинне спадкування?

3. Захищені базового члени класу.

4. Захищені похідного члени класу

5. Правила доступу до базових класів відносно похідних класів.

6. Вимоги до конструкторів базового та похідних класів.

7. Вимоги до деструктора базового та похідних класів.

8. Умови спадкування членів базового класу.

9. Умови формування ієрархії класів.

10. Умови спадкування в похідних класах.

 

 

Лабораторна робота №6

Тема: Розробка ієрархії класів з використанням перевантаження операторів та функцій.

Мета: Засвоєння навичок розробки програм з використанням перевантаження функцій.

Порядок виконання роботи

1. Ознайомитися з теоретичними основами розробки програм, що використовують перевантаження операторів та функцій.

2. Розробити ієрархією класів відповідно завдання 1 з використанням перевантаження операторів.

3. Розробити програму, яка використовує ієрархію класів п.2 для роботи з не менш ніж двома об’єктами.

4. Розробити 2-3 тести для перевірки правильності роботи розробленої програми.

5. Оформити звіт до лабораторної роботи.

Завдання 1

Примітка: у всіх класах повинне бути хоча б одне поле, пам'ять під яке виділяється динамічно.

Варіант 1.

Описати базовий клас РЯДОК.

Обов'язкові поля класу:

- покажчик на char — зберігає адресу динамічно виділеної пам'яті для розміщення символів рядка;

- значення типу int — зберігає довжину рядка в байтах.

Обов'язкові методи повинні виконувати наступні дії:

- конструктор без параметрів;

- конструктор, що приймає як параметр Сі-рядок (закінчується нульовим байтом);

- конструктор, що приймає як параметр символ;

- конструктор копіювання;

- одержання довжини рядка;

- очищення рядка (зробити рядок порожнім);

- деструктор.

Описати похідний від РЯДОК клас РЯДОК_ІДЕНТИФІКАТОР.

Рядки даного класу будуються за правилами запису ідентифікаторів у мові С і можуть містити в собі тільки ті символи, що можуть входити до складу З-ідентифікаторів. Якщо вихідні дані суперечать правилам запису ідентифікатора, то створюється порожній РЯДОК_ІДЕНТИФІКАТОР.

Обов'язкові методи:

- конструктор без параметрів;

- конструктор, що приймає як параметр Сі-рядок (закінчується нульовим байтом);

- конструктор, що приймає як параметр символ;

- конструктор копіювання;

- переведення усіх символів рядка у верхній регістр;

- переведення усіх символів рядка в нижній регістр;

- пошук першого входження символу в рядок;

- деструктор.

Перевизначити наступні операції:

- присвоювання (=);

- додавання (+) — операція конкатенації рядків;

- віднімання (–) — з рядка (перший операнд) видаляються всі символи, що входять у рядок — другий операнд, при цьому може вийти порожній рядок;

- оператор > — перевірка на більше. Рядок вважається більше іншого, якщо код символу першого рядка в i-й позиції (i змінюється від 0 до n–1, де n — довжина більш короткого рядка) більше коду символу в тій же позиції в другому рядку, довжини рядків можуть не збігатися.

- оператор < — перевірка на менше. Рядок вважається менше іншого, якщо код символу першого рядка в i-й позиції (i змінюється від 0 до n–1, де n — довжина більш короткого рядка) менше коду символу в тій же позиції коду символу в тій же позиції в другому рядку, довжини рядків можуть не збігатися.

Розроблювач вправі вводити кожне (з обґрунтуванням необхідності) число додаткових полів і методів.

Написати тестову програму, яка:

- динамічно виділяє масив покажчиків на базовий клас (4–6);

- в режимі діалогу заповнює цей масив покажчиками на похідні класи, при цьому екземпляри похідних класів створюються динамічно із завданням початкових значень;

- для створених екземплярів похідних класів виконує перевірку всіх розроблених методів з виведенням вихідних даних і результатів на дисплей.

- для конструкторів копіювання кожного класу передбачити діагностичний друк кількості його викликів у визначене місце дисплея (рекомендується використовувати статичні члени класу).

Режим діалогу забезпечується за допомогою ієрархічного меню.

Варіант 2.

Описати базовий клас РЯДОК.

Обов'язкові поля класу:

- покажчик на char — зберігає адресу динамічно виділеної пам'яті для розміщення символів рядка;

- значення типу int — зберігає довжину рядка в байтах.

Обов'язкові методи повинні виконувати наступні дії:

- конструктор без параметрів;

- конструктор, що приймає як параметр Сі-рядок (закінчується нульовим байтом);

- конструктор, що приймає як параметр символ;

- конструктор копіювання;

- одержання довжини рядка;

- очищення рядка (зробити рядок порожнім);

- деструктор.

Описати похідний від РЯДОК клас БІТОВИЙ_РЯДОК.

Рядки даного класу можуть містити тільки символи '0' чи '1'. Якщо в складі ініціалізуючого рядка будуть зустрінуті будь-які символи, відмінні від припустимих, БІТОВИЙ_РЯДОК приймає нульове значення. Вміст даних рядків розглядається як двійкове число.

Від’ємні числа зберігаються в додатковому коді.

Обов'язкові методи:

- конструктор без параметрів;

- конструктор, що приймає як параметр Сі-рядок (закінчується нульовим байтом);

- конструктор копіювання;

- деструктор;

- зміна знаку на протилежний (переведення числа в додатковий код).

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

- присвоювання (=);

- додавання (+) — арифметична сума рядків;

- операція (==) — перевірка на рівність.

Розроблювач вправі вводити кожне (з обґрунтуванням необхідності) число додаткових полів і методів.

Написати тестову програму, яка:

- динамічно виділяє масив покажчиків на базовий клас (4–6);

- в режимі діалогу заповнює цей масив покажчиками на похідні класи, при цьому екземпляри похідних класів створюються динамічно з завданням початкових значень;

- для створених екземплярів похідних класів виконує перевірку всіх розроблених методів з виводом вихідних даних і результатів на дисплей.

Для конструкторів копіювання кожного класу передбачити діагностичну печатку кількості його викликів у визначене місце дисплею (рекомендується використовувати статичні члени класу).

Режим діалогу забезпечується за допомогою ієрархічного меню.

Варіант 3.

Описати базовий клас РЯДОК.

Обов'язкові поля класу:

- покажчик на char — зберігає адресу динамічно виділеної пам'яті для розміщення символів рядка;

- значення типу int — зберігає довжину рядка в байтах.

Обов'язкові методи повинні виконувати наступні дії:

- конструктор без параметрів;

- конструктор, що приймає як параметр Сі-рядок (закінчується нульовим байтом);

- конструктор, що приймає як параметр символ;

- конструктор копіювання;

- одержання довжини рядка;

- очищення рядка (зробити рядок порожнім);

- деструктор.

Описати похідний від РЯДОК клас ДЕСЯТКОВИЙ_РЯДОК.

Рядки даного класу можуть містити тільки символи десяткових цифр і символи – і +, що задають знак числа. Символи – чи + можуть знаходитися тільки в першій позиції числа, причому символ + може бути відсутнім, у цьому випадку число вважається додатнім. Якщо в складі ініціалізуючого рядка будуть зустрінуті будь-які символи, відмінні від припустимих, ДЕСЯТКОВИЙ_РЯДОК приймає нульове значення. Вміст даних рядків розглядається як десяткове число.

Обов'язкові методи:

- конструктор без параметрів;

- конструктор, що приймає як параметр Сі-рядок (закінчується нульовим байтом);

- конструктор копіювання;

- деструктор;

- метод, що визначає, чи можна представити дане число у форматі int;

Перевизначити наступні операції:

- присвоювання (=);

- віднімання (–) — арифметична різниця рядків;

- операція > — перевірка на більше (за значенням);

- операція < — перевірка на менше (за значенням);

Розроблювач вправі вводити кожне (з обґрунтуванням необхідності) число додаткових полів і методів.

Написати тестову програму, яка:

- динамічно виділяє масив покажчиків на базовий клас (4–6);

- в режимі діалогу заповнює цей масив покажчиками на похідні класи, при цьому екземпляри похідних класів створюються динамічно з завданням початкових значень;

- для створених екземплярів похідних класів виконує перевірку всіх розроблених методів з виводом вихідних даних і результатів на дисплей.

Для конструкторів копіювання кожного класу передбачити діагностичну печатку кількості його викликів у визначене місце дисплею (рекомендується використовувати статичні члени класу).

Режим діалогу забезпечується за допомогою ієрархічного меню.

Варіант 4.

Описати базовий клас РЯДОК.

Обов’язкові поля класу:

- покажчик на char — зберігає адресу динамічно виділеної пам’яті для розміщення символів рядка;

- значення типу int — зберігає довжину рядка в байтах.

Обов’язкові методи повинні виконувати наступні дії:

- конструктор без параметрів;

- конструктор, що приймає як параметр Сі-рядок (закінчується нульовим байтом);

- конструктор, що приймає як параметр символ;

- конструктор копіювання;

- одержання довжини рядка;

- очищення рядка (зробити рядок порожнім);

- деструктор.

Похідний від РЯДОК клас КОМПЛЕКСНЕ_ЧИСЛО.

Рядки даного класу складаються з двох полів, розділених символом і.

Перше поле задає значення реальної частини числа, а друге – уявної. Кожне з полів може містити тільки символи десяткових цифр і символи – і +, що задають знак числа. Символи – чи + можуть знаходитися тільки в першій позиції числа, причому символ + може бути відсутнім, у цьому випадку число вважається додатнім. Якщо в складі ініціалізуючого рядка будуть зустрінуті будь-які символи, відмінні від припустимих, КОМПЛЕКСНЕ_ЧИСЛО приймає нульове значення. Приклади рядків: 33i12, –7i100, +5і-21.

Обов’язкові методи:

- конструктор без параметрів;

- конструктор, що приймає як параметр Сі-рядок (закінчується нульовим байтом);

- конструктор копіювання;

- деструктор.

Перевизначити наступні операції:

- присвоювання (=);

- операція (==) — перевірка на рівність;

- множення (*) — множення чисел.

Розроблювач вправі вводити кожне (з обґрунтуванням необхідності) число додаткових полів і методів.

Написати тестову програму, яка:

- динамічно виділяє масив покажчиків на базовий клас (4–6);

- в режимі діалогу заповнює цей масив покажчиками на похідні класи, при цьому екземпляри похідних класів створюються динамічно з завданням початкових значень;

- для створених екземплярів похідних класів виконує перевірку всіх розроблених методів з виводом вихідних даних і результатів на дисплей.

Для конструкторів копіювання кожного класу передбачити діагностичну печатку кількості його викликів у визначене місце дисплея (рекомендується використовувати статичні члени класу).

Режим діалогу забезпечується за допомогою ієрархічного меню.

Варіант 5.

Створити динамічний клас для роботи з рядками. Максимальна довжина послідовності – 254. Перший байт повинен містити інформацію про фактичну кількість елементів масиву. Здійснити перевантаження операцій:

" = "– присвоєння,

" + " – конкатенація (з’єднання) рядків,

" <= " – відношення "менше чи дорівнює",

" >= " – відношення "більше чи дорівнює",

" == " – відношення "дорівнює",

"!= " – відношення "не дорівнює".

" <= " – відношення включення (перевіряється, чи є множина, надана лівим операндом, підмножиною множини, наданої правим),

" == " – еквівалентність множин,

"!= " – нееквівалентність множин,

" << " – належність (перевіряється, чи належить значення, що надане лівим операндом, до множини, що надана правим операндом).

Варіант 6.

Розробити ієрархію класів для роботи з одновимірними динамічними масивами з перевантаженими операторами new[] і delete[], яка містить: два конструктора, деструктор, функцію визначення довжини тексту, функцію визначення кількості рядків в тексті, функцію визначення кількості слів в тексті, функцію визначення кількості пробілів у тексті, функцію видалення зайвих пробілів з тексту.

Варіант 7.

Розробити ієрархію класів для роботи з двовимірними динамічними масивами з перевантаженим оператором інкремента (--) та декремента (++), яка містить: два конструктора, деструктор, функцію визначення довжини тексту, функцію визначення кількості рядків в тексті, функцію визначення кількості слів в тексті, функцію визначення кількості пробілів у тексті, функцію видалення зайвих пробілів з тексту.

Теоретичні відомості

Перевантаження операторів

Як і більшість інших мов, C++ підтримує набір операторів для вбудованих типів. Однак більшість концепцій, для яких звичайно використаються оператори, не є вбудованими типами C++, тому вони повинні бути представлені у вигляді типів, обумовлених користувачем. Наприклад, якщо вам потрібна комплексна арифметика, матрична алгебра, сигнальна логіка або символьні рядки в C++, ви користуєтесь механізмом класів для подання цих понять. Визначення операторів для таких класів іноді дозволяє програмістові реалізувати більш звичну і зручну форму запису для маніпулювання об'єктами, ніж та, котра доступна з використанням тільки базової функціональної форми запису. Наприклад,

class complex { // дуже спрощений клас complex

double re, im; public:

complex {double r, double i) re [r], in (i) {}

complex operator {complex);

complex operator {complex};

};

визначає просту реалізацію концепції комплексного числа. Клас complexпредставлений парою чисел із плаваючою крапкою подвійної точності й двома операторами + і *. Програміст вводить оператори comptex::operator+() і complexv.operator*(), які визначають зміст операцій додавання й множення. Наприклад, якщомають тип complex, b+cозначає b.operator+(c). Тепер ми можемо записати комплексні вирази у формі, близької до загальноприйнятої:

voidf()

{

complex a=complex {1,3.1); complex b=complex {1.2,2);

a = b+c;

b = b+c* a;

с = a*b+complex (1,2);

Виконуються звичайні правила пріоритету операцій, тому друга інструкція означає b=b+{c*a), а не b={b+c)*a.

Найбільш очевидне використання перевантажених операторів - застосування їх до конкретних типів. Однак користь від операторів, обумовлених користувачем, не обмежується тільки конкретними типами. Наприклад, проектування узагальнених і абстрактних інтерфейсів часто приводить до використання операторів, таких як ->, [] і ().

Операторні функції

Можна оголосити функції, що визначають зміст наступних операторів:

+ - * / % ^ &

| ~! = < > +=

- =. *= /= %= Л= &= |=

<< >> >>= «= ==!= <=

>= && || ++ — ->*,

-> [] () newnew[]deletedelete[]

 

Наступні оператори не можуть бути визначені користувачем:

- дозвіл області видимості;

- вибір члена;

- вибір члена через покажчик на член.

Правим операндом у них є не значення, а ім'я, і вони надають основні кошти доступу до членів. Дозвіл їхнього перевантаження привело б до дуже тонких помилок. Тернарний умовний оператор також не може бути перевантажений. Аналогічно не можуть бути перевантажені оператори sizeof і typeid.

Ім’я операторної функції починається із ключового слова operator. Операторна функція оголошується й може бути викликана, як будь-яка інша функція. Використання операторної функції як оператора є просто скороченою формою її явного виклику. Наприклад:

void j[complex a, complex b)

{

complex c = a + b; // скорочена форма

complex d = a.operator+ [b); // явний виклик

}

При наявності попереднього визначення complexобидві інструкції є синонімами.

В С++ є можливість поширення дії стандартних операцій на операнди абстрактних типів даних. Для того, щоб перевизначити одну зі стандартних операцій для роботи з операндами абстрактних типів, програміст повинен написати функцію з ім'ям operator знак, де знак - позначення цієї операції (наприклад, + - | + = і т.д.).

Проте в мові існує декілька обмежень, накладених на перевизначення операторів:
1. Не можна створювати нові символи операцій.

2. Не можна перевизначити операції:::; * (розіменування, а не бінарне множення);?:; sizeof; # #; #.

3.Символи унарної операції не може використовуватися для зміни бінарної операції і навпаки. Наприклад, символ <<можна використовувати тільки для бінарної операції,!- тільки для унарної, а & - і для унарної, і для бінарної.
4. Перевизначення операцій не міняє ні їх пріоритетів, ні порядку їх виконання (зліва направо або справа наліво).

5. При перевантаженні операції комп'ютер не робить ніяких припущень про її властивості. Це означає, що якщо стандартна операція + = може бути виражена через операції + і =, тобто а + = b еквівалентно а = а + b, то для перевизначення операцій у загальному таких співвідношень не існує, хоча, звичайно, програміст може їх забезпечити.

6. Ніяка операція не може бути перевизначена для операндів стандартних типів.
7. Як для унарної, так і для бінарної операції число аргументів функції operator () має точно відповідати числу операндів цієї операції. Причому в перевантаження бінарного оператора прийнято передавати один аргумент, тому що другий - неявний. Його має будь-яка функція - член класу, той самий покажчик this - покажчик на об'єкт, для якого викликаний метод. Таким чином, в перевизначенні унарного оператора не слід передавати нічого.
Примітка: Зручно передавати значення параметрів у функцію operator () не за значенням, а по посиланню.

Приклад:

Перевантаження чотирьох операторів + - * % на прикладі чисел

Лістинг програми

#include <iostream>

usingnamespace std;

class Digit{

private:

int dig; // число

public:

Digit(){

dig=0;

}

Digit(int iDig){

dig=iDig;

}

void Show(){

cout<<dig<<"\n"; }

//перевантажуємо чотири оператора

//зверніть увагу, усі оператори бінарні, тому ми передаємо в них один параметр - це операнд, який буде знаходитися праворуч від оператора у виразі

//лівий операнд передається за допомогою this

 

Digit operator+(const Digit &N)

{

Digit temp;

temp.dig=dig+N.dig;

return temp;

}

Digit operator-(const Digit &N)

{

Digit temp;

temp.dig=dig-N.dig;

return temp;

}

Digit operator*(const Digit &N)

{

Digit temp;

temp.dig=dig*N.dig;

return temp;

}

Digit Digit::operator%(const Digit &N)

{

Digit temp;

temp.dig=dig%N.dig;

return temp;

}

};

int main()

{

// перевіряємо роботу операторів

Digit A(8),B(3);

Digit C;

 

cout<<"\Digit A:\n";

A.Show();

 

cout<<"\Digit B:\n";

B.Show();

 

cout<<"\noperator+:\n";

C=A+B;

C.Show();

 

cout<<"\noperator-:\n";

C=A-B;

C.Show();

 

cout<<"\noperator*:\n";

C=A*B;

C.Show();

 

cout<<"\noperator%:\n";

C=A%B;

C.Show();

system ("pause");

}

 

На відміну від бінарних і унарних операторів, оператор виклику функції може приймати будь-яку кількість аргументів (від 0 і більше), іншими словами кількість параметрів функції обмежується тільки здоровим глуздом.

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

Розглянемо приклад перевантаження оператора виклику функції.

Лістинг програми

# include<iostream>

usingnamespace std;

class MyPoint{

int X;

int Y;

public:

MyPoint(){

X=0;

Y=0;

}

 

// перевантажений оператор ()

voidoperator()(int x,int y){

X=x;

Y=y;

}

void Show(){

cout<<X<<" "<<Y<<"\n\n";

}

};

int main(){

MyPoint P;

P.Show();

 

//зміна значень полів обєкта

P(2,3);

P.Show();

system("pause");

}

 

Перевантаження оператора + на прикладі класу “СТРОКА”

Лістинг програми

#include<iostream>

#include<string.h>

 

usingnamespace std;

 

class string_

{

private:

// стрічка

char* S;

 

// довжина стрічки

int len;

public:

// Конструктор за замовчуванням без параметрів

string_();

 

// Перевантажений конструктор з параметром

string_(char* s);

 

// Конструктор копіювання

string_(const string_& s);

 

 

// Деструктор

~string_(){

delete [] S;

}

 

// Метод сортування

void Sort(string_ s[], int n);

 

// Константний метод що повертає вміст строки

constchar*GetStr()const

{

return S;

}

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

void SetStr()

{

// якщо стрічка не порожня - очистити

if(S!=NULL)

delete[]S;

 

// створюємо массив і запитуємо у користувача дані

char a[256];

cin.getline(a,256);

 

// прораховуємо розмір

len=strlen(a)+1;

 

// виділяємо пам’ять

S = newchar[len];

 

// переписуємо в об’єкт введену стрічку

strcpy(S,a);

}

 

// Перевантаження бінарного оператора

// Перший параметр передається неявно за допомогою покажчика this

// функція реалізує зчеплення стрічок

string_ operator+(const string_&);

 

// Перевантаження бінарного оператора

// Перший параметр передається неявно за допомогою покажчика this

//Функція реалізує коректне присвоєння обєктів один одному в ситуації обєкт1=обєкт2. Нагадую, ця ситуація являється четвертим випадком побітового копіювання, при якому конструктор копіювання - безсилий.

string_&operator=(const string_&);

 

// Перевантаження типу

// Функція реалізує перетворення обєкта класу до типу char*

operatorchar*() { return S; }

};

 

string_::string_()

{

// Початкова ініціалізація

S = NULL;

len = 0;

}

 

string_::string_(char* sVar)

{

len = strlen(sVar);

S = newchar[len + 1];

// Ініціалізація стрічкою, переданої користувачем

strcpy(S, sVar);

}

 

string_::string_(const string_& sVar)

{

len = sVar.len;

// Безпечне копіювання

S = newchar[len + 1];

strcpy(S, sVar.S);

}

 

void string_::Sort(string_ s[], int n)

{

// Сортування стрічок методом бульбашки

 

string_ temp;

 

for(int i=0;i<n-1;i++)

{

for(int j=n-1;j>i;j--)

{

// порівняння двох стрічок

if(strcmp(s[j].S,s[j-1].S)<0)

{

//запис стрічки s[j] в temp

temp=s[j];

 

// запис стрічки s[j-1] в s[j]

s[j]=s[j-1];

 

// запис стрічки temp в s[j-1]

s[j-1]=temp;

}

}

}

}

 

// Функція зчеплення стрічок (перевантажений бінарний плюс)

string_ string_::operator+(const string_ &str)

{

// створення тимчасового обєкта

string_ sVar;

 

// вираховуємо нову довжину стрічки

sVar.len = len + str.len;

 

// Виділяємо пам’ять під нову стрічку

sVar.S = newchar[s.len + 1];

 

// Ініціалізація першої частини стрічки

strcpy(sVar.S, S);

 

//Ініціалізація другої частини стрічки

strcat(sVar.S, str.S);

 

// Повернення нового обєкта

return sVar;

}

 

// Функція, що реалізує безпечне витягування

string_& string_::operator=(const string_ &str)

{

// Передбачення варіанта STRING = STRING; (присвоєння самому собі),де STRING змінна класу string

if(this == &str)

return *this;

 

// якщо розміри стрічок не співпадають, або стірчка, в яку відбувається запис несформована

if(len!= str.len || len == 0)

{

// видалення старої стрічки

delete [] S;

// вирахування нової довжини стрічки

len = str.len;

// виділення пам’яті під нову стрічку

S = newchar[len + 1];

}

 

// ініціалізація стрічки

strcpy(S, str.S);

 

// повернення посилання на "самого себе"

// Завдяки цьому можливе багатократне присвоєння обєктів один одному, наприклад, string_ a, b, c; a = b = c;

return *this;

}

 

int main()

{

int n,i;

 

// Вводимo кількість стрічок

cout<<"Input the number of string s:\t";

cin>> n;

 

if(n < 0)

{

cout<<"Error number:\t"<< n << endl;

return 0;

}

 

// Забираємо з потока символ Enter ("\n")

char c[2];

cin.getline(c, 2);

 

// Створюємо массив з n стрічок

string_ *s = new string_[n];

 

// Введення стрічок з клавіатури

for(i = 0; i < n; i++)

s[i].SetStr();

 

// Сортування стрічок

// Виклик через покажчик,так як функція працює для групи обєктів, а не для одного конкретного

s->Sort(s, n);

 

// Вивід відсортованих стрічок

for(i = 0; i < n; i++)

cout<<"\n"<<s[i].GetStr()<<"\n";

 

// Видалення масива стрічок

delete [] s;

 

cout<<"\n\n+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n\n";

 

//Перевіряємо на практиці оператор + і перетворення

 

string_ A,B,C,RES;

 

A="Ivanov ";

B="Ivan ";

C="Ivanovich";

RES=A+B+C;

cout<<RES.GetStr()<<"\n\n";

system("pause");

}



Поделиться:


Последнее изменение этой страницы: 2016-04-18; просмотров: 702; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 18.220.97.161 (0.011 с.)