我想知道:有没有办法让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: ...
}
将导致更简单和可读的构造。有没有解决方案来支持这样的结构?或者这个略有变化?
答案 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}范围内,则可以使用两种方法。
你可以构建一个 选择器的多维数组 然后选择正确的选择器 使用你的var1,var2。 (由于在编译时构造选择器,此方法更有效)
您可以构建选择器 名称基于的值 var,var2变量。
此代码段中举例说明了两种方法。
- (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()/performSelector,NSSelectorFromString,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)