C开关/情况宏,多个情况

3

我知道大多数人都会说这很糟糕。

我编写了以下宏,以便使用字符串而不是if/else if/else轻松编写开关:

#define str_switch( value )                                    \
do {                                                           \
    const char * __strswitchptr__ = (value);                   \
    if( 0 )                                                    \

#define str_case( test )                                       \
    } if( strcmp( __strswitchptr__, (test) ) == 0 ) {          \

#define str_default                                            \
    } else {                                                   \

#define str_switchend                                          \
} while( 0 );                                                  \

我是这样使用的:

char * sVal =  "D";

str_switch( sVal )
{
str_case( "A" )
    printf( "Case A" );
    break;
str_case( "B" )
    printf( "Case B" );
    break;
str_case( "C" )
    printf( "Case C" );
    break;
str_default
    printf( "Error" );
}
str_switchend

但我不知道如何修改它,以便我可以使用多个案例:

char * sVal =  "D";

str_switch( sVal )
{
str_case( "A" )
    printf( "Case A" );
    break;
str_case( "B" )
    printf( "Case B" );
    break;
str_case( "C" )
str_case( "D" )
str_case( "E" )
    printf( "Case C" );
    break;
str_default
    printf( "Error" );
}
str_switchend

有任何想法吗?谢谢 :-)

1
因为 switch 仅进行整数比较。 - Oliver Matthews
1
据我所知,您无法使用C switch比较字符串。 - Virus721
2
只是一点小提示:__strswitchptr__ 是被标准保留的。你可以使用 _strswitchptr,它是保留给文件作用域标识符的,这样你就可以确保它不会在头文件中被意外地替换为宏或其他问题。 - Shahbaz
我使用这个又长又不可能的名字来避免命名冲突,但它似乎是一个标准名称... :o - Virus721
宏定义了一个循环,所以我不明白为什么你说break会引起问题。据我理解,使用break应该立即离开do while循环。你所说的“fall-through”是什么意思? - Virus721
显示剩余3条评论
2个回答

7
这样怎么样?当一个条件为真时,程序会一直执行所有的if语句,直到遇到break关键字才停止:
#define str_switch( value )                                    \
do {                                                           \
    const char * __strswitchptr__ = (value);                   \
    int __previous_case_true = 0;                              \
    if( 0 )                                                    \

#define str_case( test )                                       \
    } if(  __previous_case_true                                \
        || strcmp( __strswitchptr__, (test) ) == 0 ) {         \
        __previous_case_true = 1;                              \

#define str_default                                            \
    } {                                                        \

#define str_switchend                                          \
} while( 0 );

谢谢你的回答,很聪明。编译器中是否有if嵌套限制?长列表可能会导致问题吗? - Virus721
1
@Virus721 if语句没有嵌套,它们是顺序执行的。 - Sergey L.
下一个挑战:编写一个 str_goto(string) 函数,它可以跳转到 str_case(string) 函数。然后你就拥有了完整的 switch 实现! - Shahbaz
@Shahbaz,不要使用goto!虽然如果您可以使用类似于将#(字符串化)宏运算符的逆操作用于形成标签并将其前置到if之前,那么可能是可行的。 - Kninnug
在同一个函数中有多个开关的情况下,goto语句会成为一个问题。 - Virus721

0
你可以使用 switch 代替:
char * sVal =  "D";

while ( *sVal ) {
    switch ( *sVal ) {
        case 'A':
            printf( "Case A" );
        break;

        case 'B':
            printf( "Case B" );
        break;

        case 'C':
        case 'D':
        case 'E':
            printf( "Case C" );
        break;

        default:
            printf( "Error" );

    }
    sVal++;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接