c语言duplicate case,C/C++ switch case with string [duplicate]

可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):

问题:

Possible Duplicate:

C/C++: switch for non-integers

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?

h=_myhash (mystring);

switch (h)

{

case 66452:

.......

case 1342537:

........

}

回答1:

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.

回答2:

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::map<: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 :)

回答3:

Typically, you would use a hash table and function object, both available in Boost, TR1 and C++0x.

void func1() {

}

std::unordered_map<:string std::function>> 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.

回答4:

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.

回答5:

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

回答6:

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.

回答7:

You can use enumeration and a map, so your string will become the key and enum value is value for that key.

回答8:

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.

回答9:

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.

template <: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.

回答10:

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:

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.

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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值