0

我有以下代码

#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;
    }
}

如果我用 生成预处理器代码gcc -E,我将得到以下代码

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");
        };
    }
}

但是对于一些char *_S = buf;在代码中间定义的 gcc 是不受欢迎的,并且可能会提供编译错误

如何在我的宏中解决这个问题?

请不要建议定义char *_S为全局(out of the main

4

3 回答 3

8

不好了!!!

我在这篇文章中写了这个作为一个笑话

不要使用它是非常非常可怕的,如果你想避免 if-else 你可以在不折磨编译器的情况下做到这一点,考虑使用一对字符串:

#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;
}
于 2013-01-09T09:38:37.367 回答
8

完全删除宏,并以“扩展”方式编写,将声明移到顶部。这些宏太可怕了。

做不到这一点,调整SWITCH以引入一个新的范围(第二个{)。这当然会迫使你不得不关闭两个范围,所以也许SWITCH_END在最后添加一个可憎的东西来封装它。任何。

于 2013-01-08T16:10:30.113 回答
1

确保代码被编译为 C99 或更高版本;否则,您将需要使用不同的控制结构。

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

  SWITCH(buf)
  {
    ...
  }

#else

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

#endif

使用预处理器来“改变”或扩展 C 语法通常不是一个好主意(我有疤痕组织来证明);switch没有在字符串表达式上定义是有原因的。

如果你真的switch在这种情况下使用 a ,那么最好编写一个哈希函数来为每个字符串返回一个键,然后打开结果:

#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;
}
于 2013-01-08T16:30:32.027 回答