Click to See Complete Forum and Search --> : Strings in switch statements
Tom Hirst
December 13th, 2001, 05:40 PM
I need a section of code which selects an action based on s 3 character string and a switch statement cannot be used with string values. I was working on converting the string to an integer but am not sure how to do this for the case values, as these must be converted and made constant at compile time. Can anyone help me?
TekBoy
December 13th, 2001, 08:26 PM
for strings, I do not recommend a switch statement. Just use many if... else if.... else if.... statements!
if ( !strcmp( string, "action1" ) ) {
/* do something */
}
else
if ( !strcmp( string, "action2" ) ) {
/* do something */
}
else
if ( !strcmp( string, "action3" ) ) {
/* do something */
}
Paul McKenzie
December 13th, 2001, 10:12 PM
If you are programming in C++ use a map of strings to integers:
#include <map>
#include <string>
using namespace std;
typedef map<string, int> StringToIntMap;
//...
StringToIntMap MyMap;
int main()
{
MyMap["abc"] = 1;
MyMap["def"] = 2;
MyMap{"123"] = 3;
//.. Somewhere else in your code, instead of switch do this:
// Assume "str" variable contains the string
StringToIntMap::iterator it = MyMap.find(str);
if ( it != MyMap.end() )
{
switch((*it).second)
{
case 1: // This is the "abc"
break;
case 2: // This is the "def"
break;
case 3: // This is the "123:
break;
}
}
}
So basically you are mapping each of the strings to a known value. Then you are using the find() member to search for a particular string in the map. The find() function returns a data structure called a "pair". The pair consists of two members -- the "first" is the key (which is the string), and the "second" is the integer that you associated with the string.
Whenever you encounter this type of scenario of doing a switch on a non-integral type, use the map approach of associating the non-integer data to an actual integer.
Regards,
Paul McKenzie
Paul McKenzie
December 13th, 2001, 10:13 PM
If it is C++, use a map. See my post.
Regards,
Paul McKenzie
NMTop40
December 14th, 2001, 04:40 AM
there is a whole article on the C++ pages (if anyone here actually goes to them as well as the discussion forums)
someone submitted an article about creating a map.
if you are going to create a map, do it static in the function (in my opinion).
however if there are only 3 options, it is wasteful, as it won't be any faster than a number of comparisons. incidentally if you are using comparisons you might want to do
if (str=="abc" ) etc rather than using strcmp.
and if there are a very large number, you may prefer to make a map of strings to function pointers, rather than to integers and then do a switch on the integer.
one final alternative is to find a hash function that produces a different value for each string in your case statement. The hash the input string and do a case on the results. You'll still need to do one comparison as there is a chance someone has given you a different string.
The hash function should be something very basic - maybe something like "nth_char" (below)
inline char nth_char( const char *str, int n )
{
return ( (strlen(str) <= n ) ? 0 : str[n] );
}
or a combination of two letters (more likely to get uniqueness)
inline unsigned short char_m_n( const char *str, int m, int n )
{
int len = strlen( str );
short val = 0;
if ( m < len )
{
val = (unsigned short)str[m];
val <<= 8;
}
if ( n < len )
{
val |= str[n];
}
}
This last example is, for example, unique on the twelve months of the year on their 2nd and 3rd characters. Not only that but you can allow short versions too, as you can compare a hash value of 0x6172 ('ar', and it will accept 'ar' by the way) with both "Mar" or "March".
NMTop40
December 14th, 2001, 05:05 AM
by the way the other link is here:
http://www.codeguru.com/cpp_mfc/SwitchOnStrings.html
Tom Hirst
December 16th, 2001, 01:30 PM
This is helpfull but what I wanted was a way of having the following type of code
int value = HashFunction(String);
switch(value)
{
case HashFunction("Value 1"): ....
}
For this to work it would require the HashFunction to give a int at compile time if the parameter was a constant value. Is there anyway of doing this?
Andreas Masur
December 16th, 2001, 02:04 PM
No the case expressions MUST be an integral constant...
Ciao, Andreas
"Software is like sex, it's better when it's free." - Linus Torvalds
Tom Hirst
December 16th, 2001, 02:12 PM
I know, what I'm asking is can a hash function or macro be made to convert a constant string to an integral constant when it is compiled. This would help to improve readability.
NMTop40
December 16th, 2001, 05:18 PM
i gave a solution which you rated 10 (well someone did) but you continued to ask the question anyway.
having worked out the hash values in advance for the strings you are testing, you can indeed also make up names for them, either with #define or enums (latter being preferable)
However after hashing you still have to check that the string submitted didn't succeed by chance.
For example, if using my formula of the 2nd and 3rd letter of the word for months of the year, if someone passed in "Sunday" that would not be a correct month of the year, but the 2nd and 3rd letter are the same as that of "June".
codeguru.com
Copyright Internet.com Inc., All Rights Reserved.