我有以下代码
#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
定义为全局(main
之外)
答案 0 :(得分:8)
完全删除宏,并以“扩展”方式写入,将声明移到顶部。这些宏很可怕。
如果失败,请调整SWITCH
以引入新范围(第二个{
)。这当然会迫使你必须关闭两个范围,所以也许最后要添加一个SWITCH_END
憎恶来封装它。不管。
答案 1 :(得分: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;
}
答案 2 :(得分: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
,那么编写一个为每个字符串返回一个键的哈希函数可能会更好,并打开结果:
#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;
}