473,666 Members | 2,144 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

switch statement - ANSI-C

Hi,

A simple question: In ANSI-C, how to specify a string as the expression
for switch statement.

eg

switch (mystr) {
case "ABC" : bleh...
break;
case "DEF" : bleh
break'
default: bleh;
break;
}

AFAIK, the expression must produce an integer value. In the case of a
string, what is the work-around?

Aaron

Dec 27 '06 #1
21 7719
Q: How do I switch on strings?

The simple answers are:
a) don't use switch. use if/else with strcmp
b) make an array of possible strings and use a lookup function to
return the index of your string (or -1) and switch on that.

The most common time I face this sort of thing is parsing config files
for tokens. The approach I take is an enhancement to the simple answer
b) above, using a structure consisting of an enumeration of index
values associated with the string. The enum makes it handy to add new
keys without having to worry about index numbers as opposed to having
case 1:, case 2: to go update. Here's an example for a few strings:

typedef enum
{
eKEY_HOST = 0,
eKEY_PORT, /* implicitly = 1 ... etc */
eKEY_PROTO,
eNUM_KEYS, /* number of valid keys */
eKEY_INVALID
} cfg_key_names;

/* array of structures to map the enum (numerical) values to strings */
struct {
cfg_key_names id;
const char *str;
} cfg_keys[] = {
{ eKEY_HOST, "host" },
{ eKEY_PORT, "port" },
{ eKEY_PROTO, "proto" }
};

/* get the number of entries in the above array automatically */
int n_cfg_keys = sizeof(cfg_keys ) / sizeof(cfg_keys[0]);

/* lookup function */
int parse_cfg_key(c onst char *str)
{
int i;
for (i = 0; i < n_cfg_keys; i++)
if (strcmp(str, cfg_keys[i].str) == 0)
return cfg_keys[i].id;

return eKEY_INVALID;
}

switch (parse_cfg_key( some_str))
{
case eKEY_HOST:
/* ... */
break;
default:
case eKEY_INVALID:
/* NO STRING FOR YOU! */
break;
}

Hope that helps.

Dec 27 '06 #2
aa******@yahoo. com.au said:
Hi,

A simple question: In ANSI-C, how to specify a string as the expression
for switch statement.
You can't, but keep reading, because there is a way around this.
eg

switch (mystr) {
case "ABC" : bleh...
break;
case "DEF" : bleh
break'
default: bleh;
break;
}

AFAIK, the expression must produce an integer value. In the case of a
string, what is the work-around?
Associate each string with an integer (a struct works well here), preferably
in a sorted container of some kind (sorted array, or BST, or hash table, or
something of the kind), to make retrieval quicker. Look up the string, find
the associated number, and switch on that instead.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 27 '06 #3
"typedef" <ty************ @gmail.comwrote :
Q: How do I switch on strings?

The simple answers are:
a) don't use switch. use if/else with strcmp
b) make an array of possible strings and use a lookup function to
return the index of your string (or -1) and switch on that.
c) Use a hash.

Richard
Dec 27 '06 #4

"typedef" <ty************ @gmail.comha scritto nel messaggio
news:11******** *************@i 12g2000cwa.goog legroups.com...
Q: How do I switch on strings?

The simple answers are:
a) don't use switch. use if/else with strcmp
b) make an array of possible strings and use a lookup function to
return the index of your string (or -1) and switch on that.

The most common time I face this sort of thing is parsing config files
for tokens. The approach I take is an enhancement to the simple answer
b) above, using a structure consisting of an enumeration of index
values associated with the string. The enum makes it handy to add new
keys without having to worry about index numbers as opposed to having
case 1:, case 2: to go update. Here's an example for a few strings:

typedef enum
{
eKEY_HOST = 0,
eKEY_PORT, /* implicitly = 1 ... etc */
eKEY_PROTO,
eNUM_KEYS, /* number of valid keys */
eKEY_INVALID
} cfg_key_names;

/* array of structures to map the enum (numerical) values to strings */
struct {
cfg_key_names id;
const char *str;
} cfg_keys[] = {
{ eKEY_HOST, "host" },
{ eKEY_PORT, "port" },
{ eKEY_PROTO, "proto" }
};

/* get the number of entries in the above array automatically */
int n_cfg_keys = sizeof(cfg_keys ) / sizeof(cfg_keys[0]);
And for checking:

char only_for_check[2 * (sizeof(cfg_key s) / sizeof(cfg_keys[0]) ==
eNUM_KEYS) - 1];

/*
* in this case "n_cfg_keys " is not necessary
*/
>
/* lookup function */
int parse_cfg_key(c onst char *str)
{
int i;
for (i = 0; i < n_cfg_keys; i++)
if (strcmp(str, cfg_keys[i].str) == 0)
return cfg_keys[i].id;

return eKEY_INVALID;
}

switch (parse_cfg_key( some_str))
{
case eKEY_HOST:
/* ... */
break;
default:
case eKEY_INVALID:
/* NO STRING FOR YOU! */
break;
}
If you have found the index, the work is done.
It is possible to add a function field to the
struct to avoid the switch.

x = parse_cfg_key(s ome_str);
if (x != eKEY_INVALID) {
(*cfg_keys[x].fun)(); /* or with arguments */
} else {
/* ... */
}

The "id" field is not necessary if you respect the order:

struct str_and_fun_onl y {
const char *str;
void (*fun)(void);
};

"parse_cfg_ key" can return directly 'i'.

--
Giorgio Silvestri
DSP/Embedded/Real Time OS Software Engineer

Dec 27 '06 #5

Richard Bos wrote:
"typedef" <ty************ @gmail.comwrote :
Q: How do I switch on strings?

The simple answers are:
a) don't use switch. use if/else with strcmp
b) make an array of possible strings and use a lookup function to
return the index of your string (or -1) and switch on that.

c) Use a hash.

Richard
That inspired an entry on The Daily WTF. I wouldn't recommend it
myself.

Dec 27 '06 #6

aa******@yahoo. com.au wrote:
Hi,

A simple question: In ANSI-C, how to specify a string as the expression
for switch statement.

eg

switch (mystr) {
case "ABC" : bleh...
break;
case "DEF" : bleh
break'
default: bleh;
break;
}

AFAIK, the expression must produce an integer value. In the case of a
string, what is the work-around?
After 16 years, I've become an advocate for simplicity. Any workaround
that allows you to use a switch is just going to bog you down in extra
work and complexity, so I'd advocate ditching the switch statement
entirely and just going with

if (!strcmp(mystr, "ABC"))
{
/* do stuff */
}
else if (!strcmp(mystr, "DEF"))
{
/* do stuff */
}
...
else
{
/* do default */
}

Dec 27 '06 #7
John Bode said:
>
aa******@yahoo. com.au wrote:
>Hi,

A simple question: In ANSI-C, how to specify a string as the expression
for switch statement.

eg

switch (mystr) {
case "ABC" : bleh...
break;
case "DEF" : bleh
break'
default: bleh;
break;
}

AFAIK, the expression must produce an integer value. In the case of a
string, what is the work-around?

After 16 years, I've become an advocate for simplicity. Any workaround
that allows you to use a switch is just going to bog you down in extra
work and complexity, so I'd advocate ditching the switch statement
entirely and just going with

if (!strcmp(mystr, "ABC"))
{
/* do stuff */
}
else if (!strcmp(mystr, "DEF"))
{
/* do stuff */
}
...
else
{
/* do default */
}
That's a perfectly reasonable alternative, but what if you have a great many
cases? It's not a very scalable solution. You can, of course, use the
result of strcmp:

diff = strcmp(mystr, "MNO");
if(diff == 0)
{
/* whatever */
}
else if(diff < 0)
{
/* handle cases "AAA" to "MNN" */
diff = strcmp(mystr, "HIJ");
if(diff == 0) etc etc
}
else
{
/* handle cases "MNP" to "ZZZ" */
diff = strcmp(mystr, "RST");
if(diff == 0) etc etc
}

but really, if you have so many cases as to make this worth doing, you're
better off with a bunch of string/functionptr structs in a sorted array, a
tree, or a hashtable.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at the above domain, - www.
Dec 27 '06 #8
<aa******@yahoo .com.auwrote in message
news:11******** **************@ 42g2000cwt.goog legroups.com...
Hi,

A simple question: In ANSI-C, how to specify a string as the expression
for switch statement.

eg

switch (mystr) {
case "ABC" : bleh...
break;
case "DEF" : bleh
break'
default: bleh;
break;
}

AFAIK, the expression must produce an integer value. In the case of a
string, what is the work-around?
You can't. Other posters have made great suggestions. I'll make more.

The disadvantage of else-if is of course that the execution time to match
one of the last clauses will be longest of all. Depends on how many you
have. I have a couple suggestions, all of which will get me boo'd on this
group.

#1
---
Make the compiler work for a living:

switch(mystr[0])
{
case 'A' :
{
switch (mystr[1])
{
//And nest arbitrarily deeply.
#2
---
Standard BSEARCH, with the table of strings ordered in the source code. You
can include a function pointer as part of the table. That, at least is
O(log N) rather than O(N).

http://en.wikipedia.org/wiki/Bsearch

---------

The suggestions by the other posters involving hashing were of course very
good ... but BSEARCH seems easier and cleaner. For one thing, no hash
collisions to worrry about.

Dave.

Dec 27 '06 #9
David T. Ashley wrote:
<aa******@yahoo .com.auwrote in message
news:11******** **************@ 42g2000cwt.goog legroups.com...
Hi,

A simple question: In ANSI-C, how to specify a string as the expression
for switch statement.

You can't. Other posters have made great suggestions. I'll make more.
[...]
The suggestions by the other posters involving hashing were of course very
good ... but BSEARCH seems easier and cleaner. For one thing, no hash
collisions to worrry about.
If you use a hash function generator such as gperf, you have no hash
collisions to worry about either.

Dec 27 '06 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
10904
by: Myster Ious | last post by:
Polymorphism replaces switch statements, making the code more compact/readable/maintainable/OO whatever, fine! What I understand, that needs to be done at the programming level, is this: a switch-case has a variable (most probably an enumeration) & associated symbols or integral value. Selection is made, base on what symbol/value the variable holds. So
35
8331
by: Thomas Matthews | last post by:
Hi, My son is writing a program to move a character. He is using the numbers on the keypad to indicate the direction of movement: 7 8 9 4 5 6 1 2 3 Each number has a direction except for '5'. So in his switch statement, he omits a case for '5':
18
3447
by: Minti | last post by:
I was reading some text and I came across the following snippet switch('5') { int x = 123; case '5': printf("The value of x %d\n", x); break; }
24
4375
by: Mark | last post by:
Hi - how can I get a switch statement to look for a range of values? I have: function payCalc(field, field2) switch(field.value) { case 0-50: field2.value="lower band"; case 51-99: field2.value="mid band"; case 100-9999: field2.value="high band";
8
1506
by: pickedaname | last post by:
I work for a telecom company. We need to get data from our 5ESS switches to be consumed by a .NET app. The data I am getting back is incomplete. For example, the beginning of the first line recvd from the device should read: SWT5 5e16(2) 02.00 Instead I get a bunch of gibberish then SWT5
12
12317
by: | last post by:
Is it fine to call another method from Switch? Eg. Switch (stringVar) { case ("a"): somVar = "whatever"; Another_Method(); //call another method return;
46
3009
by: ajba74 | last post by:
Hi fellows, I am reading some books to learn the C programming language, and sometimes I have the feeling that when somebody becomes a C expert, he must learn a more modern and object-oriented language. When I read things like "... C++ is an evolution of C ..." or "... C is a subset of C++ ..." I tend to believe that I will have to learn C+ + sooner or later. It sounds like C++ is the future and C is the past (and will be no longer...
7
3356
by: Rohit | last post by:
Hi, I am working on a switch module which after reading voltage through a port pin and caterogizing it into three ranges(open,low or high), passes this range to a function switch_status() with parameters value and signal ID. Signal Id is used to get a user configurable parameter inside a configuration file, which depends on the type of switch. I have implemented it as under. Please ignore those magic numbers as I have mimized logic to...
13
11808
by: Satya | last post by:
Hi everyone, This is the first time iam posting excuse me if iam making any mistake. My question is iam using a switch case statement in which i have around 100 case statements to compare. so just curious to find out is it effective to use this method?? or is there is any other alternative method present so that execution time and code size can be reduced?? Thanks in advance.
0
8444
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8356
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
8869
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
8781
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
1
6198
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
5664
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
4198
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
1
2771
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1775
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.