Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
+ООП_Навч_посібник.doc
Скачиваний:
8
Добавлен:
01.07.2025
Размер:
6.58 Mб
Скачать

9.4.1. Перерахунки – списки іменованих цілочисельних констант

У мові програмування C++ можна визначити список іменованих цілочисельних констант. Такий список називається перерахунком (enumeration). Ці константи можна потім використовувати скрізь, де допускаються цілочисельні значення (наприклад, в цілочисельних виразах). Перерахунки визначаються за допомогою ключового слова enum, а формат їх визначення має такий вигляд:

enum type_name { список_перерахунку } список_змінних;

Під елементом список_перерахунку розуміють список розділених між собою комами імен, які представляють значення перерахунку. Елемент список_змінних є необов'язковим, оскільки змінні можна оголосити пізніше, використовуючи ім'я типу перерахунку. У наведеному нижче прикладі визначається перерахунок apple і дві змінні типу apple з іменами red і yellow:

enum apple {Jonathan Golden_Del, Red_Del, Winesap,

Cortland, McIntosh} red, yellow;

Визначивши перерахунок, можна оголосити інші змінні цього типу, використовуючи ім'я перерахунку. Наприклад, за допомогою такої настанови оголошується одна змінна fruit перерахунку apple:

apple fruit;

Цю настанову можна записати і так:

enum apple fruit;

Ключове слово enum оголошує перерахунок.

Проте використання ключового слова enum тут є зайвим. У мові програмування С (яка також підтримує перерахунки) обов'язковою була друга форма, тому в деяких програмах Ви можете натрапити на подібний запис.

З урахуванням попередніх оголошень наведені нижче типи настанов абсолютно допускаються:

fruit = Winesap;

if(fruit==Red_Del) cout << "Red Delicious\n";

Важливо розуміти, що кожен символ перерахунку означає ціле число, причому кожне наступне число (представлене ідентифікатором) є на одиницю більшим від попереднього. За замовчуванням значення першого символу перерахунку дорівнює нулю, отже, значення другого – одиниці і т.д. Тому у процесі виконання цієї настанови

cout << Jonathan << " " << Cortland;

на екран буде виведено числа 0 4.

Хоча перерахункові константи автоматично перетворяться в цілочисельні, зворотне перетворення автоматично не виконується. Наприклад, така настанова є некоректною

fruit = 1; // помилка

Ця настанова спричинить під час компілювання помилку, оскільки автоматичного перетворення цілочисельних значень в значення типу apple не існує. Відкоректувати попередню настанову можна за допомогою операції приведення типів:

fruit = (apple) 1; // Тепер все гаразд, але стиль не досконалий.

Тепер змінна fruit міститиме значення Golden_Del, оскільки ця apple-константа зв'язується із значенням 1. Як зазначено в коментарі, хоча ця настанова стала коректною, її стиль написання надто недосконалий, тобто його можна вибачити тільки за виняткових обставин.

Використовуючи ініціалізацію, можна вказати значення однієї або декількох перерахункових констант. Це робиться так: після відповідного елемента перерахунку ставиться знак рівності і потрібне ціле число. Під час використання ініціалізації наступному (після того, що ініціалізувало) елементу перерахунку присвоюється значення, що на одиницю перевищує попереднє значення ініціалізації. Наприклад, у процесі виконання такої настанови константі Winesap присвоюється значення 10:

enum apple {Jonathan Golden_Del, Red_Del, Winesap=10, Cortland, McIntosh};

Тепер всі символи перерахунку apple мають такі значення:

Jonathan

0

Golden_Del

1

Red_Del

2

Winesap

10

Cortland

11

McIntosh

12

Часто відносно перерахунків помилково вважають, що символи перерахунку можна вводити і виводити як рядки. Наприклад, такий фрагмент коду програми виконаний не буде:

// Слово "McIntosh" на екран таким чином не потрапить.

fruit = McIntosh;

cout << fruit;

Не забувайте, що символ McIntosh – це просто ім'я для певного цілочисельного значення, а не рядок. Отже, у процесі виконання попереднього коду програми на екрані відобразиться числове значення константи McIntosh, а не рядок "McIntosh". Звичайно, можна створити код введення та виведення символів перерахунку у вигляді рядків, але він виходить дещо громіздким. Ось, наприклад, як можна відобразити на екрані назви сортів яблук, пов'язаних із змінною fruit:

switch(fruit) {

case Jonathan : cout << "Jonathan";

break;

case Golden_Del: cout << "Golden Delicious";

break;

case Red_Del : cout << "Red Delicious";

break;

case Winesap : cout << "Winesap";

break;

case Cortland : cout << "Cortland";

break;

case McIntosh: cout << "McIntosh";

break;

}

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

Код програми 9.11. Демонстрація перекладу значення перерахунку у відповідний рядок

#include <vcl>

#include <iostream> // Для потокового введення-виведення

#include <conio> // Для консольного режиму роботи

using namespace std; // Використання стандартного простору імен

enum apple {Jonathan, Golden_Del, Red_Del, Winesap,

Cortland, McIntosh};

// Масив рядків, пов'язаних з перерахунком apple.

char name[][20] = {

"Jonathan",

"Golden Delicious",

"Red Delicious",

"Winesap",

"Cortland",

"McIntosh"

};

int main()

{

apple fruit;

fruit = Jonathan;

cout << name[fruit] << "\n";

fruit = Winesap;

cout << name[fruit] << "\n";

fruit = McIntosh;

cout << name[fruit] << "\n";

getch(); return 0;

}

Результати виконання цієї програми є такими:

Jonathan

Winesap

McIntosh

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

Через те, що значення перерахунку необхідно вручну перетворювати в зручні для сприйняття людиною рядки, то вони, в основному, використовуються там, де таке перетворення не потрібне. Для прикладу розгляньте перерахунок, що використовують для визначення таблиці символів компілятора.