[英]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.