[iOS]计算器问题总结

用到的知识点:

  1. Masonry布局[iOS]-Masonry的使用
  2. MVC设计模式[iOS]- MVC模式基础
  3. 栈的思想实现四则运算C语言-栈的四则运算(带小数点和括号)

整体思路:

UI界面的创建:

  1. 前四行都是四个小按钮,使用四个for循环创建,每次建立一行,最后一行的三个按钮单独建立
  2. 每个按钮的位置使用Masonry约束,以保证兼容多个机型

代码如下:

//下面只给出第一行的按钮和0按钮单个按钮的建立代码
//第一行的四个按钮
    for (int i = 1; i <= 4; ++i) {
        NSString *string = [NSString stringWithFormat:@"1%d.jpg", i];
        
        _firstGroup = [UIButton buttonWithType:UIButtonTypeCustom];
        [_firstGroup setImage:[UIImage imageNamed:string] forState:UIControlStateNormal];
        [_firstGroup addTarget:self action:@selector(pressButtonFirst:)  forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:_firstGroup];
        
        [_firstGroup mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.mas_offset(self.frame.size.height * 0.380);
            make.left.mas_equalTo(self.frame.size.width * (0.035 + 0.241 * (i - 1)));
            make.size.mas_equalTo(CGSizeMake(self.frame.size.width * 0.206, self.frame.size.height * 0.095));
        }];
        
        _firstGroup.tag = 10 + i;
    }

//0按钮
    _zeroButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [_zeroButton setImage:[UIImage imageNamed:@"0.jpg"] forState:UIControlStateNormal];
    
    [_zeroButton addTarget:self action:@selector(pressButtonZero:) forControlEvents:UIControlEventTouchUpInside];
    
    [self addSubview:_zeroButton];
    
    _zeroButton.tag = 51;
    
    [_zeroButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_offset(self.frame.size.height * 0.824);
        make.left.mas_equalTo(self.frame.size.width * 0.035);
        make.size.mas_equalTo(CGSizeMake(self.frame.size.width * 0.447, self.frame.size.height * 0.095));
    }];

其中Masonry约束的写法以约束top、left、size三个条件为规范
且每个按钮的事件函数同样写在V中,每次按下按钮时触发事件函数,利用协议传值将相应按钮的tag值传至C中分情况进行操作
四则运算思路:

  1. 每按下一个按钮就将按钮的相应元素添加至可变字符串中,待按下等号按钮时调用M中的运算函数进行计算
  2. 首先进行判错处理,如果通过判错处理则进行实际运算过程
  3. 实际的运算过程是遍历此可变字符串,对每个字符分情况处理

处理逻辑如下:
每次对一个元素进行判断和操作,一共两个栈(一个数字栈,一个符号栈)
(1)如果是数字就入数字栈,然后继续操作下一个字符串中的元素
下面是对括号的一些操作:
如果是左括号,就进符号栈,然后继续操作下一个字符串中的元素
如果是右括号,就让符号栈栈顶元素出栈,让数字栈栈顶和次栈顶的两个元素出栈进行运算,并将运算结果入数字栈,一直循环此操作直至遇见符号栈栈顶为左括号为止,遇见左括号后将其出符号栈,并继续操作下一个字符串中的元素
(2)如果是符号:
如果符号栈为空,就直接入符号栈
如果符号栈栈顶的符号的优先级大于当前正在操作的字符串中的元素,就将符号栈栈顶符号出栈,将数字栈栈顶和次栈顶的两个元素出栈,进行运算后将结果入数字栈
如果符号栈栈顶的符号的优先级小于当前正在操作的字符串中的元素,就入符号栈
(3)当字符串中的元素全部遍历完后如果符号栈仍然有元素,就继续从符号栈栈顶出一个元素,从数字栈栈顶出两个元素,计算后将结果入数字栈,循环此操作直至符号栈为空为止

具体代码详见上方超链接中的四则运算博客,实际的计算器编写中可根据需求添加判错
注意的点:
OC的栈我们用可变数组来代替,具体代码如下:

//进数字栈
- (void) pushNum: (double) num {
    if (_numArray.count == 50) {
        NSLog(@"进栈失败");
        return;
    }
    [_numArray addObject:[NSString stringWithFormat:@"%f",num]];
    return;
}

//进符号栈
- (void) pushChar: (char) str {
    if (_strArray.count == 50) {
        NSLog(@"进栈失败");
        return;
    }
    [_strArray addObject:[NSString stringWithFormat:@"%c", str]];
//    NSLog(@"$$$$$%c", str);
    return;
}

//出数字栈
- (double) popNum {
    double t;
    t = [self backNum:_numArray[_numArray.count - 1]];
    [_numArray removeLastObject];
    return t;
}

//出符号栈
- (char) popChar {
    char ch;
    ch = [_strArray[_strArray.count - 1] characterAtIndex:0];
    [_strArray removeLastObject];
    //NSLog(@"$$$$$%c", ch);
    return ch;
}

//返回数字栈栈顶
- (double) topNum {
    return [self backNum:_numArray[_numArray.count - 1]];
}

//返回符号栈栈顶
- (char) topChar {
    return [_strArray[_strArray.count - 1] characterAtIndex:0];
}

可以看到我们入数字栈的时候实际上入的是字符串,所以需要编写一个函数出数字栈的时候将字符串转为实际的数字,该函数如下:

//转换数组中的字符串为数字
- (double) backNum:(NSString *) string {
	//这里的flag用来判断需要出栈的数字是否为负数,若flag为0则为正数,若flag为1则为负数
    int flag = 0;
    double res;
    if ([string characterAtIndex:0] == '-') {
        flag = 1;
    }
    if (flag == 0) {
        int i = 0;
        double x = 0;
        while ([string characterAtIndex:i] >= '0' && [string characterAtIndex:i] <= '9' && i < string.length) {
            x *= 10;
            x += (double)[string characterAtIndex:i] - '0';
            ++i;
        }
        
        //计算是小数的情况
        if (i < string.length && [string characterAtIndex:i] == '.') {
            double d = 0.1;
            ++i;
            while (i < string.length) {
                x += ((double)[string characterAtIndex:i] - '0') * d;
                d *= 0.1;
                ++i;
            }
        }
        res = x;
    } else {
        int i = 1;
        double x = 0;
        while ([string characterAtIndex:i] >= '0' && [string characterAtIndex:i] <= '9' && i < string.length) {
            x *= 10;
            x += (double)[string characterAtIndex:i] - '0';
            ++i;
        }
        
        //计算是小数的情况
        if (i < string.length && [string characterAtIndex:i] == '.') {
            double d = 0.1;
            ++i;
            while (i < string.length) {
                x += ((double)[string characterAtIndex:i] - '0') * d;
                d *= 0.1;
                ++i;
            }
        }
        res = x;
    }
    
    if (flag == 0) {
        return res;
    } else {
        return -res;
    }
}

比较符号优先级和计算结果的函数代码如下:

//比较符号优先级
- (NSInteger) compare:(char) str {
    if (str == '+' || str == '-') {
        return 1;
    } else if (str == '*' || str == '/') {
        return 2;
    } else {
        return 0;
    }
}

//计算函数
- (double) counter:(double) first :(double) second :(char) strSecond {
    double ans = 0.0;
    if (strSecond == '+') {
        ans = first + second;
    } else if (strSecond == '-') {
        ans = first - second;
    } else if (strSecond == '*') {
        ans = first * second;
    } else {
        ans = first / second;
    }
    return ans;
}

有了以上函数,我们就可以编写计算的主函数,在主函数中调用以上函数实现计算最终结果的功能了。主函数具体逻辑参考上方四则运算博客

一些细节问题:

我们定义了一个可变字符串,用于存最终的运算结果,最后将屏幕上UI Label的text设置为该可变字符串即可在屏幕上显示最终结果
计算等相关函数写在M中,在C中调用产生效果

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值