p align="left">cout << … << …; Операція введення (8) реалізована на основі динамічного алгоритму: виділяється буфер, якщо не вистачає, то виділяється у два рази більший (у нього копіюється попередній і звільняється) і т.д. Замість множення на 2 використовуюємо швидшу операцію зсуву. Це дозволяє максимально збалансувати швидкість виконання та використання ресурсів. Об'ява нащадку TPStrCompare від TPString має наступний вигляд: class TPStrCompare abstract: virtual public TPString {···} У ньому ми перевантажимо всі операції порівняння: |
(1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) (15) (16) (17) (18) (19) (20) (21) (22) (23) (24) (25) (26) (27) (28) (29) | bool TPStrCompare:: operator! () const { if (len==0) return true; else return false; } bool TPStrCompare:: operator! = (const TPStrCompare& part) const { return (strcmp (symb,part. symb) ! =0); } bool TPStrCompare:: operator== (const TPStrCompare& part) const { return! (*this! = part); } bool TPStrCompare:: operator< (const TPStrCompare& part) const { return strcmp (symb,part. symb) <0; } bool TPStrCompare:: operator> (const TPStrCompare& part) const { return (strcmp (symb,part. symb) >0); } bool TPStrCompare:: operator<= (const TPStrCompare& part) const { return! (*this> part); } bool TPStrCompare:: operator>= (const TPStrCompare& part) const { return! (*this< part); } | | |
У рядках (1), (6), (10), (14), (16), (18), (22), (26) об'являються оператори порівнняння. Кожен з них є константною функцією та приймає константні аргументи, що гарантує захищеність, та щожливість використання, коли об'єкт був об'явлений константно. У рядках (16) та (20) викорисовубться функіії порівняння у стилі С. Останні функції порівняння (крім (1)) створювалися на основі заданих. Розробка результуючого класу пов'язана з успадкуванням від двох абстрактних. Має наступну об'яву: class clsString: public TPStrThread, public TPStrCompare { ··· } Зауважимо, що базові класи не є віртуальними і немає наслідування від базового класу (як це зазначено у теоретичній частині). Виклики конструкторів будуть проходити так: Конструктор за замовчуванням TPString Конструктор за замовчуванням TPStrThread або TPStrCompare Конструктор за замовчуванням TPStrCompare або TPStrThread Конструктор clsString Пункти 2 і 3 рівносильні і їх порядок залежить від компілятору (хоча в стандарті сказано, що вони викликаються в порядку об'яви). В звязку з тим, що конструктори та операції присвоєння не наслідубться потрібно їх створювати зоново. Конструктори копіювання та перетворення аналогічні TPString. Розглянемо добавлені конструктори. |
(1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) (15) (16) (17) (18) (19) | clsString:: clsString (const long l) { char s [_CVTBUFSIZE]; if (_i64toa_s (l,s,15,10) ==EINVAL) code=1; else code=0; len=strlen (s); BuffLen=0; symb=NULL; setString (s); } clsString:: clsString (const double d, int pers) { char buf [_CVTBUFSIZE]; if (_gcvt (d,pers,buf) ! =0) code=1; else code=0; len=strlen (buf); BuffLen=0; symb=NULL; setString (buf); } | | |
У рядках (1) та (11) також об'явлені конструктори перетворення. Цікавим є виділення пам'яті для тимчасового буферу, використовуючи _CVTBUFSIZE. Згідно документації вона забезпечує саме той розмір, який необхідно для розміщення будь-якого число у строковому форматі, не залежно від системи (3) та (13). Функція i64toa_s (4) забезпечує перетворення 64 бітного цілого на строку і у разі помилки повертає EINVAL. Функція _gcvt (14) перетворює дійсне число у рідок символів і у разі помилки повертає її значення. (6) - (9) та (15) - (18) аналогічні розлянутим раніше. Оператор () повертає підстроку але за типом класу: |
(1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) | clsString& clsString:: operator () (int index, int subLen) index+subLen>=len) return clsString (""); char *tempstr=new char [subLen+1]; if (subLen==0) subLen=len-index; strncpy (tempstr,symb+index,subLen); tempstr [subLen] ='\0'; clsString temp (tempstr); delete [] tempstr; return temp; | | |
У (3) забзпечення коректності роботи алгоритму. (4) виділення тимчасовогу буферу. У рядку (6) - копіювання підрядка, котрий у (8) передається у якості аргументу. Далі (9) знищення тимчасового буферу та (10) повертання результату. Функція пошуку першого входження реалізована за надійним але не найшвидшим алгоритмом О (n) =n*m, n-довжина базового рядка, а m-довжина рядка еквівалент якого шукаємо. |
(1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11) (12) (13) (14) (15) | int clsString:: find (const clsString& comp, int pos) { bool Notequal=1; if (comp. len>pos+this->len) return - 1; int fin=this->len-comp. len; for (; (pos<=fin) &&Notequal; pos++) { int k=0; for (int j=pos; k<comp. len; k++,j++) if (this->symb [j] ! =comp. symb [k]) break; if (k==comp. len) Notequal=0; } if (Notequal) return - 1; else return pos; } | | |
Флагова змінна Notequal (3) слугує для визначення: чи було знайдене вхождения. Змінна fin (5) вказує на кількість символім починаючи з яких необхідно виконати порівняння. (10) вийти з вложенного циклу, якщо знайдені неодинакові символи. 2.3 ТестуванняРезультат проведення тестування: |
(Т1) (Т2) (Т3) (Т4) (Т5) (Т6) (Т7) (Т8) (Т9) (Т10) (Т11) (Т12) (Т13) (Т14) (Т15) (Т16) (Т17) (Т18) (Т19) (Т20) (Т21) (Т22) (Т23) (Т24) (Т25) (Т26) (Т27) (Т28) (Т29) (Т30) (Т31) (Т32) (Т33) (Т34) (Т35) (Т36) (Т37) (Т38) (Т39) | This program will test my work This is a small driver Testing in process This is a small driver Enter string Enter string Good day! This is a very good day! I have already done my work! Good day! This is a very good day! I have already done my work! s1 is "Testing in process" and s2 is "This is a small driver" The results of comparing is: s2==s1 yields false s2! =s1 yields true s2>s1 yields true s2<s1 yields false s2<=s1 yields false s2>=s1 yields true s1 += s2 yields s1 = Testing in processThis is a small driver s1 after s1 [0] = 't' and s1 [1] ='E' tEsting in processThis is a small driver find and delete in s1 s2 tEsting in process ********************************************************** s1 is "112211221122" and s2 is "334433443344334"Insert to s1 5 symbols from s2. Start position 0: 33443112211221122 Insert to s1 5 symbols from s2. Start position 5: 11221334431221122 Insert to s1 5 symbols from s2. Start position end of s1: 11221122112233443 2007 12.3456789012 Для продолжения нажмите любую клавишу... | | |
Тестування об'яви змінних, тобто конструкторів: |
(1) (2) (3) (4) (5) (6) (7) | clsString* temp=new clsString ("This program will test my work"); cout <<*temp<<endl; *temp= (clsString)"This is a small driver"; clsString test1 ("Testing in process"); clsString test2; clsString test3 (*temp); cout<<*temp<<endl<<test1<<endl<<test2<<endl<<test3; | | |
Создамо динамічний об'єкт (1) присвоївши значення "This program will test my work". Буде викликаний конструктор преведення типів. Перевіримо отримане значення (2), вивівши його в потік (чим і почнемо тестуваня введення/виведення). Далі виконаємо явне приведення типів (3), а також перевіримо оператор присвоєння. Крім того в покроковому режимі перевіримо роботу деструктора. Варіант створення статичної змінної (4) з початковим значенням, а із значенням за замовчуванням (5). Створення об'єкту на основі конструктора копіювання у рядку (6). Створені об'єкти у рядках (3) - (6) виведемо в потік (7). Результати роботи рядкі (1) - (7) є рядки на єкрані (Т1) - (Т5). Далі протестуємо оператор введення. |
(1) (2) (3) (4) (5) (6) | cout<<"\nEnter string"<<endl; cin>>test2; cout<<test2<<endl; cout<<"Enter string"<<endl; cin>>test2; cout<<test2<<endl; | | |
У рядках (1) та (3) попросимо ввести рядок символів, що закінчується оператором переходу на новий рядок. Далі (2) та (4) вводимо ці рядки, та відразу ж показуємо введене. Має сенс ввести порожню строку, а потім непорожню. Результати у рядках (6) - (11).
Страницы: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
|