有没有办法让Objective-C支持多变量开关构造?

时间:2011-06-08 15:57:57

标签: objective-c switch-statement

我想知道:有没有办法让Objective-C支持多变量switch构造?

我的意思是,我经常需要处理解决方案依赖于一对变量而不是一对变量的问题。对于一长串单变量值,可以使用简单的switch/case构造:

switch (var) {
    case 0: ...
    case 1: ...
    default: ...
}

但是当你必须处理两个值的组合时,你经常碰巧做这样的事情:

switch (var1) {
    case 0: 
        switch (var2) {
            case 0: ...
            case 1: ...
        }
    case 1: 
        switch (var2) {
            case 0: ...
            case 1: ...
        }        
    ...
}

它变得越来越复杂......我真正喜欢做的是这样的事情:

switch (var1, var2) {
    case (0,0) : ...
    case (1,0) : ...
    case (*,1) : ...
    default: ...
}

将导致更简单和可读的构造。有没有解决方案来支持这样的结构?或者这个略有变化?

7 个答案:

答案 0 :(得分:10)

我喜欢saphrosit的回答,但我会尝试让它易于理解。

想象一下你的问题的可能结果是网格中的正方形,其中网格边缘的一个边表示var1的值,另一个边表示var2的可能值,然后如果你逐渐计算通过网格你会得到这样的东西

      ||                              var1                                   |    
      ||    0    |     1     |     2     | ... |     j     | ... |   n-1     |
======++=====================================================================|
    0 ||    0    |     1     |     2     | ... |     j     | ... |   n-1     |
   ---||---------+-----------+-----------+-----+-----------+-----+-----------|
    1 ||    n    |    n+1    |    n+2    | ... |    n+j    | ... |  n+(n-1)  |
   ---||---------+-----------+-----------+-----+-----------+-----+-----------| 
    2 ||   2*n   |   2*n+1   |  2*n+2    | ... |   2*n+j   | ... | 2*n+(n-1) |
 v ---||---------+-----------+-----------+-----+-----------+-----+-----------|
 a    ||    .    |     .     |     .     |     |     .     |     |  .        |
 r ---||---------+-----------+-----------+-----+-----------+-----+-----------|
 2  i ||   i*n   |   i*n+1   |   i*n+2   | ... |   i*n+j   | ... | i*n+(n-1) |
   ---||---------+-----------+-----------+-----+-----------+-----+-----------|
      ||    .    |      .    |      .    |     |     .     |     |  .        |
  ----||---------+-----------+-----------+-----+-----------+-----+-----------|
  m-1 || (m-1)*n | (m-1)*n+1 | (m-1)*n+2 | ... | (m-1)*n+j | ... |   mn-1    | <-- (m-1)*n+(n-1) = m*n-n + (n-1) = mn-1
------||---------+-----------+-----------+-----+-----------+-----+-----------|

这将被称为行主矩阵,因为您首先计算行数。还有一个列主矩阵,您首先开始倒数而不是开始倒数。这就是矩阵存储在C BLAS库中的方式,因此它应该与很多人非常相似。

在您的情况下,您正在寻找的结果可以var3 = var2*n + var1解决,您可以在代码中将其列为

#define N 10 // Maximum size of var1

int main() {

   int var1 = 1;
   int var2 = 1;

   switch(var1 + var2 * N){
      case 1 + 1 * N: printf("One One"); break;
      case 2 + 2 * N: printf("Two Two"); break;
      default:
      printf("Bada Bing");
   }

   return 0;
}

注意:之前的代码不起作用,这可行。

答案 1 :(得分:3)

在你提出的问题中你提到: “我真正喜欢做的是这样的事情:”

switch (var1, var2) {
    case (0,0) : ...
    case (1,0) : ...
    case (*,1) : ...
    default: ...
}

如果您的可能值在{0..n}范围内,则可以使用两种方法。

  1. 你可以构建一个 选择器的多维数组 然后选择正确的选择器 使用你的var1,var2。 (由于在编译时构造选择器,此方法更有效)

  2. 您可以构建选择器     名称基于的值     var,var2变量。

  3. 此代码段中举例说明了两种方法。

    - (void) case00 {
        NSLog(@"Case ZeroZero");
    }
    
    - (void) testSelectorIdea {
         NSInteger var1 = 0;
         NSInteger var2 = 0;
    
    // ----- ARRAY OF SELECTORS METHOD ----
        SEL selectors[2][2] = {@selector(case00),@selector(case01), @selector(case10), @selector(case11)};
        [self performSelector:selectors[var1][var2]];
    
    
    // ----- SELECTOR CONSTRUCTION METHOD ----
        NSString * selectorName = [NSString stringWithFormat:@"case%d%d",var1,var2];
        SEL  selector = NSSelectorFromString(selectorName);
        [self  performSelector:selector];
    
    }
    

答案 2 :(得分:2)

正如其他人所说,如果你发现自己想要这样做,那么你应该考虑一种更好地构建数据的方法。你好像在处理标量类型。我倾向于发现一点c ++在那里有很长的路要走,你可以使用objective-c ++将它集成到一个objective-c项目中。也就是说,如果你确定你想要你想要的东西,并且你不会厌恶预处理器的邪恶,你可以尝试这样的事情:

#define BEGIN_SWITCH(type,...) ({  typedef type T; T switchVars[] = { __VA_ARGS__ }; BOOL performAction;

#define CASE(...) { \
            T caseVars[] = { __VA_ARGS__ }; \
            performAction = YES; \
            size_t count = MIN(sizeof(switchVars), sizeof(caseVars)) / sizeof(T); \
            for (size_t i = 0 ; i < count / sizeof(T) ; i++) \
            { \
                if (caseVars[i] != switchVars[i]) \
                { \
                    performAction = NO; \
                    break; \
                } \
            } \
        } \
        if (performAction)

#define END_SWITCH });

int main (int argc, char const *argv[])
{
    id pool = [[NSAutoreleasePool alloc] init];

    int a1 = 0;
    int a2 = 5;
    int a3 = 10;

    BEGIN_SWITCH(int, a1, a2, a3)
        CASE(0,5) NSLog(@"0,5");
        CASE(1,2,3) NSLog(@"1,2,3");
        CASE(0,5,10) NSLog(@"0,5,10");
        CASE(1) NSLog(@"1");
    END_SWITCH

    [pool drain];

    return 0;
}

它不像switch / case,因为你不能将多个case:clauses堆叠在另一个上面。在任何情况下你都必须添加默认值并以某种方式中断 - 也许你可以用一些额外的宏和一个goto for break来做到这一点。关于预处理器的标准警告适用:它不像Objective-C那样漂亮,并且很容易给你各种不可思议的语法错误。但是如果你真的想要改变语言的语法,那么你的选择就是这样或者得到Apple的工作。

答案 3 :(得分:1)

不是解决方案,只是一种解决方法:你可能会想到这样的事情

SInt32 var1, var2;
/*...*/
SInt64 var3 = var1<<32 + var2;

switch(var3) {
 .
 .
 .
}

如果您的vars具有某些特定属性,您可以使用它进行一些轻微的简化,即如果vars是&lt; 10然后你可以使用

 var3 = 10*var1+var2;

答案 4 :(得分:0)

你确定这是一个很好的编程风格,有这样的结构:)? Switch语句旨在加速多个if()else if()语句,但是当你需要比较优化将要进行的多个变量时。

一种方法是使用逻辑移位/其他操作将多个变量放在一个中,另一种方法是使用if((a == 0)&amp;(b == 0)){...} else if((a == 0)&amp;&amp;(b == 1)).... 这不会占用太多空间。

答案 5 :(得分:0)

由于存在ObjC-Runtime,应该可以使用选择器类型SEL/@selector()/performSelectorNSSelectorFromString,NSArrays / NSDictionaries和NSIndexPathes等内容来构建交换机替换。 ,这比c-switch声明更强大。
但它不会停留在语言层面,因为Python-code并不是那么好。

答案 6 :(得分:0)

如下:

switch ([NSString StringWithFormat: @"%d,%d", var1, var2]) {
    case (@"0,0") : ...
    case (@"1,0") : ...
    case (@"*,1") : ...
    default: ...
}

问题可能是*,1但是你可以拼写全部,或者你可以做contains @",1"(我忘记了正确的语法atm)