How to switch and case for string?

左心房为你撑大大i 提交于 2021-02-08 10:14:01

问题


I have the following code

#define SWITCH(S) char *_S = S; if (0)
#define CASE(S) } else if (strcmp(_S, S) == 0) {switch(1) { case 1
#define BREAK }
#define DEFAULT } else {switch(1) { case 1

int main()
{
    char buf[256];

    printf("\nString - Enter your string: ");
    scanf ("%s", buf);

    SWITCH (buf) {
        CASE ("abcdef"):
            printf ("B1!\n");
            BREAK;
        CASE ("ghijkl"):
            printf ("C1!\n");
            BREAK;
        DEFAULT:
            printf ("D1!\n");
            BREAK;
    }
}

If I generate the pre-processor code with gcc -E, I will get the following code

int main()
{
    char buf[256];

    printf("\nString - Enter your string: ");
    scanf ("%s", buf);

    char *_S = buf;
    if (0) {
    } else if (strcmp(_S, "abcdef") == 0) {switch(1) { case 1:
        printf ("B1!\n");
        };
    } else if (strcmp(_S, "ghijkl") == 0) {switch(1) { case 1:
        printf ("C1!\n");
        };
    } else {switch(1) { case 1:
        printf ("D1!\n");
        };
    }
}

But for some gcc defining char *_S = buf; in the middle of the code is not wolcome and could provide compilation error

How to fix that in my macro?

Please do not suggest to define char *_S as global (out of the main)


回答1:


Remove the macros altogether, and write it in the "expanded" way, moving the declaration to the top. These macros are horrific.

Failing that, tweak SWITCH to introduce a new scope (a second {). This will of course force you to have to close two scopes, so perhaps add a SWITCH_END abomination to use at the end, to encapsulate that. Whatever.




回答2:


Oh no!!!

I wrote this as a joke in this post

Don't use it is very very horrific, if you want to avoid if-else you can do it without torturing the compiler, consider using pair of strings:

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

int main(void)
{
    char buf[256];
    const char *ap[] = {
        "abcdef", "B1!\n",
        "ghijkl", "C1!\n",
        NULL    , "D1!\n",
    }, **p = ap;

    printf("\nString - Enter your string: ");
    scanf ("%s", buf);
    while (*p) {
        if (strcmp(buf, *p) == 0) break;
        p += 2;
    }
    printf("%s", *(++p));
    return 0;
}



回答3:


Make sure the code is being compiled as C99 or later; otherwise, you will need to use a different control structure.

#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L

  SWITCH(buf)
  {
    ...
  }

#else

  if (strcmp(buf, "abcdef") == 0)
  {
    ...
  }
  else if (strcmp (buf, "ghijkl") == 0)
  {
    ...
  }
  else
  {
    ...
  }

#endif

It's generally not a good idea to use the preprocessor to "alter" or extend C syntax (I have the scar tissue to prove it); switch isn't defined on string expressions for a reason.

If you really want to use a switch in this situation, then it may be better to code up a hash function that returns a key for each string, and switch on the result:

#define ABCDEF ... // hash key generated for "abcdef"
#define GHIJKL ... // hash key generated for "ghijkl"
...
switch(hash(buf))
{
  case ABCDEF :
     ...
     break;

  case GHIJKL :
     ...
     break;

  default:
     ...
     break;
}


来源:https://stackoverflow.com/questions/14219156/how-to-switch-and-case-for-string

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!