switch()

Started by
36 comments, last by mikeman 17 years, 10 months ago
Quote:Original post by TANSTAAFL
I'd go the other way, and map strings to directionids, not the other way around.

*** Source Snippet Removed ***

Note: you'll need to either come up with a case insensitive string compare, or else ensure that your strings are first converted to the proper case.


Ugh you beat me to it...
Advertisement
Quote:Original post by Servant of the Lord
Thanks. That seems rather chunky for what seems like a simple thing. Someone should create a varation of switch which acepts most variables.


Some languages offer a construct along these lines, but generally also do not provide fall-through of cases (used normally only when you want the same logic for multiple case values). At this point, it basically becomes syntactic sugar for an if/else-if chain.

The mapping illustrated by Evil Steve is backwards: if you have a string, then you want a map from string to Direction: reverse the types in the declaration, and the items in the initialization (thus stringMap["North"] = North;).

The approach with function objects looks like this, and avoids switch statements altogether:

class DirectionAction {  virtual void operator()();};class NorthAction : public DirectionAction {  void operator()() {    // insert logic for going north here.  }};// etc.// HOWEVER, do note that because these are *objects*, you can instantiate them// several times, and also give them member data. If the logic for going in any// given direction is effectively the same, then you might just use one class,// with a "direction" data member that is initialized by a constructor and// consulted by the operator()().std::map<std::string, DirectionAction*> mapping;// If you can avoid inheritance altogether by the above technique, then you// can store plain objects here and avoid the memory management headache.mapping["North"] = new NorthAction();// etc.std::map<Direction, std::string>::iterator it = stringMap.find(input);if (it != stringMap.end()) {  (*it->second)();}// That is, dereference the iterator to get a key/value pair, select the value// (which is a DirectionObject*), dereference the pointer to get the object,// and "call the object" (invoke its operator()()). Look ma, no switch.


You should probably read this as well.
Quote:Original post by TANSTAAFL
I'd go the other way, and map strings to directionids, not the other way around.

*** Source Snippet Removed ***

Note: you'll need to either come up with a case insensitive string compare, or else ensure that your strings are first converted to the proper case.


I convert all my strings to lowercase for comparison already, so that's no problem. My program, which was a simple text adventure ment to give me experience in classes, has now given me much experience. I'm going to rewrite the majority of it, I think, and I'll create a function for easier string comparisons. Thanks for the source, I'm trying to take all this in as best as I can.

[edit:] Thanks Zahlman.


I think I get the drift of it now. Many thanks for all the help!
#defines are evil, but IMO sometimes it's ok to use them:

#ifndef INC_UTILS_H#define INC_UTILS_H//If SWITCH_C_LIKE is defined, SWITCHes work like C/C++ switches.//Else, they break out as soon as a CASE is evaluated True.//#define SWITCH_C_LIKE#ifdef SWITCH_C_LIKE#define begin_switch(type,var) {bool switch_hit=false;type switch_var;switch_var=var;{#define case_of(val) }if((switch_var==val)||(switch_hit==true)){switch_hit=true;#define case_default }{#define end_switch }}#else#define begin_switch(type,var) {type switch_var;switch_var=var;if(false){#define case_of(val) } else if(switch_var==val) {#define case_default } else {#define end_switch }}#endif#endif


It has worked fine in all occasions that I have tried it, although I'm sure there are flaws that I haven't spotted.
Quote:Original post by mikeman
#defines are evil, but IMO sometimes it's ok to use them:

*** Source Snippet Removed ***

It has worked fine in all occasions that I have tried it, although I'm sure there are flaws that I haven't spotted.


O_O

...

Do *NOT* do that.

Get off my lawn!

Quote:Original post by TANSTAAFL
Quote:Original post by mikeman
#defines are evil, but IMO sometimes it's ok to use them:

*** Source Snippet Removed ***

It has worked fine in all occasions that I have tried it, although I'm sure there are flaws that I haven't spotted.


O_O

...

Do *NOT* do that.


You think so? Why?

Quote:Original post by mikeman
Quote:Original post by TANSTAAFL
Quote:Original post by mikeman
#defines are evil, but IMO sometimes it's ok to use them:

*** Source Snippet Removed ***

It has worked fine in all occasions that I have tried it, although I'm sure there are flaws that I haven't spotted.


O_O

...

Do *NOT* do that.


You think so? Why?


For the same reason you don't use recursion to calculate factorials.

Just because you *CAN* do something a particular way doesn't mean that you *SHOULD*.

Get off my lawn!

You could use atoi() function if you are using C style strings...
Quote:Original post by MARS_999
You could use atoi() function if you are using C style strings...


Only if the strings contained numbers, and any that were invalid numbers would evaluate to zero.

If you want to avoid the complexity of using a map, you could always

enum dirs { north,south,east,west };dirs word_id(string s){    if(s=="north") return north;    // etc}void f(string s){    switch(word_id(s))        {        case north: // etc        }}


although you probably shouldn't since it would be harder to extend and couldn't be changed to support run-time adding of new words etc.
Quote:Original post by TANSTAAFL
Quote:Original post by mikeman
Quote:Original post by TANSTAAFL
Quote:Original post by mikeman
#defines are evil, but IMO sometimes it's ok to use them:

*** Source Snippet Removed ***

It has worked fine in all occasions that I have tried it, although I'm sure there are flaws that I haven't spotted.


O_O

...

Do *NOT* do that.


You think so? Why?


For the same reason you don't use recursion to calculate factorials.

Just because you *CAN* do something a particular way doesn't mean that you *SHOULD*.


That still doesn't explain why I *SHOULDN'T* use these particular macros. Recursion for factorials adds unnessecery complexity, but here, all these macros do is basically produce the same chain of if...else if you would write yourself by hand. Apart from the minor fact that you can't have variables named "switch_var" and "switch_hit", what exactly is wrong with them? Is the interface hard to grasp, unintuitive? Are they overly slow? Do they cause the stack to overflow? Do they break something else while trying to solve the problem?

This topic is closed to new replies.

Advertisement