目标C:传递NSArray作为方法的参考

时间:2012-07-16 05:36:39

标签: objective-c recursion stack nsarray pass-by-reference

我有一个方法将数组作为引用传递,我使用递归来多次调用此方法。我将数组用作“堆栈”。代码是一个计算器,它将postfix转换为中缀,只是一个简单的工具。

我对代码及其输出有疑问。代码可以工作但是当我取消注释一个部分[stack removeLastObject];时它停止工作并声称数组是空的。

我没有得到这个,因为我从主数组中删除一个对象 - 而不是我在递归中使用的副本。如果我输入一个副本进行递归,然后从原始文件中删除一个对象,该副本是否受到影响?

我的主要例子是使用一个3,5或+的数组,它应该输出(3 + 5)。如果我取消注释代码的一部分,我得到(3 + 3)。这是代码:

+(NSString*) descriptionTop:(NSMutableArray *) stack{

NSMutableString *programFragment = [NSMutableString stringWithString:@""];

id topOfStack = [stack lastObject];
if (topOfStack) [stack removeLastObject];
NSLog(@"operation is %@", topOfStack);
NSLog(@"Stack is%@", stack);


if([ topOfStack isKindOfClass:[NSNumber class]]){
    [programFragment appendFormat:@"%g", [topOfStack doubleValue]];
}
else if( [topOfStack isKindOfClass:[NSString class]])
{
    NSString *operation = topOfStack;
    if ([operation isEqualToString:@"+"] || 
        [operation isEqualToString:@"-"] ||  
        [operation isEqualToString:@"/"] ||  
        [operation isEqualToString:@"*"]) {

       NSMutableArray *operand1 = [stack mutableCopy];
        [operand1 removeLastObject];

        NSMutableArray *operand2 = [stack mutableCopy];
        // [stack removeLastObject];

        [programFragment appendFormat:@"(%@ %@ %@)", [self descriptionTop:operand1], operation, [self descriptionTop:operand2]];

    }
 }

NSLog(@" program fragment returns %@", programFragment);
return programFragment;
}

2 个答案:

答案 0 :(得分:2)

我想我明白你要做的是什么,但你的逻辑却相当混乱。让我们遍历您的代码,输入[3 5 +](其中+是堆栈的顶部),假设您的额外[stack removeLastObject]已取消注释。首先,您(正确地)从堆栈中弹出操作符:

id topOfStack = [stack lastObject];
// topOfStack = +
// stack = [3 5 +]

if (topOfStack) [stack removeLastObject];
// topOfStack = +
// stack = [3 5]

然后您会发现topOfStack是一个字符串,因此您将其分配给operation。然后你这样做:

        NSMutableArray *operand1 = [stack mutableCopy];
        // operation = +
        // operand1 = [3 5]
        // stack = [3 5]

        [operand1 removeLastObject];
        // operation = +
        // operand1 = [3]
        // stack = [3 5]

        [stack removeLastObject];
        // operation = +
        // operand1 = [3]
        // stack = [3]

请注意,此时,5完全消失了!你没有任何变量。因此,当您设置operand2时,3位于顶部(实际上是唯一的元素):

        NSMutableArray *operand2 = [stack mutableCopy];
        // operation = +
        // operand1 = [3]
        // stack = [3]
        // operand2 = [3]

现在,让我们回到设置operand1的位置,但删除额外的[stack removeLastObject]

        NSMutableArray *operand1 = [stack mutableCopy];
        // operation = +
        // operand1 = [3 5]
        // stack = [3 5]

        [operand1 removeLastObject];
        // operation = +
        // operand1 = [3]
        // stack = [3 5]

        NSMutableArray *operand2 = [stack mutableCopy];
        // operation = +
        // operand1 = [3]
        // stack = [3 5]
        // operand2 = [3 5]

现在operand2顶部有5,因此descriptionTop:operand2的递归调用会找到5,您会得到正确答案{ {1}} (3 + 5)

但此功能仍然存在。

考虑输入[3 5 +]。什么是正确的输出?我认为它应该是[3 4 5 * +]。但是你的功能是做什么的?让我们来看看吧。首先,它会弹出(3 + (4 * 5))运算符:

+

接下来,它将堆栈复制到id topOfStack = [stack lastObject]; // topOfStack = + // stack = [3 4 5 * +] if (topOfStack) [stack removeLastObject]; // topOfStack = + // stack = [3 4 5 *] 并从operand1中删除最后一个元素:

operand1

然后,假设我们没有 NSMutableArray *operand1 = [stack mutableCopy]; // operation = + // operand1 = [3 4 5 *] // stack = [3 4 5 *] [operand1 removeLastObject]; // operation = + // operand1 = [3 4 5] // stack = [3 4 5 *] ,它会将堆栈复制到[stack removeLastObject]

operand2

现在您可以看到,当我们在此 NSMutableArray *operand2 = [stack mutableCopy]; // operation = + // operand1 = [3 4 5] // stack = [3 4 5 *] // operand2 = [3 4 5 *] 递归调用descriptionTop:时,它将返回operand1。当我们在5上以递归方式调用descriptionTop:时,它将返回operand2。所以我们返回4 * 5(5 + (4 * 5))发生了什么事?我们从来没有达到过它!

这里的问题是,为了达到3,我们必须从堆栈中消耗 3作为一个操作数,然后查找另一个操作数相同的堆栈(其中已使用4 5 *),以便我们可以找到4 5 *

你需要做的是而不是复制堆栈!您需要将相同的堆栈对象传递给递归调用,这样当您弹出构成一个操作数的所有元素时,您可以在堆栈顶部找到另一个操作数的元素。像这样:

3

答案 1 :(得分:0)

您拨打[stack removeLastObject]两次。当你的stack数组剩下一个元素时,代码会失败,因为你首先删除了最后一个对象,然后(如果它是NSString)你试图再次删除最后一个元素,但是没有物品离开了。