
Перерахування.
Структури можна розглядати як новий тип даних, визначуваний користувачем. Існує ще один спосіб створення призначених для користувача типів даних, званий перерахуванням. Перерахування відносяться до типових засобів програмування в стилі C++, і їх використання може помітно спростити процес створення програми.
Перерахування використовуються в тих випадках, коли змінні створюваного типу можуть приймати заздалегідь відому кінцеву (і, як правило, невелику) безліч значень.
Приклад 6. dayenum.срр Дні тижня - застосування перерахувань.
В даному прикладі перерахування використовуються для створення типу даних, що зберігає дні тижня.
#include <iostream.h>
// оголошення перераховуваного типу
enum days_of_week { Sun, Mon, Tue, Wed, Thu, Fri, Sat };
Int main()
{
days_of_week day1, day2; // визначення змінних, що зберігають дні тижня
day1 = Mon; // ініціалізація змінних
day2 = Thu;
int diff = day2 - day1; // арифметична операція
cout << "Різниця в днях: " << diff << endl;
if( day1 < day2) // порівняння
cout << "day1 наступить раніше, ніж day2\n";
return 0;
}
Оголошення типу починається із слова enum і містить перерахування всіх можливих значень змінних створюваного типу. Ці значення називаються константами перераховуваного типу.
Змінним перераховуваного типу можна привласнювати будь-яке із значень, вказаних при оголошенні типу.
Внутрішньо перераховуванні типи даних представляються і обробляються як цілі числа. Цей факт пояснює можливість застосування до змінних перераховуваного типу арифметичних операцій і операцій відношення.
Фактично перше значення в списку розглядається як число 0, друге - як число 1, і т.д. В наший програмі значення від Sun до Sat є цілими числами в діапазоні 0...6.
Відмінність між типом int і перераховуваними типами:
Перерахування - це список всіх можливих значень.
Тип int задається за допомогою діапазону значень.
Приклад 7. wdcount.срр // підрахунок числа слів в реченні з використанням перерахувань.
Програма підраховує кількість слів в реченні, яке вводиться з клавіатури користувачем.
#include <iostream.h>
#include <conio.h> // для getche()
enum Word { NO, YES }; // NO=0, YES=1
Int main()
{
Word word1 = NO; // word1 дорівнює YES, коли вводиться слово, і NO, коли вводяться пропуски
char ch='a'; // прочитування символу з клавіатури
int wordcount = 0; // число слів
do {
ch = getche(); // введення символу
if( ch==' ' || ch=='\r' ) // якщо введений пропуск
{
if( word1 == YES ) // а до цього вводилося слово,
{ // значить, слово закінчилося
wordcount++; // підрахунок слова
word1 = NO; // скидання прапора
}
} // інакше
else // введення слова продовжується
if ( word1 == NO ) // якщо почалося введення слова
word1 = YES; // те встановлюємо прапор
} while( ch !='\r ' ); // вихід по натисненню Enter
cout << "\n---число слів: " << wordcount << "---\n";
return 0;
}
Програма прочитує символи з клавіатури в циклі do. Коли з клавіатури вводиться пропуск, лічильник кількості слів збільшується на одиницю, після чого програма ігнорує всі пропуски, до появи першого непробільного символу. і т.д. Для того, щоб реалізувати подібний алгоритм, програмі необхідно розрізняти, чи вводиться в даний момент слово або послідовність пропусків. Для цього використовується змінна word1 перераховуваного типу Word, визначеного таким чином:
enum Word { N0, YES };
Змінні типу Word можуть мати тільки два різні значення: N0 і YES. Зверніть увагу на те, що перерахування починається із значення N0; це означає, що цьому значенню відповідатиме внутрішнє уявлення у вигляді цілого числа 0, яке може інтерпретуватися ще і як хибне значення.
На початку роботи програми змінної word1 привласнюється значення N0. Як тільки з клавіатури буден отриманий перший непробільний символ, значення змінної зміниться на YES і сигналізуватиме про те, що в даний момент вводиться слово. Значення YES зберігатиметься за змінній word1 до тих пір, поки з клавіатури не буде введений пропуск, який означає кінець слова. Тому змінна word1 набуде значення N0, яке зберігатиметься до тих пір, поки не з'явиться непробільний символ.
Завдання цілих значень для перераховуваних констант.
Першої з перераховуваних констант відповідає ціле значення, рівне 0, другою - значення, рівне 1, і т.д. Для того, щоб змінити значення, з якого починається нумерація, можна за допомогою операції привласнення задати це значення першої з перераховуваних констант:
enum days_of_week { Sun = 1, Mon, Tue, Wed, Thu, Fri, Sat };
В цьому випадку наступним у списку константам відповідатимуть числа 2, 3 і 4 відповідно. Фактично ми можемо змінити величину цілого числа, відповідного будь-якому елементу списку, застосувавши до нього операцію привласнення.
Недолік перерахувань.
Важливим недоліком перераховуваних типів даних є те, що вони не розпізнаються засобами введення/виводу C++. Наприклад, результатом виводу у фрагменті
enum direction { north, south, east, west };
direction dir = south;
cout << dir;
буде не south, що формально є значенням змінної dir, а її внутрішнє уявлення, тобто ціле число 1.
Для виводу екран значень перераховуваного типу можна використовувати конструкцію вибора switch:
switch (dir)
{
case 0: cout << “north” << endl; break;
case 1: cout << “south” << endl; break;
case 2: cout << “east” << endl; break;
case 3: cout << “west” << endl; break;
}
Приклади перераховуваних типів
enum months{Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec}; // місяці року
enum switch { off, on }; // перемикач
enum meridian { am, pm }; // меридіан
enum chess { pawn, knight, bishop, rook, queen, king }; // шахові фігури
Приклад 8. cardenum.срр // карточная игра с использованием перечислений
Групу констант типу const int, призначених для представлення карткових мастей:
const int clubs = 0;
const int diamonds = 1;
const int hearts = 2;
const int spades = 3;
Замінимо на перераховуваний тип:
enum Suit { clubs, diamonds, hearts, spades };
--------------------------------------------------------------------------
#include <iostream.h>
const int jack = 11; // именованные достоинства карт
const int queen = 12;
const int king = 13;
const int ace = 14;
enum Suit { clubs, diamonds, hearts, spades };
--------------------------------------------------------------------------
struct card
{
int number; // достоинство карты
Suit suit; // масть
};
--------------------------------------------------------------------------