我有一个方法将数组作为引用传递,我使用递归来多次调用此方法。我将数组用作“堆栈”。代码是一个计算器,它将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;
}
答案 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
)你试图再次删除最后一个元素,但是没有物品离开了。