簡體   English   中英

C ++如何將字符串轉換為枚舉以在開關中使用它?

[英]C++ How can I convert a string to enum to use it in a switch?

我有一個命令列表,如果用戶輸入,它將調用單獨的函數。 與一位朋友交談時,他說我應該使用 switch,這樣可以更快、更容易地閱讀“if、else if、else”語句。

在檢查如何實現這一點時,我意識到我無法做到,因為輸入是一個字符串,並且要讓開關工作,我需要將它轉換為一個枚舉,我似乎最直接的選擇是映射每個選項如下所示。

標題

enum class input 
{
    min,
    max,
    avg,
    count,
    stdev,
    sum,
    var,
    pow
};

map<string, input> inMap
{ 
    { "min", input::min },
    { "max", input::max }, 
    { "avg", input::avg },
    { "count", input::count },
    { "stdev", input::stdev }, 
    { "sum", input::sum },
    { "var", input::var },
    { "pow", input::pow }
};

在我不必映射每個值的情況下,是否有更易於使用的選項來使用enum 這非常耗時,目前我沒有看到任何好處。

.cpp 文件

void test::processInput(vector<string> input) {

    switch (inMap[input[0]]) {

        case inMap::min:
            MIN(input);
            break;

        case inMap::max:
            MAX(input);
            break;

        case inMap::avg:
            AVG(input);
            break;

        case inMap::count:
            COUNT(input);
            break;

        case inMap::stdev:
            STDEV(input);
            break;

        case inMap::sum:
            SUM(input);
            break;

        case inMap::var:
            VAR(input);
            break;

        case inMap::pow:
            POW(input);
            break;

        default:
            std::cout << "Error, input not found" << std::endl;
    }
}

我讀了一些關於散列值的帖子,這是一個好的選擇嗎? 此時繼續使用 if、else if、else 不是更好嗎?

謝謝!

為什么沒有要運行的字符串映射。
然后你不需要轉換為枚舉。

using Action     = void(std::vector<std::string>);
using ActionFunc = std::function<Action>;
using ActionMap  = std::map<std::string, ActionFunc>;

void MIN(std::vector<std::string>){}
... etc


ActionMap inMap
{ 
        { "min", MIN },
        { "max", MAX }, 
        { "avg", AVG },
        { "count", COUNT },
        { "stdev", STDDEV }, 
        { "sum", SUM },
        { "var", VAR },
        { "pow", POW }
};

void test::processInput(std::vector<std::string> input) // May want a ref here.
{
    auto find = inMap.find(input[0]);
    if (find == inMap.end()) {
         std::cout << "Error, input not found" << std::endl;
         return;
    }
    find->second(input);
}

無論哪種方式,您都在進行許多字符串比較,並且字符串比較很慢。

當您執行 if/else 時,如果您有 n 個目標字符串,您平均會進行 n/2 比較。 所以 4 比較了 8 個關鍵字。

當您執行map時,這將減少為 log2(n) 比較 - 因此 3 比較 8 個條目。 哦,還有一個額外的向后比較以檢查值是否等於索引。 如果它既不小也不大,那么它一定是相等的。

鑒於地圖代碼更復雜,如您所見,您不會贏。 使用(許多)更多關鍵字來檢查,您將獲得好處。

如果您使用unordered_map ,則字符串將轉換為整數散列值,並且可以有效地用於直接查找答案。 但是,計算哈希可能是一個緩慢的過程,並且將進行最終比較以檢查找到的值是否完全匹配。 為所有關鍵字生成散列的設置成本也更高。 在這種特殊情況下,您可以編寫自己的哈希函數,它只需要前 2 個字符,並且可能會縮小范圍,這會比默認的字符串哈希函數快一些。

最后一種選擇是逐個字符查找。 如果第一個字符是“m”,那么您立即將檢查減少到 2 個選項。 's' 提供 2 個其他選項,依此類推。 對於像這樣的小型數據集,只需執行第一個字符過濾器就會有所作為,執行第二個字符會為您提供唯一檢查。 這些是簡單的字符比較,而不是整個字符串比較,快得多!

沒有簡單的 stdlib 數據結構可以幫助您解決這個問題。 您可以將其寫成 2 級嵌套 case 語句:

switch (input[0][0])
{
case 'm':
  switch (input[0][1])
  {
  case 'i':
    if (input[0].compare("min")==0) return MIN;
    return NO_MATCH;
  case 'a':
    if (input[0].compare("max")==0) return MAX;
    return NO_MATCH;
  }
  return NO_MATCH;
case 's':
  switch(input[0][1])
  {
  case 't':

  case 'u':
  }

... etc

(作為讀者練習,有一個版本的 string::compare() 會跳過你已經比較過的字符)

您可以構建自己的樹結構來表示此單詞查找。 如果您添加跳過樹中多個字母的功能,您可以生成相當有效的字符串字典查找,其成本僅比單個字符串比較多一點。

另一種選擇是,使用字符串/目標對的排序向量,您可以執行自定義二進制截斷函數,該函數利用知道仍在搜索范圍內的所有字符串具有相同的首字母,並且不再需要比較. 在這種情況下,它不會有太大的區別,但是有數百個關鍵字,這將比手動 case 語句更易於維護。

但最后,使用unordered_map提供的簡單哈希表,大多數關鍵字檢測代碼都足夠快。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM