带字符串的 C/C++ switch case
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4480788/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C/C++ switch case with string
提问by Luke
Possible Duplicate:
C/C++: switch for non-integers
可能的重复:
C/C++:切换非整数
Hi, I need to use a string in switch case. My solution so far was to calculate the hash of the string with my hash function. Problem is I have to manually pre-calculate all my hash values for strings. Is there a better approach?
嗨,我需要在 switch case 中使用字符串。到目前为止,我的解决方案是使用我的哈希函数计算字符串的哈希值。问题是我必须手动预先计算所有字符串的哈希值。有没有更好的方法?
h=_myhash (mystring);
switch (h)
{
case 66452:
.......
case 1342537:
........
}
回答by tenfour
Just use a if() { } else if () { }
chain. Using a hash value is going to be a maintenance nightmare. switch
is intended to be a low-level statement which would not be appropriate for string comparisons.
只需使用if() { } else if () { }
链条。使用哈希值将是维护的噩梦。switch
旨在成为不适合字符串比较的低级语句。
回答by Tony
You could map the strings to function pointer using a standard collection; executing the function when a match is found.
您可以使用标准集合将字符串映射到函数指针;找到匹配项时执行该函数。
EDIT: Using the example in the article I gave the link to in my comment, you can declare a function pointer type:
编辑:使用我在评论中提供链接的文章中的示例,您可以声明一个函数指针类型:
typedef void (*funcPointer)(int);
and create multiple functions to match the signature:
并创建多个函数来匹配签名:
void String1Action(int arg);
void String2Action(int arg);
The map would be std::string
to funcPointer
:
地图是std::string
到funcPointer
:
std::map<std::string, funcPointer> stringFunctionMap;
Then add the strings and function pointers:
然后添加字符串和函数指针:
stringFunctionMap.add("string1", &String1Action);
I've not tested any of the code I have just posted, it's off the top of my head :)
我还没有测试过我刚刚发布的任何代码,它超出了我的脑海:)
回答by Puppy
Typically, you would use a hash table and function object, both available in Boost, TR1 and C++0x.
通常,您会使用 Boost、TR1 和 C++0x 中提供的哈希表和函数对象。
void func1() {
}
std::unordered_map<std::string, std::function<void()>> hash_map;
hash_map["Value1"] = &func1;
// .... etc
hash_map[mystring]();
This is a little more overhead at runtime but a bajillion times more maintainable. Hash tables offer O(1) insertion, lookup, and etc, which makes them the same complexity as the assembly-style jump-table.
这在运行时会增加一点开销,但更易于维护。哈希表提供 O(1) 插入、查找等,这使得它们与组装式跳转表具有相同的复杂性。
回答by ruslik
The best way is to use source generation, so that you could use
最好的方法是使用源代码生成,这样你就可以使用
if (hash(str) == HASH("some string") ..
in your main source, and an pre-build step would convert the HASH(const char*)
expression to an integer value.
在您的主要源代码中,预构建步骤会将HASH(const char*)
表达式转换为整数值。
回答by Sergei Tachenov
Ruslik's suggestion to use source generation seems like a good thing to me. However, I wouldn't go with the concept of "main" and "generated" source files. I'd rather have one file with code almost identical to yours:
Ruslik 建议使用源代码生成对我来说似乎是一件好事。但是,我不会采用“主要”和“生成”源文件的概念。我宁愿有一个代码与您几乎相同的文件:
h=_myhash (mystring);
switch (h)
{
case 66452: // = hash("Vasia")
.......
case 1342537: // = hash("Petya")
........
}
The next thing I'd do, I'd write a simple script. Perl is good for such kind of things, but nothing stops you even from writing a simple program in C/C++ if you don't want to use any other languages. This script, or program, would take the source file, read it line-by-line, find all those case NUMBERS: // = hash("SOMESTRING")
lines (use regular expressions here), replace NUMBERS with the actual hash value and write the modified source into a temporary file. Finally, it would back up the source file and replace it with the temporary file. If you don't want your source file to have a new time stamp each time, the program could check if something was actually changed and if not, skip the file replacement.
接下来我要做的就是写一个简单的脚本。Perl 非常适合这类事情,但是如果您不想使用任何其他语言,那么即使使用 C/C++ 编写一个简单的程序,也没有什么可以阻止您的。该脚本或程序将获取源文件,逐行读取,找到所有这些case NUMBERS: // = hash("SOMESTRING")
行(此处使用正则表达式),用实际哈希值替换 NUMBERS,并将修改后的源写入临时文件。最后,它会备份源文件并将其替换为临时文件。如果你不希望你的源文件每次都有一个新的时间戳,程序可以检查某些东西是否真的改变了,如果没有,跳过文件替换。
The last thing to do is to integrate this script into the build system used, so you won't accidentally forget to launch it before building the project.
最后要做的是将此脚本集成到所使用的构建系统中,这样您就不会在构建项目之前意外忘记启动它。
回答by Magnus Andermo
There is no good solution to your problem, so here is an okey solution ;-)
您的问题没有好的解决方案,所以这里有一个很好的解决方案;-)
It keeps your efficiency when assertions are disabled and when assertions are enabled it will raise an assertion error when the hash value is wrong.
当断言被禁用时它会保持你的效率,当断言被启用时它会在哈希值错误时引发断言错误。
I suspect that the D programming language could compute the hash value during compile time, thus removing the need to explicitly write down the hash value.
我怀疑 D 编程语言可以在编译时计算散列值,从而消除了明确写下散列值的需要。
template <std::size_t h>
struct prehash
{
const your_string_type str;
static const std::size_t hash_value = h;
pre_hash(const your_string_type& s) : str(s)
{
assert(_myhash(s) == hash_value);
}
};
/* ... */
std::size_t h = _myhash(mystring);
static prehash<66452> first_label = "label1";
switch (h) {
case first_label.hash_value:
// ...
;
}
By the way, consider removing the initial underscore from the declaration of _ myhash()(sorry but stackoverflow forces me to insert a space between _ and myhash). A C++ implementation is free to implement macros with names starting with underscore and an uppercase letter (Item 36 of "Exceptional C++ Style" by Herb Sutter), so if you get into the habit of giving things names that start underscore, then a beautiful day could come when you give a symbol a name that starts with underscore and an uppercase letter, where the implementation has defined a macro with the same name.
顺便说一下,考虑从 _ myhash()的声明中删除初始下划线(抱歉,stackoverflow 迫使我在 _ 和 myhash 之间插入一个空格)。C++ 实现可以自由地实现名称以下划线和大写字母开头的宏(Herb Sutter 的“Exceptional C++ Style”的第 36 项),所以如果你习惯给事物命名以下划线开头,那么美好的一天当你给一个符号一个以下划线和一个大写字母开头的名字时可能会出现,其中实现定义了一个具有相同名称的宏。
回答by sriks
You can use enumeration and a map, so your string will become the key and enum value is value for that key.
您可以使用枚举和映射,因此您的字符串将成为键,枚举值是该键的值。
回答by Milan
If you are after performance and don't want to go through all the if
clauses each time if there are many or the need to hash the values, you could send some extra information to the function with the help of enum
or just add an enum
type to your structure.
如果你是演出结束后,不希望通过所有去if
,如果有很多还是需要哈希值每一次的条款,你可以发送一些额外的信息功能的帮助下enum
,或只是增加一个enum
类型的结构体。
回答by Wang
You could use the string to index into a hash table of function pointers.
您可以使用该字符串索引到函数指针的哈希表中。
Edit: glib has a hash table implementation that supports strings as keys and arbitrary pointers as values: http://library.gnome.org/devel/glib/stable/glib-Hash-Tables.html
编辑:glib 有一个哈希表实现,支持字符串作为键和任意指针作为值:http: //library.gnome.org/devel/glib/stable/glib-Hash-Tables.html
回答by zsalzbank
You could create a hashtable. The keys can be the string and the value can be and integer. Setup your integers for the values as constants and then you can check for them with the switch
.
您可以创建一个哈希表。键可以是字符串,值可以是整数。将值的整数设置为常量,然后您可以使用switch
.