iOS——实现简单计算器

记录一下最近写的一个计算器APP。

实现包含括号以及四则运算的简单计算器,利用MVC设计模式以及Masonry布局。
实现界面:
在这里插入图片描述
首先实现这个界面到了之前学过的Masonry第三方库,对按钮进行了屏幕比例的限制。

遇见的一些问题

在MVC设计模式中Button事件的处理

根据MVC的设计模式,Button事件应该加在C的代码中,这里一开始没有好的思路,后来问了下学长,学了一手。、
我们可以利用协议传值,在V的代码中添加事件,但事件函数是在C中实现的,每次点击Button时,C可以得到Button的tag值,以进行下一步处理。
部分代码:

//  View.h
//  计算器
//
//  Created by 差不多先生 on 2021/10/6.
//

#import <UIKit/UIKit.h>

@protocol viewDelegate <NSObject>

- (void) pressChange: (UIButton*) cButton;

@end
[_zeroButton addTarget:self action:@selector(return:) forControlEvents:UIControlEventTouchUpInside];

- (void) return: (UIButton*) cButton {
    [_delegate pressChange:cButton];
}

// 在c中实现的pressChange:方法

// 记录小数点状态
int flag = 0;
// 防止连续输入符号
int secondFlag = 0;
// 记录等于号状态
int thirdFlag = 0;
// 防止连续输入zero
int zeroFlag = 0;
- (void) pressChange: (UIButton*) cButton {
    if (cButton.tag == 101) {
        [_changeArray removeAllObjects];
        NSString *ansString = @"0";
        _firstView.topLabel.text = ansString;
        flag = 0;
        secondFlag = 0;
        thirdFlag = 0;
    } else if (cButton.tag == 120) {
        if (thirdFlag == 1) {
            ;
        } else {
            [_changeArray addObject:@"#"];
            NSString *ansString = [_changeArray componentsJoinedByString:@""];
//            NSLog(@"%@", ansString);
            [_firstModel operation:ansString];
            _firstView.topLabel.text = [_firstModel operation:ansString];;
            [_changeArray removeAllObjects];
            thirdFlag = 1;
        }
        
    } else if (cButton.tag == 119) {    //控制小数点输入合理
        if (flag == 0) {
            flag = 1;
            [_changeArray addObject:cButton.titleLabel.text];
            NSString *ansString = [_changeArray componentsJoinedByString:@""];
            _firstView.topLabel.text = ansString;
        } else {
            ;
        }
    }
    else {
        if (cButton.tag == 104 || cButton.tag == 108 || cButton.tag == 112 || cButton.tag == 116 ) {
            flag = 0;
            if (secondFlag == 0) {
                return;
            } else {
                secondFlag = 0;
            }
        } else if (cButton.tag != 102){ // 左括号后不能按符号
            secondFlag = 1;
        }
        [_changeArray addObject:cButton.titleLabel.text];
        NSString *ansString = [_changeArray componentsJoinedByString:@""];
        _firstView.topLabel.text = ansString;
        thirdFlag = 0;
        
    }
}

一些判错处理和预处理

这里我参考手机计算器的一些限制非法输入。
1.当没有数字时无法输入符号。
2.不能连续输入两个符号
3.当已经又了一个小数点,但没有出现运算符的情况下,不能继续输入小数点。
4.左括号后不能立即添加符号
代码在上面的方法中

对于输入进来的数据处理

首先判断括号是否有效

当括号无效时,直接判断输入错误。
代码:

// 设置符号优先级
int compareReturn(char str1) {
    if (str1 == '#') {
        return 0;
    } else if (str1 == '+' || str1 == '-') {
        return 1;
    } else if (str1 == '*' || str1 == '/') {
        return 2;
    } else if (str1 == '(' || str1 == ')') {
        return 0;
    }
    else {
        // 此时为数字
        return -1;
    }
}
// 判断括号是否有效
int tureKH (const char* str) {
    int top = 0;
    for (int i = 0; i < strlen(str); i++) {
        if (str[i] == '(') {
            top++;
        } else if (str[i] == ')') {
            if (top == 0) {
                return 0;
            } else {
                top--;
            }
        } else {
            ;
        }
    }
    if (top == 0) {
        return 1;
    } else {
        return 0;
    }
}

中缀转后缀

这个我前面写过博客中缀表达式转后缀表达式
只不过当时是用c语言实现的,这次是用OC实现的。
有些细微的区别,OC的数组并不能存储简单的数据类型,所以得将输入的数据转成一个个字符串对象再存入数组,由于输入的数据没有分隔符,所以如果直接将表达式转化为数组,那么会发现数组的第一个元素就是这个字符串整体对象,所以这里我先将字符串对象变为c风格的数组,然后再对其逐一处理进行转换。

// 判断是否是符号
- (BOOL) isSymbol:(NSString*) string {
    if ([string isEqual:@"*"] || [string isEqual:@"+"] || [string isEqual:@"-"] || [string isEqual:@"/"] || [string isEqual:@"("] || [string isEqual:@")"] || [string isEqual:@"#"]) {
        return YES;
    } else {
        return NO;
    }
}
// 优先级表
- (int) firstSymbol:(NSString*) string {
    if ([string isEqual:@"-"] || [string isEqual:@"+"]) {
        return 2;
    } else if ([string isEqual:@"*"] || [string isEqual:@"/"]) {
        return 3;
    } else if ([string isEqual:@"#"]) {
        return 1;
    } else {
        return 0;
    }
}
// 中缀转后缀

- (NSMutableArray*)switchString :(const char *) outString {
    // 设置存字符串标识
    int flag = 0;
    // 结果栈
    self.ansArray = [[NSMutableArray alloc] init];
    // 临时符号栈
    self.tempArray = [[NSMutableArray alloc] init];
    NSMutableArray *textArray = [[NSMutableArray alloc] init];
    for (int i = 0; i < strlen(outString); i++) {
//        printf("%c", outString[i]);
        NSString *str1 = [NSString stringWithFormat:@"%c", outString[i]];
        [textArray addObject:str1];
    }
//    NSLog(@"%@", textArray);
    NSMutableString* numberString = [[NSMutableString alloc] init];
    for (int i = 0; i < textArray.count;) {
        if ([self isSymbol:textArray[i]] == NO) {
            [numberString appendString:textArray[i++]];
            flag = 0;
        } else {
            if (flag == 0) {
                NSMutableString* temp = [[NSMutableString alloc] init];
                temp = [numberString copy];
                [self.ansArray addObject:temp];
                flag = 1;
                [numberString deleteCharactersInRange:NSMakeRange(0, numberString.length)];
                NSLog(@"%@", self.ansArray);
            }
            if ([textArray[i] isEqual:@"("]) {
//                [symbolString appendString:textArray[i++]];
                [self.tempArray addObject:textArray[i++]];
            } else if ([textArray[i] isEqual:@")"]) {
                while (![self.tempArray[self.tempArray.count - 1] isEqual:@"("]) {
                    [self.ansArray addObject:self.tempArray[self.tempArray.count - 1]];
                    [self.tempArray removeLastObject];
                }
                [self.tempArray removeLastObject];
                i++;
            } else {
                if (self.tempArray.count == 0) {
                    [self.tempArray addObject:textArray[i++]];
                    continue;
                }
                if (self.tempArray.count != 0 && [self firstSymbol:textArray[i]] > [self firstSymbol:self.tempArray[self.tempArray.count - 1]]) {
                    [self.tempArray addObject:textArray[i++]];
                } else {
                    [self.ansArray addObject:self.tempArray[self.tempArray.count - 1]];
                    [self.tempArray removeLastObject];
                }
            }
        }
    }
//    NSLog(@"%lu", self.ansArray.count);
    NSLog(@"%@", self.ansArray);
    return self.ansArray;
}

计算后缀表达式后有多余的0

在将字符串转为double计算后,再变为字符串,会出现多余0的问题,这里可以在最后再进行一次处理。

// 除去sum后多余的0
-(NSString*)removeZero:(NSString*)string {
    NSString * testNumber = string;
    NSString * ansNumber = [NSString stringWithFormat:@"%@",@(testNumber.doubleValue)];
    return ansNumber;
}

做除法运算分母不能为0

设置一个比较奇怪的值,加判断返回输入有误

} else if ([symbol isEqual:@"/"]) {
        if (y == 0) {
            ans = -9999;
            return ans;
        }
        ans = x / y;
    }

完整代码地址

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值