Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП_KAZYMYR.doc
Скачиваний:
14
Добавлен:
09.11.2019
Размер:
3.71 Mб
Скачать

5.1.3.Маніпулятори

Це спеціальні функції для модифікації формату, які можна включати в оператори введення й виведення.

Нижче наведені найбільше часто використовувані маніпулятори:

  • setw(int) – аналогічно width(int);

  • setfill(int) – установлює символ-заповнювач;

  • ws – ігнорувати пробіли при введенні;

  • endl – вставка символу наприкінці рядка;

  • dec – виведення в десятичному форматі;

  • oct – виведення в восьмеричному форматі;

  • hex – виведення в шістнадцятерічному форматі;

  • flush – при виведенні вивантажує буфер.

Приклад використання маніпуляторів:

cout << setw(4) << i << setw(6) << j;

Це рівносильно:

cout.width(4);

cout << i;

cout.width(6);

cout << j;

Для використання маніпуляторів необхідно підключити до програми заголовочний файл <iomanip.h>.

5.1.4.Введення/виведення у файл

Відкриття файлу на введення/виведення здійснюється шляхом використання наступної конструкції:

fstream <ім'я об'єкта> (<шлях до файлу>, <список прапорів >);

Наприклад, це може виглядати так:

fstream inout ('c:\My\data.bat', ios::in | ios:out);

Прапори визначені в класі ios:

class ios {public:

enum open_mode {

in, // прапор введення

out, // прапор виведення

app, // додавання даних у кінець файлу

nocreate, //видається помилка, якщо файл не існує

noreplace // помилка, якщо не встановлений прапор app

};

};

Після відкриття файлу запис і зчитування відбувається за допомогою перевизначених операцій << і >>:

fstream inout(“c:\My\data”, ios::in|ios::out);

inout << i;

inout >> j;

Крім форматованого введення/виведення існують функції неформатованого введення/виведення:

put(char);

write(const unsigned char* ptr, int n);

Дані функції дозволяють вивести один символ і вивести n символів, відповідно:

cout.put('a'); // буде виведене “a”

cout.write(“Hello”,3); // буде виведене “Hel”

5.2.Контейнерні класи

Класи, які містять покажчики або об'єкти, що містять покажчики, називаються контейнерними. До них відносяться класи, які використовуються для побудови списків, стеків, черг, масивів, словників. Такі класи приховують подробиці об'єктів, що включають, і забезпечують зручні зовнішні способи реалізації операцій обробки перерахованих структур. У свою чергу, реалізація операцій з об'єктами контейнерних класів ґрунтується на можливості одержання доступу до їхніх окремих елементів. Одним зі шляхів вирішення цього завдання є створення спеціального класу, задача якого полягає у звертанні до елементів екземпляра контейнерного класу. Цей спеціальний клас повинен виконувати ітерації над елементами іншого класу.

5.2.1.Ітератори

Стандартним прийомом реалізації ітерації є використання оператора for:

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

sum+=a[i]; // підсумовування елементів

Масив, що використовує даний цикл, може бути описаний так:

class vect {

private:

int *p; // базовий покажчик

int size; // розмір масиву

int cur_ind; // поточний індекс

public:

vect (int); // конструктор

int & next(); // звертання до наступного елемента

} &а;

vect::vect(int n): cur_ind(0){

size = n;

p = new int[size];

}

int & vect :: next (){

if (cur_ind = = size)

return(p[cur_ind = 0]); //скидання індексу й повернення до 1-му елемента

esle

return(p[cur_ind ++]); // повернення елемента й збільшення індексу

}

void main (){

for (i = 0; i <= (size-1);++ i)

sum += a.next();

}

У даному прикладі індекс i вже розв'язаний зі зверненням до елемента, проте, побічно використовується індекс cur_ind класу vect. Це означає, що звертання до масиву обмежується використанням одного індексу (одного екземпляра вектора) під час різних обігів. Такий порядок аналогічний, наприклад, відвідуванню великого музею тільки одним екскурсантом.

У той же час об'єкт класу vect постійно існує в пам'яті й повинен бути здатний обслужити безліч звертань до нього. . Один зі способів забезпечити це - продублювати масив для кожного завдання, що вимагає звертання до елементів масиву (аналогічно тому. що дати кожному екскурсантові по музею). Інший шлях - створити безліч індексів і передавати їхнім функціям обігу, але це веде до різкого збільшення невиробничих витрат.

Оптимальне рішення складається в створенні окремого, пов'язаного з вихідним класом vect, класа-ітератора, у функції, якого буде входити стандартне звертання до елементів масиву. Із цією метою змінимо визначення класу vect:

class vect {

private:

friend class vect_iterator;

int *p;

public:

…………………

};

class vect_iterator {

private:

vect *pv; // зв'язаний об'єкт vect

int cur_ind; // поточний індекс

public:

vect_iterator (vect & v): cur_ind (0); {}

int & next();

};

int & vectiterator :: next (){

if (cur_ind = = pv > size)

return(pv > p [cur_ind = 0]);

esle

return(pv > p [cur_ind ++]);

}

Тепер у наявності повне від'єднання звертання до елемента від контейнерного екземпляра vect, і можна оголосити як завгодно багато ітераторів для всіх необхідних обчислень (оголошення ітератора рівносильне видачі дозволу ще одному екскурсантові відвідати музей, не залежно від того, скільки там людей уже перебуває).

Таким чином, використання контейнерних класів сполучено із застосуванням спеціальних класів-ітераторів.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]