2013-01-11 20 views
4

將錯誤代碼從枚舉映射到字符串的更有效方法是什麼? (在C++)將錯誤代碼映射到C++中的字符串

例如,現在我在做這樣的事情:

std::string ErrorCodeToString(enum errorCode) 
{ 
    switch (errorCode) 
    { 
     case ERROR_ONE: return "ERROR_ONE"; 
     case ERROR_TWO: return "ERROR_TWO"; 
     ... 
     default: 
     break; 
    } 

    return "UNKNOWN"; 
} 

難道以任何方式更有效,如果我會做這樣的事?:

#define ToStr(name) # name; 

std::string MapError(enum errorCode) 
{ 
    switch (errorCode) 
    { 
     case ERROR_ONE: return ToStr(ERROR_ONE); 
     case ERROR_TWO: return ToStr(ERROR_TWO); 
     ... 
     default: 
     break; 
    } 

    return "UNKNOWN"; 
} 

也許有人對此有任何建議或想法? 謝謝。

+0

如果你正在考慮運行時的性能,這兩個是完全一樣的。 – Angew

+0

[如何將枚舉類型變量轉換爲字符串?](http://stackoverflow.com/questions/5093460/how-to-convert-an-enum-type-variable-to-a-string) –

+2

我會忽略'default:'分支;如果你這樣做了,那麼如果你忘記包含所有的代碼,你應該得到一個編譯器警告。 –

回答

7

如果你要使用宏,爲什麼不走一路:

std::string MapError(enum errorCode) 
{ 
    #define MAP_ERROR_CODE(code) case code: return #code ; 
    switch (errorCode) 
    { 
     MAP_ERROR_CODE(ERROR_ONE) 
     MAP_ERROR_CODE(ERROR_TWO) 
     ... 
    } 
    #undef MAP_ERROR_CODE 
    return "UNKNOWN"; 
} 
+1

我認爲「一路」實際上將修復此功能與錯誤代碼枚舉的定義:可能的代碼列表。請參閱我的答案以解決該問題。 –

2

預處理程序通過代碼後,兩者將完全相同。唯一的問題是第二種方法不太容易出錯。

我會說你已經實施已經是一個很好的解決方案。

4
enum errors { 
    error_zero, 
    error_one, 
    error_two 
}; 

namespace { 
const char *error_names[] = { 
    "Error one", 
    "Error two", 
    "Error three" 
}; 
} 

std::string map_error(errors err) { 
    return error_names[err]; 
} 
+1

或者一個非常花哨的註冊表,其中每個模塊註冊自己的錯誤代碼和字符串。 – TemplateRex

4

你建議的替代沒有任何更有效的,但你可以在兩個方面改善的事情:

  1. 你顯然在errorCode enum和這個函數之間有一個重複。
  2. 您的函數中也有某種重複,因爲枚舉值與字符串給出的名稱相同。

可以解決這兩個一個小預處理魔術:

// This is your definition of available error codes 
#define ERROR_CODES \ 
    ERROR_CODE(ERROR_ONE) \ 
    ERROR_CODE(ERROR_TWO) \ 
    ERROR_CODE(ERROR_THREE) 

// Define ERROR_CODE macro appropriately to get a nice enum definition 
#define ERROR_CODE(a) ,a 
enum ErrorCode { 
    None, 
    ERROR_CODES 
}; 
#undef ERROR_CODE 

// Define ERROR_CODE macro differently here to get the enum -> string mapping 
std::string MapError(enum errorCode) 
{ 
    #define ERROR_CODE(a) case a: return #a; 

    switch (errorCode) 
    { 
     case None: return "None"; 
     ERROR_CODES 
    } 
} 
+0

在枚舉中,我得到「未聲明的標識符」(ERROR_CODES)。 – Rebirth

5

我就想辦法有錯誤代碼(int)和字符串描述(任何字符串)在一個聲明,只有一個單一的地方上面的例子都沒有允許。

所以我宣佈了一個簡單的類,存儲int和string,併爲int-> string轉換維護一個靜態映射。我還添加了一個「自動投地」整數功能:

class Error 
{ 
public: 
    Error(int _value, const std::string& _str) 
    { 
     value = _value; 
     message = _str; 
#ifdef _DEBUG 
     ErrorMap::iterator found = GetErrorMap().find(value); 
     if (found != GetErrorMap().end()) 
      assert(found->second == message); 
#endif 
     GetErrorMap()[value] = message; 
    } 

    // auto-cast Error to integer error code 
    operator int() { return value; } 

private: 
    int value; 
    std::string message; 

    typedef std::map<int,std::string> ErrorMap; 
    static ErrorMap& GetErrorMap() 
    { 
     static ErrorMap errMap; 
     return errMap; 
    } 

public: 

    static std::string GetErrorString(int value) 
    { 
     ErrorMap::iterator found = GetErrorMap().find(value); 
     if (found == GetErrorMap().end()) 
     { 
      assert(false); 
      return ""; 
     } 
     else 
     { 
      return found->second; 
     } 
    } 
}; 

然後,你只需如下聲明你的錯誤代碼:

static Error ERROR_SUCCESS(    0, "The operation succeeded"); 
static Error ERROR_SYSTEM_NOT_INITIALIZED( 1, "System is not initialised yet"); 
static Error ERROR_INTERNAL(    2, "Internal error"); 
static Error ERROR_NOT_IMPLEMENTED(  3, "Function not implemented yet"); 

然後,返回int的任何功能可以做回1

return ERROR_SYSTEM_NOT_INITIALIZED; 

而且,您的圖書館將獲得的客戶端程序調用

時「系統還沒有初始化」

或:

Error::GetErrorString(ERROR_SYSTEM_NOT_INITIALIZED); 

我看到的唯一限制是靜態的錯誤對象被創建多次,如果.h文件中聲明它們是由許多的.cpp包括(這就是爲什麼我做了_DEBUG測試在構造函數檢查地圖的一致性)。如果你沒有成千上萬的錯誤代碼,它不應該是一個問題(並且可能有一個解決方法...)

1

我知道這是一個古老的線程,但我不喜歡Frerich拉貝的方法,並得到它在VS工作,沒有錯誤:

#define ERROR_CODES \ 
    ERROR_CODE(NO_ERROR) \ 
    ERROR_CODE(ERROR_ONE) \ 
    ERROR_CODE(ERROR_TWO) \ 
    ERROR_CODE(ERROR_THREE) \ 
    ERROR_CODE(ERROR_FOUR) 

#define ERROR_CODE(code) code, 
typedef enum { ERROR_CODES } ErrorCodes; 
#undef ERROR_CODE 

const char *MapError(const int errorCode) 
{ 
#define ERROR_CODE(code) case code: return #code; 
    switch (errorCode) 
    { 
     ERROR_CODES 
    default: return "UNKNOWN ERROR"; 
    }; 
#undef ERROR_CODE 
} 
相關問題