0

Possible Duplicate:
C/C++: switch for non-integers
C/C++ switch case with string

I am passing a string to a function get_band(char *str) Then I am comparing the passed argument with a specific string

if(strcmp(str, "auto"))
{
  //do something
}

My question is - since i have many number of strings to compare, how can i use switch statement instead of if/else, since switch statement supports only integral type.

Community
  • 1
  • 1
Angel
  • 191
  • 4
  • 4
  • 12

6 Answers6

4

Short answer: you can't.

Long answer: this question is a duplicate of C/C++ switch case with string.

Community
  • 1
  • 1
Giovanni Funchal
  • 8,934
  • 13
  • 61
  • 110
  • I agree about duplication, though the linked answer specifies a hash. That's one way to tokenize strings, but not the best IMHO, unless you're ready to handle collisions (i.e. two strings hashing to the same value). – Lee-Man Nov 28 '11 at 22:37
  • Add the suggestion of Ben Voigt, more info on tokenizing strings. You might consider using a lexical analyzer, such as flex(1), to easily turn your stream of strings into a stream of tokens, since such tokens can easily be switched upon. – Lee-Man Nov 29 '11 at 17:07
3

You could do:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *words[] = {"one", "two", "four"}; // words is an array of pointers to char

void f(char *str);

int main(void) {
    f("two");
    return 0;
}

void f(char *str) {

    int i;
    for (i = 0; i < sizeof words/sizeof words[0]; i++) {
        if (!strcmp(str, words[i])) {
            /* Do something */
        }
    }
}
Herrington Darkholme
  • 5,979
  • 1
  • 27
  • 43
Marcos
  • 4,643
  • 7
  • 33
  • 60
1

No, switch only works for integers.

If you want to optimize, you can use some data structure to determine if the string is any of the known strings. For example:

To make use of such a data structure, assign each known string a constant integer (e.g. define or enum); given a string, you can use the data structure to map it to some number of a known string (possibly with some number meaning "unknown"). Then you can use a switch on this number and do whatever you want for each case.

You can find an existing implementation of any of the above, but if you're new to C, it might be beneficial to implement it yourself.

Ambroz Bizjak
  • 7,809
  • 1
  • 38
  • 49
0

A switch statement branches based on evaluating the following expression.

In your case, strcmp only promises to return less than zero, zero, or greater than zero. Even if you assume that means -1, 0, and 1 (respectively), that would mean you would only have 3 values you could choose from in your switch cases. [And that is not a safe assumption, by the way ...]

Instead, if your strings are taken from a closed set of strings (i.e. can only have one of set of values), you could tokenize the string. There are actually programs to do this for you, i.e. turns strings into tokens. (See flex(1).) This would mean that each string you expected would have some unique value, and you could switch on that value.

If this is too much trouble, just use the method you used in your question, i.e.:

if (strcmp("some string", str) == 0) {
   // handle some string
} else if strcmp("some other string", str) == 0) {
   // handle alternate case here

...

} else {
   // handle error/default case here
}
Lee-Man
  • 374
  • 1
  • 8
  • 1
    You should probably go add an answer regarding lexers (discrete finite automata, typically) to one of the related questions, since this one is an exact duplicate it will soon be consigned to the dustbin of history. – Ben Voigt Nov 28 '11 at 23:50
0

Consider changing the logic of your program to use enums instead of strings. You can then use an array look up to map the integer enums to the corresponding string for display and logging purposes. The other options including hash etc have been covered.

RichieHH
  • 2,116
  • 4
  • 28
  • 30
0

The switch statement in C / C++ accepts only three case types : integers, characters and enumerated data types (which is effectively another way of saying integer). Characters also reduce to integers when evaluated as ascii codes.

@Nikolai N Fetissov made a good suggestion : switch on a hash of the string :

#define hashOfString1 <integer hash goes here>
#define hashOfString2 <integer hash goes here>
#define hashOfString3 <integer hash goes here>

. . .

switch (hashMyString("MyString")) {
  case hashOfString1:
    /* do this */
    break;
  case hashOfString2:
    /* do that */
    break;
  case hashOfString3:
    /* do other */
    break;
  default:
    /* default behavior */
    break;
}
Literati Insolitus
  • 508
  • 2
  • 6
  • 13
  • 1
    this is wrong, you need to handle hash collisions here, e.g. in each case, "if (strcmp(string, ThisString)) goto default;". Also, it won't work at all if any of the known strings have the same hash (unlikely). – Ambroz Bizjak Nov 28 '11 at 22:56
  • 1
    As soon as you say the word hash you are aware of the non-zero possibility of hash collisions, that is why you select a hash that distributes inputs across a very large space compared to the input number. The way I have implemented this catches collisions prior even to program compilation (if Angel detects an identical hash prior to defining the hash values they can try an alternate hash). – Literati Insolitus Nov 28 '11 at 23:10
  • 1
    Sure you can handle collisions between hashes of known words in advance. But it seems much harder to me to make sure that for a given known String1, there is *no* other string (any, not just one of the known ones) with the same hash. For an arbitrary hash function, this is not possible, because you'd have to check an infinite number of strings. I'm guessing you need a special kind of hash function where these collisions can be avoided in advance. Still, adding a simple check after each case will make this right, assuming collisions between known strings have been resolved. – Ambroz Bizjak Nov 29 '11 at 00:29