1

配列を参照として渡すメソッドがあり、再帰を使用してこのメ​​ソッドを数回呼び出します。配列を「スタック」として使用します。このコードは、接尾辞を中置辞に変換する電卓用であり、単なるツールです。

コードとその出力について質問があります。コードは機能しますが、1つのセクションのコメントを解除すると、機能が[stack removeLastObject];停止し、配列が空であると主張します。

メイン配列からオブジェクトを削除しているため、これは取得できません。再帰で使用しているコピーではありません。再帰のためにコピーを入力してから、元のオブジェクトからオブジェクトを削除すると、コピーは影響を受けますか?

私の主な例は、(3 + 5)を出力する3、5、+の配列を使用することです。コードの1つのセクションのコメントを外すと、(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;
}
4

2 に答える 2

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が一番上にあるので、 onを5再帰的に呼び出すと、が見つかり、の正解が得られます。descriptionTop:operand25(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:返されることがわかります。そして、再帰的にcall onを呼び出すと、が返されます。したがって、を返します。何が起こったの?到達したことはありません!operand15descriptionTop:operand24 * 5(5 + (4 * 5))3

ここでの問題は、に到達するために3、スタックからを1つのオペランドとして消費し、次に同じスタック(消費された場所)で4 5 *他のオペランドを探して、を見つける必要があることです。4 5 *3

あなたがする必要があるのは、スタックをまったくコピーしないことです!同じスタックオブジェクトを再帰呼び出しに渡す必要があります。これにより、一方のオペランドを形成するすべての要素をポップすると、スタックの最上位にあるもう一方のオペランドの要素を見つけることができます。このような:

    // operation = +
    // stack = [3 4 5 *]

    NSString *operand2Description = [self descriptionTop:stack];
    // operation = +
    // operand2Description = "4 * 5"
    // stack = [3]

    NSString *operand1Description = [self descriptionTop:stack];
    // operation = +
    // operand1Description = "3"
    // operand2Description = "4 * 5"
    // stack = [] (empty stack)

    [programFragment appendFormat:@"(%@ %@ %@)", operand1Description, operation, operand2Description];
    // programFragment = "(3 + (4 * 5))"
于 2012-07-16T06:47:54.887 に答える
0

[stack removeLastObject]あなたは二度電話します。配列に1つの要素が残っている場合stack、最初に最後のオブジェクトを削除してから(もしそうならNSString)最後の要素を再度削除しようとするため、コードは失敗しますが、オブジェクトは残っていません。

于 2012-07-16T06:06:47.500 に答える