النوع enum في السي بلاس بلاس | C++ enum

 النوع enum في C++

النوع enum يستخدم لتعريف قائمة من القيم أو عدة مجموعة قيم ثابتة بشكل منطقي.
في نهاية الأمر تعتبر هذه المجموعة كنوع جديد من البيانات و فيه عدة قيم محتملة يمكن الإختيار منها فقط.

النوع enum مفيد جداً في حال أردت بناء كود مخصص فقط للتعامل مع نوع محدد من القيم و في حال حاول أي مبرمج آخر عدم الإلتزام بنوع البيانات الذي فرضته أنت و قام بتمرير قيم من نوع آخر فإنه يتم تنبيهه مباشرةً قبل تشغيل الكود و في حال أصر على ذلك و قام بتشغيل الكود فإن مترجم لغة C++ سيمنعه وقت التشغيل و يظهر له خطأ.

بشكل عام, في حال أردت تعريف مجموعة قيم مترابطة يستحيل أن تتبدل فالخيار الأمثل هو تعريف هذه القيم في الأساس بداخل enum.

أمثلة حول بعض المعلومات الثابتة في الحياة و التي أيضاً تعتبر ثابتة في المنطق هي:

  • فصول السنة ( الخريف, الشتاء, الربيع, الصيف )

  • الإتجاهات ( الشمال - الجنوب - الشرق - الغرب )

  • أيام الأسبوع ( الإثنين - الثلاثاء - الأربعاء إلخ.. )

  • أشهر السنة ( كانون الثاني - شباط - آذار إلخ.. )

  • الجنس ( ذكر - أنثى )

عند التعامل مع هذا النوع الثابت من البيانات و الذي لا نريد لأحد أن يعبث به فإننا نستخدم النوع enum و هذا ما سنراه لاحقاً في الأمثلة.

طريقة تعريف enum في C++

تعريف enum يشبه كثيراً طريقة تعريف struct و لكن التعامل مع المتغيرات التي نضعها فيه لاحقاً هو ما يختلف.

عند وضع متغيرات بداخله يمكنك إعطاؤهم قيم بنفسك أو ترك المترجم يعطيهم قيم إفتراضية بنفسه.
إفتراضياً المتغيرات التي تضعها يتم إعطاؤها قيم بالترتيب إبتداءاً من صفر, فمثلاً أولاً أول متغير تكون قيمته 0 و الثاني تكون قيمته 1 و هكذا.


في المثال التالي قمنا بتعريف enum إسمه Days يمثل أيام الأسبوع.
بعدها قمنا بإنشاء كائن منه و جعلناه يساوي أحد الثوابت الموجودة في Days و من ثم طباعة قيمته.

مثال

Main.cpp
                    #include <iostream>

                    using namespace std;

                    // وضعنا فيه 7 ثوابت Days إسمه enum هنا قمنا بتعريف
                    enum Days
                    {
                    Monday,
                    Tuesday,
                    Wednesday,
                    Thursday,
                    Friday,
                    Saturday,
                    Sunday
                    };

                    int main()
                    {
                    // فقط Days و الهدف منه تخزين إحدى القيم الموجودة في today إسمه Days هنا قمنا بإنشاء كائن من
                    Days today;

                    // today في الكائن Days الموجود بالأساس في Monday هنا قمنا بتخزين قيمة الثابت
                    today = Monday;

                    // today هنا قمنا بطباعة قيمة الكائن
                    cout << "today value = " << today;

                    return 0;
                    }
                  

سنحصل على النتيجة التالية عند التشغيل.

                    today value = 0
                  

في المثال السابق قد تقول لما كل هذا العذاب!
لما لا نقوم بتعريف المتغير today بشكل مباشر كالتالي ؟!

                  int today = 0;
                


معلومة مهمة

في المثال السابق, لو قمت بتعريف today كمتغير عادي, كان بإمكانك وضع أي قيمة تريد فيه مثل 20 أو أي قيمة أخرى.

فائدة تعريف today ككائن من Days هو أنك أصبحت مجبر على استخدام الثوابت الموجودة فيه لتحديد قيمة today مما يجعلك تضمن أنه لا يمكن تمرير أي قيمة عشوائية غير القيم التي قمت أنت بتحديدها فمثلاً في المثال السابق يمكنك أن تغيير قيمة الكائن today كالتالي.

                  // Days لأنها موجودة في الأصل في Monday يمكنك وضع القيمة
                  today = Monday;

                  // Days لأنها موجودة في الأصل في Friday يمكنك وضع القيمة
                  today = Friday;
                

مفاهيم مهمة حول النوع enum في السي بلاس بلاس


المفهوم الأول

هنا وضعنا مثال يوضح طريقة تعيين قيم للثوابت الموضوعة في enum و كيفية الإستفادة من هذه القيم.

في حال أردت تعيين قيم للثوابت التي تنوي وضعها في enum بنفسك بدل القيم الإفتراضية التي يضعها المترجم, يمكنك وضع أعداد صحيحة كقيم لها.
ملاحظة: لا يمكنك وضع قيم نصية (كلمات أو جمل) كقيم للثوابت التي نضعها فيه.


في المثال التالي قمنا بتعريف enum إسمه Months يحتوي على ثوابت تمثل أشهر السنة و عدد الأيام الموجودة فيها.
بعدها قمنا بإنشاء كائن منه و جعلناه يساوي أحد الثوابت (أي الأشهر) الموجودة في Months و من ثم طباعة قيمته.

مثال

Main.cpp
                    #include <iostream>

                    using namespace std;

                    // وضعنا فيه 12 ثابت مع إعطائهم قيم Months إسمه enum هنا قمنا بتعريف
                    enum Months
                    {
                    Jan = 31,
                    Feb = 28,
                    Mar = 31,
                    Apr = 30,
                    May = 31,
                    Jun = 30,
                    Jul = 31,
                    Aug = 31,
                    Sep = 30,
                    Oct = 31,
                    Nov = 30,
                    Dec = 31
                    };

                    int main()
                    {
                    // فقط Months و الهدف منه تخزين إحدى القيم الموجودة في selectedMonth إسمه Months هنا قمنا بإنشاء كائن من
                    Months selectedMonth;

                    // selectedMonth في الكائن Months الموجود بالأساس في May هنا قمنا بتخزين قيمة الثابت
                    selectedMonth = May;

                    // May و التي تمثل عدد الأيام الموجودة في الشهر selectedMonth هنا قمنا بطباعة قيمة الثابت
                    cout << "May contain " << selectedMonth << " days";

                    return 0;
                    }

                  

سنحصل على النتيجة التالية عند التشغيل.

                    May contain 31 days
                  


المفهوم الثاني

هنا وضعنا مثال يعلمك كيف تقوم بالتشييك على قيمة الكائن الذي ننشئه من enum باستخدام الجملة switch مما يجعل كتابة الكود أكثر سهولة و وضوح.

من أكثر الأشياء التي تميّز النوع enum أنه يمكن استخدام الجملة switch للتشييك على قيمة الكائن الذي ننشئه منه مما يجعل كتابة الكود أكثر سهولة و وضوح.


في المثال التالي قمنا بتعريف enum إسمه Days يمثل أيام الأسبوع.
بعدها قمنا بإنشاء كائن منه و جعلناه يساوي أحد الثوابت (الأيام) الموجودة في Days.
في الأخير قمنا باستخدام الجملة switch للتشيك على قيمة الكائن و على أساسها نطبع له الجملة المناسبة.

مثال

Main.cpp
                    #include <iostream>

                    using namespace std;

                    // وضعنا فيه 7 ثوابت Days إسمه enum هنا قمنا بتعريف
                    enum Days
                    {
                    Monday,
                    Tuesday,
                    Wednesday,
                    Thursday,
                    Friday,
                    Saturday,
                    Sunday
                    };

                    int main()
                    {
                    // فقط Days و الهدف منه تخزين إحدى القيم الموجودة في selectedDay إسمه Days هنا قمنا بإنشاء كائن من
                    Days selectedDay;

                    // selectedDay في الكائن Days الموجود بالأساس في Thursday هنا قمنا بتخزين قيمة الثابت
                    selectedDay = Thursday;

                    // selectedDay هنا قمنا بالتشييك على قيمة الكائن
                    switch(selectedDay)
                    {
                    // سيتم تنفيذ أمر الطباعة التالي Thursday أو Wednesday أو Tuesday أو Monday إذا كانت تساوي قيمة الثابت
                    case Monday:
                    case Tuesday:
                    case Wednesday:
                    case Thursday:
                    cout << "We are available from 8:00 AM to 4:00 PM.";
                    break;

                    // سيتم تنفيذ أمر الطباعة التالي Friday إذا كانت تساوي قيمة الثابت
                    case Friday:
                    cout << "We are available from 8:00 AM to 12:00 PM.";
                    break;

                    // و هنا سيتم تنفيذ أمر الطباعة التالي Sunday أو Saturday إذا كانت لا تساوي أي قيمة سابقة فهذا يعني أنها تساوي
                    default:
                    cout << "We are not available on vacations.";
                    break;
                    }

                    return 0;
                    }
                  

سنحصل على النتيجة التالية عند التشغيل.

                    We are available from 8:00 AM to 4:00 PM.
                  


المفهوم الثالث

هنا وضعنا مثال يوضح كيفية تعريف دالة تأخذ باراميتر نوعه enum و كيفية تمرير قيمة لها عند استدعاءها.

المثال التالي يوضح كيفية تعريف دالة تأخذ باراميتر نوعه enum و كيفية تمرير قيمة لها عند استدعاءها.


في المثال التالي قمنا بتعريف enum إسمه Gender يمثل أنواع الجنس (ذكر, أنثى).
بعدها قمنا بتعريف دالة إسمها printInstructions() عند استدعاءها نمرر لها كائن من Gender فتقوم بالتشييك على قيمته و على أساسه تقوم بطباعة نص محدد.
في الأخير قمنا بإنشاء كائن من Gender و قمنا بتمريره للدالة printInstructions().

مثال

Main.cpp
                    #include <iostream>

                    using namespace std;

                    // وضعنا فيه ثابتين Gender إسمه enum هنا قمنا بتعريف
                    enum Gender
                    {
                    Male,
                    Female
                    };

                    // Gender عند استدعاءها يجب أن نمرر لها قيمة عبارة عن كائن من printInstructions هنا قمنا بتعريف دالة إسمها
                    void printInstructions(Gender gender)
                    {
                    // سيتم تنفيذ أمر الطباعة الموضوع هنا Male تساوي gender إذا كانت القيمة التي مررناها لها في الكائن
                    if (gender == Male)
                    {
                    cout << "Males should go to right building.";
                    }
                    // سيتم تنفيذ أمر الطباعة الموضوع هنا Male لا تساوي gender إذا كانت القيمة التي مررناها لها في الكائن
                    else
                    {
                    cout << "Females should go to the left building.";
                    }
                    }

                    // main() هنا قمنا بتعريف الدالة
                    int main()
                    {
                    // فقط Gender و الهدف منه تخزين إحدى القيم الموجودة في selectedGender إسمه Gender هنا قمنا بإنشاء كائن من
                    Gender selectedGender;

                    // selectedGender في الكائن Gender الموجود بالأساس في Male هنا قمنا بتخزين قيمة الثابت
                    selectedGender = Male;

                    // و التي ستقوم بالتشييك على قيمته و من ثم طباعة جملة تناسب قيمته selectedGender و تمرير الكائن printInstructions() هنا قمنا باستدعاء الدالة
                    printInstructions(selectedGender);

                    return 0;
                    }
                  

سنحصل على النتيجة التالية عند التشغيل.

                    Males should go to right building.