26.ประเภทข้อมูลอื่น: enum, union

ประเภทข้อมูลอื่น

ในบางสถานการณ์ การเขียนโปรแกรมนั้นก็มีความหลากหลายทางข้อมูล นอกจาก Primitive data type แล้วในภาษา C++ ยังมีประเภทข้อมูลอื่นอยู่อีก เช่น การกำหนดประเภทข้อมูลเอง ข้อมูลแบบ Enum หรือ Union เป็นต้น ในบทนี้เราจะพูดถึงประเภทข้อมูลเหล่านี้และตัวอย่างการใช้งานในภาษา C++

Type aliases (typedef)

ในภาษา C++ เราสามารถสร้างประเภทตัวแปรขึ้นมาเอง (Aliases type) ได้ นั่นหมายความว่าชื่อของประเภทข้อมูลจะเป็นอะไรก็ได้ตามที่เราต้องการ มีสองวิธีในการที่จะสร้างประเภทตัวแปรที่กำหนดโดยผู้ใช้ โดยการใช้คำสั่ง typedef และ using แต่ในบทเรียนนี้เราจะใช้แค่ typedef และ typedef มีรูปแบบการใช้งานคือ:
typedef data_type identify;
typedef เป็นคำสั่งในการสร้าง data_type เป็นประเภทข้อมูลเดิมที่มีอยู่ เช่น int, float เป็นต้น และ identify เป็นชื่อของตัวแปรที่มีกฏการตั้งชื่อเหมือนกับตัวแปร
มาดูตัวอย่าง
typedef int NUMBER;
typedef int myType;
typedef float mMoney;
typedef char * pCh;
ในตัวอย่าง เราได้ประกาศตัวแปรแบบประเภทของข้อมูล 4 ตัว เช่น NUMBER และ myType ซึ่งสืบทอดมาจากประเภทของตัวแปรที่มีอยู่ แล้วเราสามารถใช้ชื่อเหล่านี้ในตอนที่เราประกาศตัวแปรหรือทำสิ่งอื่นๆ
#include <iostream>
using namespace std;

int main()
{
    typedef int NUMBER;
    typedef float mMoney;

    NUMBER n, m;
    mMoney cost = 10.5;

    n = 2;
    m = 3;

    cout << n + m << endl;
    cout << cost << endl;

    NUMBER x = 100, y = 200;
    cout << x + y << endl;
    return 0;
}
ในตัวอย่าง เราได้ประกาศ NUMBER ซึ่งเป็นประเภทแบบ int และ mMoney กับ float หลังจากนั้นเราสามารถใช้ตัวแปรชนิดข้อมูลนี้ เพื่อประกาศตัวแปรที่มีประเภทข้อมูลแบบ integer และ float ตามลำดับ ข้อได้เปรียบของมันคือเราสามารถเปลี่ยนประเภทของ NUMBER และประเภทของข้อมูลที่ใช้ NUMBER จะถูกเปลี่ยนแปลงในครั้งเดียว
typedef string s;
typedef char c;
typedef double d;

s name = "Mateo";
c ch = 'C';
d money = 2.43;
ในการใช้งานคำสั่ง typedef เพื่อทำ aliases type ยังมีประโยนช์อีกอย่างคือสามารถใช้เพื่อย่อชื่อของประเภทข้อมูลให้สั้นลงได้ ในตัวอย่าง เราได้ใช้คำสั่ง typedef เพื่อทำการย่อคำสั่ง string char และ double ให้เป็น s c และ d ตามลำดับ ในตอนนี้ เราสามารถใช้ชื่อที่กำหนดขึ้นแทนคำสั่งต่างๆ ได้

Enumerated types (enum)

Enum คือประเภทข้อมูลที่เป็นค่าคงที่ของจำนวนเต็มแต่แสดงด้วยสัญลักษณ์อื่น ประเภทข้อมูลแบบ enum เป็นประเภทข้อมูลที่ให้เราสามารถสร้างตัวแปร enum ได้ และค่าของมันสามารถเป็นข้อมูลประเภทไหนก็ได้ ที่ยังไม่มีอยู่ในภาษา C++ มันมีรูปแบบดังนี้:
enum type_name {
    value1, value2, value3, ...
} object_names;
เราใช้คำสั่ง enum สำหรับการสร้างและตามด้วย type_name ซึ่งเป็นชื่อของ enum ในวงเล็บ {} ซึ่งสามารถเป็นตัวอักษรใดๆ ที่ไม่ใช้ประเภทข้อมูลที่มีอยู่ มาดูการสร้างตัวแปรแบบ enum
#include <iostream>

using namespace std;

enum day_m
{
    sunday, monday, tuesday, wednesday, thursday, friday, saturday
};

int main()
{
    day_m myDay;
    myDay = monday;
    if (myDay == monday) {
        myDay = tuesday;
        cout << "Value of tuesday is " << tuesday << endl;
    } else {
        myDay = sunday;
        cout << "Value of sunday is " << sunday << endl;
    }
    return 0;
}
ในตัวอย่าง ตัวแปร enum day_mใช้สร้างตัวแปร myDayเพื่อที่จะให้เป็นประเภทข้อมูลของมันโดยคำสั่ง day_m myDay; ดังนั้น ประเภทข้อมูลที่ถูกต้องของ myDay สามารถเป็นค่าใดก็ได้ใน day_m เช่น sunday, monday, thuesday และไปเรื่อยๆ...
โดยทั่วไป ค่าของข้อมูลใน enum ให้ถูกแปลงค่าให้เป็น integer โดยปริยาย โดยจะมีค่าเริ่มต้นจาก 0, 1, 2, ... ดังนั้น sunday นั้นเท่ากับ 0, monday เป็น 1, tuesday เป็น 2, และไปเรื่อย... ดังนั้นค่าของ Enum จึงสามารถใช้แทนกับค่าคงที่จำนวนเต็มได้ นี่เป็นตัวอย่างการใช้งาน Enum กับการเปรียบเทียบค่ากับ Integer
#include <iostream>

using namespace std;

enum day_m
{
    sunday, monday, tuesday, wednesday, thursday, friday, saturday
};

int main()
{
    day_m myDay = tuesday;
    if (myDay == 2)
    {
        cout << "myDay is Tuesday";
    }
    return 0;
}
จากตัวอย่างก่อนหน้า เราได้ประกาศ Enum ที่มีชื่อว่า day_m และหลังจากนั้นเรากำหนดค่าให้กับตัวแปร enum เป็น tuesday และใช้คำสั่ง If ในการเปรียบเทียบกับ 2 ซึ่งทั้งสองนั้นจะมีค่าเท่ากันในการเปรียบเทียบ ต่อไปมาดูตัวอย่างเพิ่มเติมสำหรับการใช้งาน Enum
#include <iostream>

using namespace std;

enum status
{
    STOP = 0,
    PLAY = 1,
    FORWARD_2X = 2,
    BACKWARD_2X = -2
};

void play(status);

int main()
{
    play(PLAY);
    play(STOP);
    play(FORWARD_2X);
    play(BACKWARD_2X);

    play((status)1);
    play((status)0);
    return 0;
}

void play(status n)
{
    if (n == PLAY)
    {
        cout << "Music is playing..." << endl;
    }
    else if (n == STOP)
    {
        cout << "Music has stopped" << endl;
    }
    else if (n == FORWARD_2X)
    {
        cout << "Skipping forward 2X..." << endl;
    }
    else if (n == BACKWARD_2X)
    {
        cout << "Skipping backward 2X..." << endl;
    }
}
ในตัวอย่าง เป็นโปรแกรมของการทำงานเครื่องเล่นเพลง โดยเราได้สร้าง enum status สำหรับเก็บสถานะการทำงานของเครื่องเล่น ในการประกาศ Enum นี้เราได้ทำการกำหนดค่าให้กับ Enum แบบกำหนดเอง โดยใช้เครื่องหมายเท่ากับหลังชื่อของ Enum ซึ่งสามารถเป็นจำนวนเต็มบวกหรือจำนวนเต็มลบได้
ในฟังก์ชัน play() เป็นการสั่งการทำงานของเครื่องเล่นเพลงโดยการส่งค่าของ Enum เข้ามา คุณจะเห็นว่าเราสามารถใช้ค่าของ Enum ได้เลยทำให้โปรแกรมของเรามีความหมายมากขึ้น และนอกจากนี้เรายังสามารถส่งค่าที่เป็น Integer ได้อีกด้วย
Music is playing...
Music has stopped
Skipping forward 2X...
Skipping backward 2X...
Music is playing...
Music has stopped
นี่เป็นผลลัพธ์การทำงานของโปรแกรม และหลังจากการใช้ Enum นั้นโปรแกรมของเราสามารถเข้าใจได้ง่ายขึ้น

การใช้งาน Union

ในภาษา C++ มีข้อมูลอีกประเภทหนึ่งคือ Union ซึ่งรูปแบบการเก็บข้อมูลของ Union นั้นจะมีลักษณะที่คล้ายกับ Struct แต่สิ่งที่แตกต่างกันคือภายใน Union นั้นสามารถเก็บข้อมูลได้เพียงแค่หนึ่งสมาชิกเท่านั้น ซึ่งนี่จะทำให้ Union ใช้พื้นที่ในการจัดเก็บข้อมูลทั้งหมดเท่ากับขนาดของตัวแปรที่มากที่สุด ต่อไปมาดูตัวอย่างการใช้งาน Union ในภาษา C++
#include <iostream>
#include <cstring>

using namespace std;

union person
{
    char name[20];
    int age;
    float height;
};

int main()
{
    person p1;

    strcpy(p1.name, "Danny");
    p1.age = 20;
    p1.height = 6;

    cout << "Name: " << p1.name << endl; // null
    cout << "Age: " << p1.age << endl; // null
    cout << "Height: " << p1.height << endl;

    strcpy(p1.name, "Danny");
    cout << "Name: " << p1.name << endl;
    cout << "Age: " << p1.age << endl; // null
    cout << "Height: " << p1.height << endl; // null

    cout << "Size of union: " << sizeof(p1) << endl;

    return 0;
}
ในตัวอย่าง เราได้ประกาศ union ที่มีชื่อว่า person และมีสมาชิกสามตัวแปรคือ name age และ height ภายในสมาชิกทั้งสามตัวนี้ สมาชิกใช้พื้นที่ในการเก็บข้อมูลมากที่สุดคือ name ซึ่งมีขนาด 20 bytes ดังนั้นขนาดของ union จึงมีค่าเท่ากับขนาดของสมาชิกตัวนี้
strcpy(p1.name, "Danny");
p1.age = 20;
p1.height = 6;

cout << "Name: " << p1.name << endl; // null
cout << "Age: " << p1.age << endl; // null
cout << "Height: " << p1.height << endl;

strcpy(p1.name, "Danny");
cout << "Name: " << p1.name << endl;
cout << "Age: " << p1.age << endl; // null
cout << "Height: " << p1.height << endl; // null
ต่อมาเราได้กำหนดค่าให้กับตัวแปร Union อย่างที่เราได้บอกไปว่า Union นั้นสามารถเก็บค่าได้เพียงทีละค่า ในคำสั่งข้างบนทำให้ p1.height เท่านั้นที่มีค่าซึ่งเป็นตัวแปรที่ถูกกำหนดค่าให้ล่าสุดทำให้ตัวแปรอื่นนั้นเป็นค่าขยะ และหลังจากนั้นเราได้กำหนดค่าให้กับตัวแปร p1.name อีกครั้งและตัวแปรนี้มีค่าและตัวแปรอื่นมีค่าขยะแทน และสุดท้ายเราได้แสดงผลขนาดของ Union
Name:
Age: 1086324736
Height: 6
Name: Thomas
Age: 1836017748
Height: 4.63082e+027
Size of union: 20
นี่เป็นผลลัพธ์การทำงานของโปรแกรมในการใช้งาน Union ในภาษา C++
ในบทนี้ คุณได้เรียนรู้เกี่ยวกับประเภทข้อมูลอื่นที่มีในภาษา C++ เราได้พูดถึงการกำหนดชื่อเสมือนให้กับประเภทข้อมูล และการใช้งาน Enum และ Union ซึ่งประเภทข้อมูลเหล่านี้ถูกพัฒนามาเพื่อเป็นสิ่งที่อำนวยความสะดวกในการเขียนโปรแกรม
****************************************************************************************************

C++ Enumeration

In this article, you will learn to work with enumeration (enum). Also, you will learn where enums are commonly used in C++ programming.

An enumeration is a user-defined data type that consists of integral constants. To define an enumeration, keyword enum is used.
enum season { spring, summer, autumn, winter };
Here, the name of the enumeration is season.
And, springsummer and winter are values of type season.
By default, spring is 0, summer is 1 and so on. You can change the default value of an enum element during declaration (if necessary).
enum season 
{   spring = 0, 
    summer = 4, 
    autumn = 8,
    winter = 12
};

Enumerated Type Declaration

When you create an enumerated type, only blueprint for the variable is created. Here's how you can create variables of enum type.
enum boolean { false, true };

// inside function
enum boolean check;
Here, a variable check of type enum boolean is created.
Here is another way to declare same check variable using different syntax.
enum boolean 
{ 
   false, true
} check;

Example 1: Enumeration Type

#include <iostream>
using namespace std;

enum week { Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday };

int main()
{
    week today;
    today = Wednesday;
    cout << "Day " << today+1;
    return 0;
}
Output
Day 4

Example2: Changing Default Value of Enums

#include <iostream>
using namespace std;

enum seasons { spring = 34, summer = 4, autumn = 9, winter = 32};

int main() {

    seasons s;

    s = summer;
    cout << "Summer = " << s << endl;

    return 0;
}
Output
Summer = 4

Why enums are used in C++ programming?

An enum variable takes only one value out of many possible values. Example to demonstrate it,
#include <iostream>
using namespace std;

enum suit {
    club = 0,
    diamonds = 10,
    hearts = 20,
    spades = 3
} card;

int main() 
{
    card = club;
    cout << "Size of enum variable " << sizeof(card) << " bytes.";   
    return 0;
}
Output
Size of enum variable 4 bytes.
It's because the size of an integer is 4 bytes.;
This makes enum a good choice to work with flags.
You can accomplish the same task using C++ structures. However, working with enums gives you efficiency along with flexibility.

How to use enums for flags?

Let us take an example,
enum designFlags {
 ITALICS = 1,
 BOLD = 2,
 UNDERLINE = 4
} button;
Suppose you are designing a button for Windows application. You can set flags ITALICSBOLD and UNDERLINE to work with text.
There is a reason why all the integral constants are power of 2 in above pseudocode.
// In binary

ITALICS = 00000001
BOLD = 00000010
UNDERLINE = 00000100 
Since, the integral constants are power of 2, you can combine two or more flags at once without overlapping using bitwise OR | operator. This allows you to choose two or more flags at once. For example,
#include <iostream>
using namespace std;

enum designFlags {
    BOLD = 1,
    ITALICS = 2,
    UNDERLINE = 4
};

int main() 
{
    int myDesign = BOLD | UNDERLINE; 

        //    00000001
        //  | 00000100
        //  ___________
        //    00000101

    cout << myDesign;

    return 0;
}
Output
5
When the output is 5, you always know that bold and underline is used.
Also, you can add flag to your requirements.
if (myDesign & ITALICS) {
    // code for italics
}
Here, we have added italics to our design. Note, only code for italics is written inside the if statement.
You can accomplish almost anything in C++ programming without using enumerations. However, they can be pretty handy in certain situations. That's what differentiates good programmers from great programmers.
*******************************************************************************************************

Enumeration in C++


Enum is a user defined data type where we specify a set of values for a variable and the variable can only take one out of a small set of possible values. We use enum keyword to define a Enumeration.
enum direction {East, West, North, South}dir;
Here Enumeration name is direction which can only take one of the four specified values, the dir at the end of the declaration is an enum variable.
Lets take a simple example to understand this: Here I have assigned the value West to the enum variable dir and when I displayed the value of dir it shows 1. This is because by default the values are in increasing order starting from 0, which means East is 0, West is 1, North is 2 and South is 3.

Simple enum Example

#include<iostream>
using namespace std;
enum direction {East, West, North, South}dir;
int main()
{
   dir = West;
   cout<<dir;
   return 0;
}

Another way to declare enum variable

As we have seen in the above example that I have declared the enum variable dir during enum declaration, there is another way to declare an enum variable.
#include <iostream>
using namespace std;
enum direction {East, West, North, South};
int main(){
   direction dir;
   dir = South; 
   cout<<dir;   
   return 0;
}
Output:
3

Why use enum in C++

Now that we understand what is enum and how to use them in program, lets discuss why we use them: Enums are used only when we expect the variable to have one of the possible set of values, for example, we have a dir variable that holds the direction. Since we have four directions, this variable can take any one of the four values, if we try to assign a another random value to this variable, it will throw a compilation error. This increases compile-time checking and avoid errors that occurs by passing in invalid constants.
Another important place where they are used frequently are switch case statements, where all the values that case blocks expect can be defined in an enum. This way we can ensure that the enum variable that we pass in switch parenthesis is not taking any random value that it shouldn’t accept.

How to change default values of Enum

#include <iostream>
using namespace std;
enum direction {East=11, West=22, North=33, South=44};
int main(){
   direction dir;
   dir = South;
   cout<<dir; 
   return 0;
}
Output:
44
********************************************************************************************************************

ENUMS in C++

*************************************************************************************

Enumeration - enum in C++ Programming Tutorial

*******************************************************************************************************

C++ Programming Tutorial 35 - Switch Statement and Enum

***********************************************************************

Introduction to Unions in C++ | CPP Programming Video Tutorial