C++如何将字符串转换为枚举以在开关中使用它?
我有一个命令列表,如果用户输入将调用单独的函数。他与一个朋友交谈,他说我应该使用Switch,这更快,更易于阅读“如果否则,否则”语句。
在检查如何实现此功能时,我意识到我将无法做到,因为输入是字符串,要进行工作,我需要将其投射到枚举中,似乎我拥有的最直接的选项是映射每个选项如下。
标题
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;
}
}
我读了一些有关哈希值的文章,这是一个不错的选择吗?在这一点上,如果否则,如果否则,继续使用?
谢谢!
I have a list of commands that if a user inputs then it will call separate functions. Talking to a friend he said I should use switch, which is faster and easier to read over "if, else if, else" statements.
When checking how to implement this I realised that I wouldn't be able to because the input is a string and for a switch to work I would need to cast it to an enum and it seems like the most straightforward option I have is to map each of the options like below.
header
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 }
};
Is there a more accessible option to use enum
where I don't have to map each value? This is very time-consuming and I'm not seeing any benefits at the moment.
cpp file
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;
}
}
I read some posts about hashing the value instead, is this a good option? At this point wouldn't be just better to continue using if, else if, else?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
为什么没有字符串的函数图。
然后,您无需转换为枚举。
Why not have a map of string to function.
Then you don't need to convert to an enum.
无论哪种方式,您都进行了许多字符串的比较,并且字符串比较慢。
当您执行IF/else时,如果您有N目标字符串,则平均进行N/2进行比较。因此,4比较了8个关键字。
当您进行
地图
时,这将减少到Log2(n)比较 - 因此,3个条目进行了3个比较。哦,一个额外的向后比较,以检查值是否等于索引。如果两者都不是更少和不大,则必须相等。鉴于地图代码更为复杂,您不会赢,如您所见。有了(许多)更多关键字,您将获得好处。
如果您使用
unordered_map
,则将字符串转换为整数哈希值,并有效地用于直接查找答案。但是,计算哈希是一个缓慢的过程,并且将进行最终比较以确切地匹配所找到的值。还有一个更高的设置成本,为所有关键字产生哈希。在这种特殊情况下,您可以编写自己的哈希函数,该功能只需占据前两个字符,也许会将范围调低,这将比默认的字符串哈希函数快一些。最终的替代方法是进行角色字符查找。如果第一个字符是“ M”,则立即将支票减少到2个选项。 's'还提供了另外2个选项,以及SO-ON。对于这样的小型数据集,只需执行第一个字符过滤器就会有所作为,执行第二个字符可以为您提供独特的检查。这些是简单的字符比较,而不是整个字符串比较,速度更快!
没有微不足道的STDLIB数据结构可以帮助您解决此问题。您可以将其写出为2个嵌套的案例语句:(
作为读者的练习,有一个string :: comparare()会跳过您已经比较的字符),
您可以构建自己的树结构表示这个词查找。如果您添加了跳过树中多个字母的能力,则可以产生一个相当有效的字符串词典查找,该字典的价格仅比单个字符串比较。
另一个选择是,使用字符串/目标对的分类向量,您可以执行自定义的二进制CHOP函数,该功能可以利用搜索跨度中的所有字符串都具有相同的初始字母,并且不需要再比较。在这种情况下,它不会有太大的不同,但是对于数百个关键字,这将比手动案例语句更加可维护。
但是最后,使用
unordered_map
提供的简单哈希表,大多数关键字检测代码都足够快。Either way you are doing a number of string compares, and string compares are slow.
When you do the if/else you are on average doing n/2 compares if you have n target strings. So 4 compares for the 8 keywords.
When you do a
map
, this reduces to log2(n) compares - so 3 compares for 8 entries. Oh and one extra backwards compare to check if the value equals the index. If it is both not less and not greater, then it must be equal.Given the map code is more complex, you don't win, as you have seen. With (many) more keywords to check for, you will get a benefit.
If you use
unordered_map
, then the string is converted into an integer hash value, and that is effectively used to directly look up the answer. Calculating the hash can be a slow process, though, and a final compare will be done to check the found value exactly matches. There is also a higher set-up cost generating the hashes for all the keywords. In this particular case, you could write your own hash function which just takes the first 2 characters, and perhaps trim the range down, which would be somewhat faster than the default string hash function.The final alternative is to do a character-by-character look-up. If the first character is 'm' then you immediately reduce the check to 2 options. 's' gives 2 other options, and so-on. For a small data set like this, just doing that first character filter will make a difference, doing a second character gives you unique checks. These are simple character compares, not whole string compares, so much faster!
There is no trivial stdlib data structure that can help you with this. You could write it out longhand as 2 levels of nested case statements:
(as an exercise for the reader, there is a version of string::compare() that will skip the characters you have already compared)
You can build your own tree structure to represent this word look-up. If you add the ability to skip through multiple letters in the tree you can produce a fairly efficient string dictionary look-up which costs little more than a single string compare.
Another option is that with a sorted vector of string/target pairs you can do a custom binary chop function that takes advantage of knowing that all the strings still in the search span have the same initial letters, and do not need to be compared any more. In this case, it won't make much difference, but with hundreds of keywords, this would be much more maintainable than the manual case statements.
But in the end, most keyword detecting code is fast enough using the simple hash table provided by
unordered_map
.