[斯坦福ios开发][assignment2]1

题目描述:

Add the capability to yourCalculatorBrainto accept variables as operands (in addition to still acceptingdoubles as operands). You will need new public API in yourCalculatorBrainto support this.

A variable will be specified as anNSStringobject. To simplify your implementation, you can ignore attempts to push a variable whose name is the same as an operation (e.g. you can ignore an attempt to push a variable named “sqrt”).

The values of the variables will only be supplied when the “program” is “run.” You must add a new version of therunProgram:class method with the following signature ...

+ (double)runProgram:(id)program usingVariableValues:(NSDictionary*)variableValues;

The keys in the passedvariableValuesdictionary areNSStringobjects corresponding to the names of variables used in the passedprogram, and the values in the dictionary areNSNumberobjects specifying the value of the corresponding variable (for this assignment we will supply “test” values, see Required Task #3).

If there are variables in the specifiedprogramfor which there are no values in the specifiedNSDictionary, use a value of 0 for those variables when you run the program. This should be the case if someone calls the originalrunProgram:method (the one shown in the demo in class).

In addition, create another class method to get all the names of the variables used in a givenprogram(returned as an NSSetofNSStringobjects) ...

+ (NSSet*)variablesUsedInProgram:(id)program;
If the program has no variables return nilfrom this method (not an empty set).


在正式编写runProgramUsingVariables函数之前, 我们需要写一个pushVariable函数,就像之前的pushOperand一样。用来关联以后的按键事件。非常简单

(void) pushVariable:(NSString *)variableName
{
    [self.programStack addObject:variableName];
}

还有一个辅助函数,
+(NSSet *) variableUsedInProgram:(id)program
{
    NSMutableSet *result = [NSMutableSet setWithCapacity:3];
    if ([program containsObject:@"x"])
    {
        [result addObject:@"x"];
    }
    if ([program containsObject:@"y"])
    {
        [result addObject:@"y"];
    }
    if ([program containsObject:@"foo"])
    {
        [result addObject:@"foo"];
    }
    if ([result count] == 0) {
        return nil;
    }
    else return [result copy];
}

这个函数返回一个NSSet类,告诉我们这个program中都使用了哪些变量。无非就是遍历整个堆栈,有变量就放到nsset里。这里要注意的就是nsset类方法的使用.

初始化NSSet
[NSSet setWithCapacity:int]

参数是一个整数,初始化时候使用,返回一个set,最多可以容纳int个元素。
这里我们用3就够了,因为计算器只有x,y,foo三个变量。
向NSSet中加元素
[foo addObject:Obj]

这是一个实例方法。大家一看就懂~
ContainObject:id这个其实是一个NSArray的实例方法,但用在set中最合适不过了,它返回array中是否包含object


Ok,万事俱备,下面就要攻克最难部分,编写runProgramUsingVariables

为了尽可能的少动原来的程序,这里笔者采用了最笨的方法,就是把整个stack堆栈里所有的变量全部替换成所对应的数字。。。其实我一直想在popOperandOffStack里面修改,但是改的太多,所以就放弃了。。。
具体方法就是遍历stack每个元素,遇到变量就从字典里拿value替换
+(double) runProgram:(id)program
 usingVariableValues:(NSDictionary *)variableValues
{
    NSMutableArray *stack;
    if ([program isKindOfClass:([NSArray class])])
    {
        stack = [program mutableCopy];
    }
    for (int i = 0; i < [stack count]; i++) {
        id item = [stack objectAtIndex:i];
        if ([item isKindOfClass:[NSString class]] &&
           ([item isEqualToString:@"x"] ||
            [item isEqualToString:@"y"] ||
            [item isEqualToString:@"foo"]))
        {
            [stack replaceObjectAtIndex:i withObject:[variableValues objectForKey:item]];
        }
    }
    return [self popOperandOffStack:stack];
}

很笨的方法,但却很实用,这里用到了NSArray的实例方法[foo count][foo objectAtIndex:int]还有NSMutableArray的实例方法[foo replaceObjectAtIndex:int withObject:id],具体用法看代码就好,这里我真的要感慨下,apple这里做的很厚道,按住option点class名,就能找到reference,非常友好,而且函数名字都起的那么“白痴”哈哈,要是不会就出了奇啦~

当然,不要忘记提前做好字典,这个字典做成私有即可,然后用laziliy initialize
@synthesize variableValues = _variableValues;
-(NSMutableDictionary *) variableValues
{
    if ( _variableValues == nil)
    {
        NSNumber *zero = [NSNumber numberWithDouble:0];
        NSArray *zeros = [NSArray arrayWithObjects:zero, zero, zero, nil];
        NSArray *variableNames = [NSArray arrayWithObjects:@"x", @"y", @"foo", nil];
        _variableValues =[[NSMutableDictionary alloc] initWithObjects:zeros forKeys:variableNames];
    }
    return _variableValues;
}
我不知道这是不是好方法,但确实可以用。。。而且自己看起来也蛮顺眼敲打那就这样用好啦~

最后要做的就是修改下performOperation,让它可以自我选择调用非变量版计算器还是变量版计算器
-(double) performOperation: (NSString *)operation
{
    [self.programStack addObject:operation];
    if ([CaculatorBrain variableUsedInProgram:self.program]) {
        return [CaculatorBrain runProgram:self.program usingVariableValues:self.variableValues];
    }
    else return [CaculatorBrain runProgram:self.program];
}

如此一来,大功告成~第一步就算完成了~偷笑

那么。。怎么测试呢?去storyboard放三个button,分别标记x,y,foo,然后关联一下,自己测试吧~睡觉
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值