前段時間,准備設計一個關於出錯信息的表,每一個錯誤有一個唯一的ErrID,和對應的錯誤信息以及其他輔助信息。在C語言中,很自然的實現如下:
enum {
ERR_ID_1,
ERR_ID_2,
ERR_ID_3,
ERR_ID_4
} ErrID;
const char* errmsg[] = {
"This is Error 1 msg", /*ERR_ID_1*/
"This is Error 2 msg", /*ERR_ID_2*/
"This is Error 3 msg", /*ERR_ID_3*/
"This is Error 4 msg" /*ERR_ID_4*/
};
int main() {
printf("Error= %s", errmsg[ERR_ID_1]);
return 0;
}
這樣帶來的問題是很不容易維護,必須人為的確定每一個ErrID和它的errmsg相對應。希望能不增加任何時間或空間的開銷的情況下,讓實現更加的“美觀”,更容易維護。自己第一時間能想到的,就是宏或者模板。
方法一
#define ERR_MSG(id, msg) const char* err_msg_##id = msg;
#define GET_MSG(id) (err_msg_##id)
ERR_MSG(ERR_ID_1, "This is Error 1 msg")
ERR_MSG(ERR_ID_2, "This is Error 2 msg")
ERR_MSG(ERR_ID_3, "This is Error 3 msg")
ERR_MSG(ERR_ID_4, "This is Error 4 msg")
int main() {
printf("Error= %s", GET_MSG(ERR_ID_1));
return 0;
}
這個方法的好處在於連errmsg數組的空間都省略掉了。缺點就是
不能支持在運行時通過傳入的ErrID來動態決定輸出。
不支持基於errmsg的遍歷操作甚至不知道ErrID的個數。因為errmsg本來就不存在。
方法二
首先,另外建一個文件,比如err.txt,每行的格式如:
ERR_MSG(ERR_ID_1, "This is Error 1 msg")
ERR_MSG(ERR_ID_2, "This is Error 2 msg")
ERR_MSG(ERR_ID_3, "This is Error 3 msg")
ERR_MSG(ERR_ID_4, "This is Error 4 msg")
在主文件中:
#undef ERR_MSG
#define ERR_MSG(id, msg) id,
enum {
#include "err.txt"
MAX_ERR_NUMBER
} ERRID;
#undef ERR_MSG
#define ERR_MSG(id, msg) msg,
const char* errmsg[] = {
#include "err.txt"
""
};
在最後加入一個無用的元素,用來避免某些編譯器監測到最尾元素後有逗號時的警告。
當然,errmsg數組也不一定需要。比如,可以這樣實現一個通過傳入的ErrID返回相應errmsg的函數get_err_msg():
#undef ERR_MSG
#define ERR_MSG(id, msg) case id: return msg; break;
const char* get_err_msg(ErrId eid) {
switch (eid) {
#include "err.txt"
}
return NULL; // Dummy。用來消除某些編譯器的警告。
}