Enumerationها
enum یا شمارشگر، یکی از انواع داده مشتقشده در C است که به شما امکان میدهد مجموعهای از ثابتهای نامدار با مقادیر صحیح تعریف کنید. Enumها کد را خواناتر، قابلنگهداریتر و مستندتر میکنند، بهخصوص زمانی که با حالتها، گزینهها یا وضعیتهای مختلف سروکار دارید.
تعریف Enum
سینتکس پایه برای تعریف یک enum:
enum enumName { constant1, constant2, constant3, // ... };
مثال ساده:
enum Weekday { Saturday, Sunday, Monday, Tuesday, Wednesday, Thursday, Friday };
در این مثال، Saturday برابر با 0، Sunday برابر با 1، Monday برابر با 2 و الی آخر است. بهطور پیشفرض، اولین عضو مقدار 0 میگیرد و هر عضو بعدی یک واحد افزایش مییابد.
مقداردهی سفارشی به اعضای enum
میتوانید به هر عضو enum یک مقدار صحیح مشخص اختصاص دهید:
enum Status { PENDING = 1, PROCESSING = 2, COMPLETED = 3, FAILED = 4 };
اگر به همه اعضا مقدار ندهید، اعضای بعدی بهطور خودکار از آخرین مقدار مشخصشده ادامه پیدا میکنند:
enum Colors { RED = 10, GREEN, // 11 BLUE, // 12 YELLOW = 20, ORANGE // 21 };
مقادیر عضوها حتی میتوانند تکراری باشند:
enum HttpStatus { OK = 200, CREATED = 201, NOT_FOUND = 404, INTERNAL_ERROR = 500, SUCCESS = 200 // همان مقدار OK };
استفاده از Enum
تعریف متغیر از نوع enum:
enum Weekday today = Wednesday; enum Status currentStatus = PROCESSING; enum Colors favoriteColor = BLUE;
استفاده در شرطها:
#include <stdio.h> enum Status { PENDING = 1, PROCESSING = 2, COMPLETED = 3, FAILED = 4 }; int main() { enum Status taskStatus = COMPLETED; if (taskStatus == COMPLETED) { printf("تسک با موفقیت انجام شد!\n"); } else if (taskStatus == FAILED) { printf("تسک ناموفق بود.\n"); } else { printf("تسک در حال انجام است...\n"); } return 0; }
استفاده در switch:
#include <stdio.h> enum HttpStatus { OK = 200, NOT_FOUND = 404, INTERNAL_ERROR = 500 }; int main() { enum HttpStatus response = OK; switch (response) { case OK: printf("درخواست موفقیتآمیز بود (۲۰۰)\n"); break; case NOT_FOUND: printf("منبع یافت نشد (۴۰۴)\n"); break; case INTERNAL_ERROR: printf("خطای داخلی سرور (۵۰۰)\n"); break; default: printf("وضعیت ناشناخته\n"); } return 0; }
کاربردهای عملی Enum
۱. حالتهای یک برنامه یا سیستم:
enum GameState { MENU, PLAYING, PAUSED, GAME_OVER };
۲. خطاهای سیستمی:
enum ErrorCode { ERR_NONE = 0, ERR_FILE_NOT_FOUND = -1, ERR_PERMISSION_DENIED = -2, ERR_MEMORY_ALLOC = -3 };
۳. ماههای سال:
enum Month { JAN = 1, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC };
۴. نقشهای کاربری در یک سیستم:
enum UserRole { ADMIN = 10, MODERATOR = 20, EDITOR = 30, USER = 40, GUEST = 50 };
تفاوت enum با #define
| ویژگی | enum | #define |
|---|---|---|
| نوع داده | نوع خاص خود را دارد (enum type) | ماکروی پیشپردازنده، بدون نوع |
| محدوده | دارای محدوده (scope) است | سراسری است |
| قابلیت دیباگ | در دیباگر نامها قابل مشاهده است | نامها در دیباگ دیده نمیشوند |
| ایمنی نوع | نسبی (نوعهای مختلف enum قابل مقایسه هستند) | ندارد |
| گروهبندی | اعضا با هم گروهبندی میشوند | هر ماکرو مستقل است |
مثال مقایسه:
// با #define #define RED 1 #define GREEN 2 #define BLUE 3 // با enum enum Color { RED = 1, GREEN = 2, BLUE = 3 };
در استفاده از enum، کامپایلر میداند که RED، GREEN و BLUE به هم مرتبط هستند و این اطلاعات در هنگام دیباگ در دسترس است.
نکات پیشرفته در استفاده از enum
تعریف type alias برای enum:
برای راحتی بیشتر، از typedef برای ایجاد نام کوتاهتر استفاده کنید:
typedef enum { MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY } Day; // استفاده سادهتر Day today = FRIDAY;
enum و عملیات بیتی:
از enum برای تعریف پرچمهای بیتی (bit flags) استفاده میشود:
enum Permission { READ = 1 << 0, // ۱ WRITE = 1 << 1, // ۲ EXECUTE = 1 << 2, // ۴ DELETE = 1 << 3 // ۸ }; // ترکیب پرچمها با OR int userPermissions = READ | WRITE; // ۳ // بررسی وجود پرچم if (userPermissions & EXECUTE) { printf("کاربر مجوز اجرا دارد\n"); }
enum بهعنوان آرگومان تابع:
#include <stdio.h> enum Operation { ADD, SUBTRACT, MULTIPLY, DIVIDE }; int calculate(int a, int b, enum Operation op) { switch (op) { case ADD: return a + b; case SUBTRACT: return a - b; case MULTIPLY: return a * b; case DIVIDE: return a / b; default: return 0; } } int main() { int result = calculate(10, 5, MULTIPLY); printf("نتیجه: %d\n", result); // چاپ ۵۰ return 0; }
محدودیتهای enum
-
مقادیر فقط صحیح: اعضای enum فقط میتوانند مقادیر صحیح داشته باشند.
-
بدون رشته: نمیتوان بهطور مستقیم نام عضو enum را بهعنوان رشته چاپ کرد.
enum Color { RED, GREEN, BLUE }; enum Color c = RED; printf("%s", c); // خطا - نام عضو را چاپ نمیکند
برای چاپ نام متناظر، باید یک آرایه رشتهای تعریف کنید:
enum Color { RED, GREEN, BLUE }; enum Color c = RED; const char* colorNames[] = {"RED", "GREEN", "BLUE"}; printf("رنگ: %s\n", colorNames[c]); // چاپ "RED"
خطاهای رایج با enum
۱. مقایسه enumهای نامربوط:
enum Weekday { SAT, SUN, MON }; enum Status { OK, ERROR }; enum Weekday w = SAT; enum Status s = OK; if (w == s) { // مشکلی ندارد (چون هر دو عدد صحیح هستند) // اما از نظر منطقی اشتباه است }
۲. انتساب مقدار نامعتبر:
enum Month { JAN = 1, FEB, MAR }; enum Month m = 99; // صحیح است اما مقدار نامعتبر
خلاصه نکات کلیدی
| نکته | توضیح |
|---|---|
| مقدار پیشفرض | اولین عضو 0 و بقیه یک واحد افزایش مییابند |
| مقداردهی سفارشی | میتوانید مقادیر دلخواه (صحیح) به اعضا اختصاص دهید |
| گروهبندی | اعضای یک enum بهصورت منطقی گروهبندی میشوند |
| دیباگ | نامهای enum در دیباگر قابل مشاهده هستند |
| نوع | enum یک نوع خاص محسوب میشود |
| محدوده | اعضای enum در محدوده (scope) خود تعریف میشوند |
| کاربرد اصلی | بهبود خوانایی و نگهداری کد در مواقعی که با مجموعهای از مقادیر ثابت سروکار داریم |