2011-12-28 34 views
8

Tôi có mã macro này, cho phép tôi xác định cả hai tên C enum và danh sách tên được liệt kê dưới dạng chuỗi sử dụng một cấu trúc. Nó ngăn cản tôi không phải trùng lặp tên điều tra viên (và có thể giới thiệu lỗi cho các danh sách lớn).Đếm các macro tiền xử lý

#define ENUM_DEFINITIONS(F) \ 
    F(0, Item1) \ 
    F(5, Item2) \ 
    F(15, Item3) \ 
    ... 
    F(63, ItemN) 

thì:

enum Items { 
    #define ITEM_ENUM_DEFINE(id, name) name = id, 
    ENUM_DEFINITIONS(ITEM_ENUM_DEFINE) 
    #undef ITEM_ENUM_DEFINE 

mà khi mở rộng, nên sản xuất:

enum Items { 
    Item1 = 0, 
    Item2 = 5, 
    Item3 = 15, 
    ... 
    ItemN = 63, 
} 

Trong tập tin thực hiện, tôi có mã này:

const char* itemNames[TOTAL_ITEMS]; 
int iter = 0; 

#define ITEM_STRING_DEFINE(id, name) itemNames[iter++] = #name; 
    ENUM_DEFINITIONS(ITEM_STRING_DEFINE) 
#undef ITEM_STRING_DEFINE 

đó, khi được mở rộng, tạo ra:

itemNames[iter++] = "Item1"; 
itemNames[iter++] = "Item2"; 
itemNames[iter++] = "Item3"; 
... 
itemNames[iter++] = "ItemN"; 

Tôi muốn biết có bao nhiêu mục liệt kê mà tôi đã tạo trong thời trang này và có thể truyền cho các mảng biên dịch. Trong ví dụ trên, điều này sẽ xác định rằng TOTAL_ITEMS = N tại thời gian biên dịch. Có thể đếm số lần gọi macro bằng cách này không?

Tôi đã nhìn thấy đề cập đến một phi tiêu chuẩn COUNTER vĩ mô, tương tự như FILEĐƯỜNG DÂY macro, nhưng tôi hy vọng có một cách chuẩn hơn.

Cũng sẽ muốn nghe nếu có cách tốt hơn để đạt được điều này mà không cần phải sử dụng macro.

+0

Tại sao bạn cần cả 'enum' và mảng chuỗi? – Philip

+0

Dường như nó xuất hiện khá thường xuyên trong công việc của tôi. Một ví dụ sẽ là một máy trạng thái mà các trạng thái được liệt kê, và một giao diện người dùng sẽ hiển thị tên của trạng thái hiện tại. Thuận tiện của nó để xác định nó chỉ một lần, và làm cho nó dễ dàng hơn cho các nhà phát triển khác, những người muốn thêm các tiểu bang mới. – Eyal

Trả lời

7

Sau đây nên làm việc:

#define ITEM_STRING_DEFINE(id, name) #name, // note trailing comma 
const char *itemNames[] = { 
    ENUM_DEFINITIONS(ITEM_STRING_DEFINE) 
}; 

#define TOTAL_ITEMS (sizeof itemNames/sizeof itemNames[0]) 

Sửa: Cảm ơn bạn Raymond Chen cho lưu ý chúng tôi không phải lo lắng về dấu phẩy thức không cần thiết trong danh sách. (Tôi đã vô tình giải quyết vấn đề cho các enums với các trình biên dịch C89 nghiêm ngặt, như trong Is the last comma in C enum required?.)

+1

Bạn không cần phải ăn dấu phẩy. Dấu phẩy sau là hợp pháp và bị bỏ qua. –

+0

Về dấu phẩy không cần thiết cuối cùng, tôi dường như nhớ lại rằng trình biên dịch SGI Irix sẽ đưa ra một cảnh báo không bị ức chế về nó, buộc tôi phải luôn bỏ qua nó. –

2

Cũng sẽ muốn nghe nếu có cách tốt hơn để đạt được điều này mà không phải sử dụng macro.

Bạn luôn có thể sử dụng ngôn ngữ kịch bản như ruby ​​hoặc python để tạo tệp .c và .h cho bạn. Nếu bạn làm tốt, bạn có thể tích hợp tập lệnh của bạn vào Makefile.

+1

Tôi thường không thích các cách tiếp cận thêm ngôn ngữ khác vào yêu cầu xây dựng. – Alex

1

Tôi biết đây không phải là câu trả lời hoàn chỉnh. Bạn có thể tạo macro xung quanh một cái gì đó như thế này.

#include <stdio.h> 

const char * array[] = { 
    "arr1", "arr2", "arr3", "arr4" 
}; 

int main (int argc, char **argv)$ 
{ 
    printf("%d\n", sizeof(array)/sizeof(const char *)); 
} 

Nếu bạn có thể sửa đổi enum của bạn để nó có yếu tố liên tục bạn có thể làm sth như thế này (từ Boost)

enum { A=0,B,C,D,E,F,N }; 
const char arr[N]; // can contain a character for each enum value 
4

Bạn có thể sử dụng kỹ thuật tương tự để đếm số lời gọi.

enum itemscounter { 
    #define ITEM_ENUM_DEFINE(id, name) name##counter, 
    ENUM_DEFINITIONS(ITEM_ENUM_DEFINE) 
    #undef ITEM_ENUM_DEFINE 
TOTAL_ITEMS 
}; 
+1

Tôi chấp nhận câu trả lời ở trên, nhưng nghĩ rằng đây là một cách tiếp cận khá tốt (và thông minh). Cảm ơn! – Eyal

0

Xem các đề xuất Mu Dynamics 'Enums, Strings and Laziness'; đây là ít nhất liên quan đến những gì bạn đang sau.

Nếu không, hãy xem bộ sưu tập Boost Preprocessor (có thể sử dụng với bộ tiền xử lý C cũng như bộ tiền xử lý C++).

Các vấn đề liên quan