本文介绍: 仿写iOS的计算器使用了MVC模式masonry库。MainView.hMainView.m添加事件MVC模式要求我们在MainViewController里实现添加事件我们在MainViewController例调用MainView的属性,为AC,等于和小数点这种特殊按钮单独添加事件遍历MainView中储存普通按钮数组,为它们添加一个总的事件。在这个总事件里,使用按钮tag值进行分类,调用不同的事件。实现这些事件。限制输入在一定程度上限制用户输入

仿写iOS的计算器使用了MVC模式和masonry库。

绘制界面

  1. 循环建立button,统一设置属性添加约束
  2. 括号按钮tag设成100+,运算符按钮tag设成200+,数字按钮tag设成300+,用于之后分类。
  3. 设置不同按钮的颜色。
  4. 将AC,等于和小数点这种特殊按钮赋给mainView的属性
  5. MainView声明一个数组属性,将除上面三个特殊按钮之外的按钮全部添加数组里。
  6. 在按钮上方添加一个UITextField,关掉它的用户交互。

MainView.h

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface MainView : UIView

@property (nonatomic, strong) NSArray* operArray;
@property (nonatomic, strong) NSMutableArray* buttonArray;

@property (nonatomic, strong) UITextField* calculation;

@property (nonatomic, strong) UIButton* ACButton;
@property (nonatomic, strong) UIButton* equalButton;
@property (nonatomic, strong) UIButton* pointButton;

- (void) initView;

@end

NS_ASSUME_NONNULL_END

MainView.m

#import "MainView.h"
#import "Masonry.h"

#define SIZE 85

#define CalculationWidth 375

@implementation MainView

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
    // Drawing code
}
*/

- (void) initView {
    self.backgroundColor = [UIColor blackColor];
    
    [self creatOperArray];
    self.buttonArray = [[NSMutableArray alloc] init];
    
    self.calculation = [[UITextField alloc] init];
    self.calculation.backgroundColor = [UIColor blackColor];
    self.calculation.textColor = [UIColor whiteColor];
    self.calculation.textAlignment = NSTextAlignmentRight;
    self.calculation.font = [UIFont systemFontOfSize:60];
    
    self.calculation.userInteractionEnabled = NO;
    
    [self addSubview:self.calculation];
    
    [self.calculation mas_makeConstraints:^(MASConstraintMaker *make) {
        make.bottom.equalTo(self).offset(-600);
        make.width.equalTo(@CalculationWidth);
    }];
    
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++) {
            UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
            button.titleLabel.font = [UIFont systemFontOfSize:42];
            button.layer.cornerRadius = SIZE / 2;
            
            [self addSubview:button];
            
            [button mas_makeConstraints:^(MASConstraintMaker *make) {
                make.bottom.equalTo(self).offset(-(70 + (SIZE + 15) * (i + 1)));
                make.left.equalTo(self).offset(3 + (SIZE + 15) * j);
                make.size.equalTo(@SIZE);
            }];
            
            if (i == 3 &amp;&amp; j < 3) {
                button.backgroundColor = [UIColor grayColor];
                [button setTitle:self.operArray[i + j + 1] forState:UIControlStateNormal];
                [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
                button.tag = 100 + j;
                if (j == 0) {

                    _ACButton = button;
                } else {

                    [self.buttonArray addObject:button];
                }
            } else if (j == 3) {
                button.backgroundColor = [UIColor colorWithRed:251.0f / 255.0f green:151.0f / 255.0f blue:15.0f / 255.0f alpha:1];
                [button setTitle:self.operArray[i] forState:UIControlStateNormal];
                [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
                button.tag = 200 + i;

                [self.buttonArray addObject:button];
            } else {
                button.backgroundColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1];
                NSString* title = [NSString stringWithFormat:@"%d", j + 3 * i + 1];
                [button setTitle:title forState:UIControlStateNormal];
                [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
                button.tag = 300 + i * 3 + j;

                [self.buttonArray addObject:button];
            }
        }
    }
    
    for (int i = 0; i < 3; i++) {
        UIButton* button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        button.titleLabel.font = [UIFont systemFontOfSize:42];
        button.layer.cornerRadius = SIZE / 2;
        [button setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
        
        [self addSubview:button];
        
        if (i == 0) {
            [button mas_makeConstraints:^(MASConstraintMaker *make) {
                make.bottom.equalTo(self).offset(-70);
                make.left.equalTo(self).offset(0);
                make.width.equalTo(@(SIZE * 2 + 15));
                make.height.equalTo(@SIZE);
            }];
            [button setTitle:@"0          " forState:UIControlStateNormal];
            button.backgroundColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1];
            button.tag = 310;

            [self.buttonArray addObject:button];
        } else {
            [button mas_makeConstraints:^(MASConstraintMaker *make) {
                make.bottom.equalTo(self).offset(-70);
                make.left.equalTo(self).offset(200 + (SIZE + 15) * (i - 1));
                make.size.equalTo(@SIZE);
            }];
            if (i == 1) {
                [button setTitle:@"." forState:UIControlStateNormal];
                button.backgroundColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1];
                button.tag = 311;

                self.pointButton = button;
            } else {
                [button setTitle:@"=" forState:UIControlStateNormal];
                button.backgroundColor = [UIColor colorWithRed:251.0f / 255.0f green:151.0f / 255.0f blue:15.0f / 255.0f alpha:1];
                button.tag = 400;

                _equalButton = button;
            }
        }
    }
}

- (void) creatOperArray {
    NSArray* array = [[NSArray alloc] initWithObjects:@"+", @"-", @"×", @"÷", @"AC", @"(", @")", nil];
    
    self.operArray = array;
}

@end

添加事件

  1. MVC模式要求我们在MainViewController里实现添加事件。
  2. 我们在MainViewController例调用MainView的属性,为AC,等于和小数点这种特殊按钮单独添加事件。
[self.mainView.ACButton addTarget:self action:@selector(pressAcButton:) forControlEvents:UIControlEventTouchUpInside];
    
[self.mainView.equalButton addTarget:self action:@selector(pressEqualButton:) forControlEvents:UIControlEventTouchUpInside];
    
[self.mainView.pointButton addTarget:self action:@selector(pressPiontButton:) forControlEvents:UIControlEventTouchUpInside];
  1. 遍历MainView中储存普通按钮的数组,为它们添加一个总的事件。
    for (UIButton* button in self.mainView.buttonArray) {
        [button addTarget:self action:@selector(pressButton:) forControlEvents:UIControlEventTouchUpInside];
    }
  1. 在这个总事件里,使用按钮的tag值进行分类,调用不同的事件。
- (void) pressButton:(UIButton*)sender {
    if (sender.tag / 100 == 1) {
        [self pressBracButton:sender];
    } else if (sender.tag / 100 == 2) {
        [self pressOperButton:sender];
    } else if (sender.tag / 100 == 3) {
        [self pressNumberButton:sender];
    }
}
  1. 实现这些事件。

限制输入

在一定程度上限制用户的输入,保证算术式的正确

  1. 为每种按钮设置BOOL类型或NSInteger类型属性用于判断此按钮是否生效。每次用户触发点击事件后,先通过这些属性判断此次点击是否有效。若有效,则输入新数据;若无效,则跳过。
@property (nonatomic, assign) NSInteger rightBracLimit;
@property (nonatomic, assign) BOOL lefBracLimit;
@property (nonatomic, assign) BOOL OperLimit;
@property (nonatomic, assign) BOOL NumLimit;
@property (nonatomic, assign) BOOL pointLimitByNum;
@property (nonatomic, assign) BOOL pointLimitByOper;
@property (nonatomic, assign) BOOL OperLimitJJ;
  1. 初始化这些属性,每种按钮在开始时是否有效是固定的,我们只需要将它们列出来。
// 设置按钮初始限制状态
    _rightBracLimit = 0;
    _lefBracLimit = YES;
    _NumLimit = YES;
    _OperLimit = NO;       // 乘除
    _pointLimitByNum = NO;
    _pointLimitByOper = YES;
    _OperLimitJJ = YES;  // 加减
  1. 某个按钮的点击事件生效后,每种按钮是否有效也是固定的,我们一样将它们列出来。(以数字按钮为例)
- (void) pressNumberButton:(UIButton*)sender {
    if (self.NumLimit) {
        NSString* oldCalculation = self.mainView.calculation.text;
        NSString* newChar = sender.titleLabel.text;
        NSString* newCalculation = nil;
        if ([newChar isEqual:@"0          "]) {
            newCalculation = [NSString stringWithFormat:@"%@0", oldCalculation];
        } else {
            newCalculation = [NSString stringWithFormat:@"%@%@", oldCalculation, newChar];
        }
        
        self.mainView.calculation.text = newCalculation;
        
        // 设置按钮限制状态
        _lefBracLimit = NO;
        if (_rightBracLimit < 0) {
            _rightBracLimit = -_rightBracLimit;
        }
        _OperLimit = YES;
        _OperLimitJJ = YES;
        if (_pointLimitByOper) {
            _pointLimitByNum = YES;
        }
    }
}
  1. 括号和小数点的限制比较特殊。

括号使用NSInteger类型,记录输入左括号的数量。输入一个括号,我们是这个属性值加一,输入一个括号减一。我们限制只有这个属性的值大于0,点击才能生效。如果输入某个非右括号符号,我们将这个值改为负数以限制错误输入。(下为括号点击事件)

// 处理括号
- (void) pressBracButton:(UIButton*)sender {
    if (sender.tag == 101) {
        if (_lefBracLimit) {
            NSString* oldCalculation = self.mainView.calculation.text;
            NSString* newChar = sender.titleLabel.text;
            NSString* newCalculation = [NSString stringWithFormat:@"%@%@", oldCalculation, newChar];
            
            self.mainView.calculation.text = newCalculation;
            
            if (_rightBracLimit < 0) {
                _rightBracLimit = -_rightBracLimit;
            }
            _rightBracLimit++;
            _OperLimit = NO;
            _NumLimit = YES;
            _OperLimitJJ = YES;
            
            _pointLimitByNum = NO;
            _pointLimitByOper = YES;
        }
    } else {
        if (_rightBracLimit > 0) {
            NSString* oldCalculation = self.mainView.calculation.text;
            NSString* newChar = sender.titleLabel.text;
            NSString* newCalculation = [NSString stringWithFormat:@"%@%@", oldCalculation, newChar];
            
            self.mainView.calculation.text = newCalculation;
            
            _rightBracLimit = _rightBracLimit - 1;
            
            _lefBracLimit = NO;
            _NumLimit = NO;
            _OperLimit = YES;
            
            _pointLimitByNum = NO;
            _pointLimitByOper = YES;
            _OperLimitJJ = YES;
        }
    }
}

小数点使用两个属性限制。一个属性限制小数点前存在数字一个属性限制两个有效的小数点之间存在一个有效运算符,保证一个数字只有一个小数点。

MainViewController全部代码

MainViewController.h

#import <UIKit/UIKit.h>
#import "MainView.h"
#import "CalculatorModel.h"

NS_ASSUME_NONNULL_BEGIN

@interface MainViewController : UIViewController

@property (nonatomic, strong) MainView* mainView;

@property (nonatomic, strong) CalculatorModel* model;

@property (nonatomic, assign) NSInteger rightBracLimit;
@property (nonatomic, assign) BOOL lefBracLimit;
@property (nonatomic, assign) BOOL OperLimit;
@property (nonatomic, assign) BOOL NumLimit;
@property (nonatomic, assign) BOOL pointLimitByNum;
@property (nonatomic, assign) BOOL pointLimitByOper;
@property (nonatomic, assign) BOOL OperLimitJJ;

@end

NS_ASSUME_NONNULL_END

MainViewController.m

#import "MainViewController.h"

#define MAXSIZE 100

@interface MainViewController ()

@end

@implementation MainViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self createView];
    
    [self createModel];
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

- (void) createView {
    self.mainView = [[MainView alloc] initWithFrame:self.view.bounds];
    
    [self.mainView initView];
    
    [self.view addSubview:self.mainView];
    
    // 设置按钮初始限制状态
    _rightBracLimit = 0;
    _lefBracLimit = YES;
    _NumLimit = YES;
    _OperLimit = NO;
    _pointLimitByNum = NO;
    _pointLimitByOper = YES;
    _OperLimitJJ = YES;
    
    for (UIButton* button in self.mainView.buttonArray) {
        [button addTarget:self action:@selector(pressButton:) forControlEvents:UIControlEventTouchUpInside];
    }
    
    [self.mainView.ACButton addTarget:self action:@selector(pressAcButton:) forControlEvents:UIControlEventTouchUpInside];
    
    [self.mainView.equalButton addTarget:self action:@selector(pressEqualButton:) forControlEvents:UIControlEventTouchUpInside];
    
    [self.mainView.pointButton addTarget:self action:@selector(pressPiontButton:) forControlEvents:UIControlEventTouchUpInside];
}

- (void) pressButton:(UIButton*)sender {
    if (sender.tag / 100 == 1) {
        [self pressBracButton:sender];
    } else if (sender.tag / 100 == 2) {
        [self pressOperButton:sender];
    } else if (sender.tag / 100 == 3) {
        [self pressNumberButton:sender];
    }
}

// 处理括号
- (void) pressBracButton:(UIButton*)sender {
    if (sender.tag == 101) {
        if (_lefBracLimit) {
            NSString* oldCalculation = self.mainView.calculation.text;
            NSString* newChar = sender.titleLabel.text;
            NSString* newCalculation = [NSString stringWithFormat:@"%@%@", oldCalculation, newChar];
            
            self.mainView.calculation.text = newCalculation;
            
            if (_rightBracLimit < 0) {
                _rightBracLimit = -_rightBracLimit;
            }
            _rightBracLimit++;
            _OperLimit = NO;
            _NumLimit = YES;
            _OperLimitJJ = YES;
            
            _pointLimitByNum = NO;
            _pointLimitByOper = YES;
        }
    } else {
        if (_rightBracLimit > 0) {
            NSString* oldCalculation = self.mainView.calculation.text;
            NSString* newChar = sender.titleLabel.text;
            NSString* newCalculation = [NSString stringWithFormat:@"%@%@", oldCalculation, newChar];
            
            self.mainView.calculation.text = newCalculation;
            
            _rightBracLimit = _rightBracLimit - 1;
            
            _lefBracLimit = NO;
            _NumLimit = NO;
            _OperLimit = YES;
            
            _pointLimitByNum = NO;
            _pointLimitByOper = YES;
            _OperLimitJJ = YES;
        }
    }
}

- (void) pressOperButton:(UIButton*)sender {
    if (sender.tag > 201) {
        [self pressOperButtonCC:sender];
    } else {
        [self pressOperButtonJJ:sender];
    }
}

// C:乘 C:除
- (void) pressOperButtonCC:(UIButton*)sender {
    if (_OperLimit) {
        NSString* oldCalculation = self.mainView.calculation.text;
        NSString* newChar = sender.titleLabel.text;
        NSString* newCalculation = [NSString stringWithFormat:@"%@%@", oldCalculation, newChar];
        
        self.mainView.calculation.text = newCalculation;
        
        _OperLimit = NO;
        _OperLimitJJ = NO;
        _NumLimit = YES;
        _lefBracLimit = YES;
        if (_rightBracLimit > 0) {
            _rightBracLimit = -_rightBracLimit;
        }
        _pointLimitByOper = YES;
        _pointLimitByNum = NO;
    }
}

// J:加 J:减
- (void) pressOperButtonJJ:(UIButton*)sender {
    if (_OperLimitJJ) {
        NSString* oldCalculation = self.mainView.calculation.text;
        NSString* newChar = sender.titleLabel.text;
        NSString* newCalculation = [NSString stringWithFormat:@"%@%@", oldCalculation, newChar];
        
        self.mainView.calculation.text = newCalculation;
        
        _OperLimit = NO;
        _OperLimitJJ = NO;
        _NumLimit = YES;
        _lefBracLimit = YES;
        if (_rightBracLimit > 0) {
            _rightBracLimit = -_rightBracLimit;
        }
        _pointLimitByOper = YES;
        _pointLimitByNum = NO;
    }
}

- (void) pressNumberButton:(UIButton*)sender {
    if (self.NumLimit) {
        NSString* oldCalculation = self.mainView.calculation.text;
        NSString* newChar = sender.titleLabel.text;
        NSString* newCalculation = nil;
        if ([newChar isEqual:@"0          "]) {
            newCalculation = [NSString stringWithFormat:@"%@0", oldCalculation];
        } else {
            newCalculation = [NSString stringWithFormat:@"%@%@", oldCalculation, newChar];
        }
        
        self.mainView.calculation.text = newCalculation;
        
        _lefBracLimit = NO;
        if (_rightBracLimit < 0) {
            _rightBracLimit = -_rightBracLimit;
        }
        _OperLimit = YES;
        _OperLimitJJ = YES;
        if (_pointLimitByOper) {
            _pointLimitByNum = YES;
        }
    }
}

- (void) pressPiontButton:(UIButton*)sender {
    if (_pointLimitByNum &amp;&amp; _pointLimitByOper) {
        NSString* oldCalculation = self.mainView.calculation.text;
        NSString* newChar = sender.titleLabel.text;
        NSString* newCalculation = [NSString stringWithFormat:@"%@%@", oldCalculation, newChar];
        
        self.mainView.calculation.text = newCalculation;
        
        _OperLimit = NO;
        _NumLimit = YES;
        _lefBracLimit = NO;
        if (_rightBracLimit > 0) {
            _rightBracLimit = -_rightBracLimit;
        }
        _pointLimitByNum = NO;
        _pointLimitByOper = NO;
        _OperLimitJJ = NO;
    }
}

- (void) pressAcButton:(UIButton*)sender {
    self.mainView.calculation.text = nil;
    
    // 设置按钮初始限制状态
    _rightBracLimit = 0;
    _lefBracLimit = YES;
    _NumLimit = YES;
    _OperLimit = NO;
    _pointLimitByNum = NO;
    _pointLimitByOper = YES;
    _OperLimitJJ = YES;
}

- (void) pressEqualButton:(UIButton*)sender {
    
    NSString* oldCalculation = self.mainView.calculation.text;
    NSString* newChar = sender.titleLabel.text;
    NSMutableString* newCalculation = [NSMutableString stringWithFormat:@"%@%@", oldCalculation, newChar];
    
    for (int i = 0; i < oldCalculation.length; i++) {
        NSString* s = [oldCalculation substringWithRange:NSMakeRange(i, 1)];
        
        if ([s isEqualToString:@"÷"]) {
            [newCalculation replaceCharactersInRange:NSMakeRange(i, 1) withString:@"/"];
        } else if ([s isEqualToString:@"×"]) {
            [newCalculation replaceCharactersInRange:NSMakeRange(i, 1) withString:@"*"];
        }
    }
    
    if ([self isCalculationTrue:newCalculation]) {
        [self.model Calculat:newCalculation];
    } else {
        self.mainView.calculation.text = @"error";
    }
    
    // 设置按钮初始限制状态
    _rightBracLimit = 0;
    _lefBracLimit = NO;
    _NumLimit = YES;
    _OperLimit = YES;
    _pointLimitByNum = NO;
    _pointLimitByOper = YES;
    _OperLimitJJ = YES;
}

- (BOOL) isCalculationTrue:(NSString*)calculation {
    if ([calculation containsString:@"e"]) {
        return NO;
    } else if ([calculation containsString:@"r"]) {
        return NO;
    } else if ([calculation containsString:@"o"]) {
        return NO;
    } else if (_rightBracLimit) {
        return NO;
    } else {
        NSInteger index = calculation.length - 2;
        NSString* s = [calculation substringWithRange:NSMakeRange(index, 1)];
        
        if ([s isEqualToString:@"+"]) {
            return NO;
        } else if ([s isEqualToString:@"-"]) {
            return NO;
        } else if ([s isEqualToString:@"*"]) {
            return NO;
        } else if ([s isEqualToString:@"/"]) {
            return NO;
        } else {
            return YES;
        }
    }
}

- (void) createModel {
    self.model = [[CalculatorModel alloc] init];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(upAnswer:) name:@"answer" object:nil];
    
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(upError) name:@"error" object:nil];
}

- (void) upAnswer:(NSNotification*)notification {
    NSDictionary* answer = notification.userInfo;
    
    
    self.mainView.calculation.text = answer[@"Value"];
}

- (void) upError {
    self.mainView.calculation.text = @"error";
}

@end

运算

首先我需要模拟一个栈。我是建立一个对象CalculatorStack
CalculatorStack.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

#define MAXSIZE 100

NS_ASSUME_NONNULL_BEGIN

@interface CalculatorStack : NSObject
{
    CGFloat _data[MAXSIZE];
    NSInteger _top;
}

- (void) Push:(CGFloat)element;
- (CGFloat) Pop;
- (CGFloat) GetTop;
- (void) initStack;

@end

NS_ASSUME_NONNULL_END

CalculatorStack.m

#import "CalculatorStack.h"

@implementation CalculatorStack
- (id) init {
    if (self = [super init]) {
        _top = -1;
    }
    return self;
}

- (void) initStack {
    _top = -1;
}

- (void) Push:(CGFloat)element {
    if (_top == 99) {
        return;
    }
    _data[++_top] = element;
}

- (CGFloat) Pop {
    if (_top == -1) {
        return 0;
    }
    return _data[_top--];
}

- (CGFloat) GetTop {
    if (_top == -1) {
        return 0;
    }
    return _data[_top];
}

@end

在Model中计算,我使用后缀表达式

  1. 建立两个栈,一个存数字,一个存运算符
  2. 运算符栈压入一个“=”,主要用于计算第一个运算符优先级
  3. 从左向右扫描表达式
  4. 遇到数字存入数字栈。
  5. 遇到运算符,与栈顶运算符比较优先级。优先级大,压入栈中;优先级小,计算栈顶运算符;优先级相等,证明匹配到“()”,弹出栈运算符。

CalculatorModel.h

#import <Foundation/Foundation.h>
#import "CalculatorStack.h"

NS_ASSUME_NONNULL_BEGIN

@interface CalculatorModel : NSObject
{
    CalculatorStack* _Num;
    CalculatorStack* _Oper;
}
- (void) Calculat:(NSString*)calculationString;
@end

NS_ASSUME_NONNULL_END

CalculatorModel.m

#import "CalculatorModel.h"

int  cmp[7][7]  = {
        { 2, 2, 1, 1, 1, 2, 2 },
        { 2, 2, 1, 1, 1, 2, 2 },
        { 2, 2, 2, 2, 1, 2, 2 },
        { 2, 2, 2, 2, 1, 2, 2 },
        { 1, 1, 1, 1, 1, 3, 0 },
        { 2, 2, 2, 2, 0, 2, 2 },
        { 1, 1, 1, 1, 1, 0, 3 }  };

char op[7] = {'+', '-', '*', '/', '(', ')', '='};

@implementation CalculatorModel

- (id) init {
    if (self = [super init]) {
        _Num = [[CalculatorStack alloc] init];
        _Oper = [[CalculatorStack alloc] init];
    }
    return self;
}

- (BOOL) inCalculator:(char)ch {
    if (ch == '+' || ch == '*' || ch == '/' || ch == '-' || ch == '(' || ch == ')' || ch == '=') {
        return YES;
    }
    return NO;
}

- (char) CompareOper1:(char)oper1 AndOper2:(char)oper2 {
    int m = 0, n = 0, i, ans;
    for(i = 0; i < 7; i++) {
        if(oper1 == op[i]) {
            m = i;
        }
        if(oper2 == op[i]) {
            n = i;
        }
    }
    ans = cmp[m][n];
    switch (ans) {
        case 2:
            return (char)('<');
        case 1:
            return (char)('>');
        case 3:
            return (char)('=');
        default:
            return 0;
        }
}

- (CGFloat) countNum1:(CGFloat)num1 Num2:(CGFloat)num2 AndOper:(char)oper {
    CGFloat val = 0;
    switch (oper) {
        case '+':
            val = num1 + num2;
            break;
        case '-':
            val = num1 - num2;
            break;
        case '*':
            val = num1 * num2;
            break;;
        case '/':
            val = num1 / num2;
            break;
        default:
            break;
    }
    
    return val;
}

- (void) Calculat:(NSString *)calculationString {
    
    [_Oper initStack];
    [_Num initStack];
    
    char* calculation = (char*)[calculationString UTF8String];
    NSInteger length = calculationString.length;
    char ch;
    CGFloat x1, x2, val;
    char oper;
    int BracFlage = 0;
    int flage = 0;
    
    [_Oper Push:'='];
    
    for (int i = 0; i < length; i++) {
        ch = calculation[i];
        
        if (![self inCalculator:ch]) {
            val = 0;
            while (![self inCalculator:ch] &amp;&amp; i < length) {
                val = val * 10 + (ch - '0');
                ch = calculation[++i];
                if (ch == '.') {
                    ch = calculation[++i];
                    int j = 1;
                    while (![self inCalculator:ch] &amp;& i < length) {
                        CGFloat f = (CGFloat)(ch - '0');
                        val = val + f / (10 * j);
                        j++;
                        ch = calculation[++i];
                    }
                }
            }
            i--;
            if (flage== 0) {
                [_Num Push:val];
            } else {
                [_Num Push:-val];
                flage = 0;
            }
        } else {
            if (BracFlage == 0 || (ch != '-' && ch != '+')) {
                switch([self CompareOper1:[_Oper GetTop] AndOper2:ch]) {
                    case '>':
                        [_Oper Push:ch];
                        break;
                    case '=':
                        [_Oper Pop];
                        break;
                    case '<':
                        oper = [_Oper Pop];
                        x2 = [_Num Pop];
                        x1 = [_Num Pop];
                        if (oper == '/' && x2 == 0) {
                            [[NSNotificationCenter defaultCenter] postNotificationName:@"error" object:nil];
                            return;
                        }
                        val = [self countNum1:x1 Num2:x2 AndOper:oper];
                        [_Num Push:val];
                        i--;
                        break;
                    default:
                        break;
                }
            }
            if (BracFlage == 1 && ch == '-') {
                flage = 1;
            }
            if (BracFlage == 1 && ch == ')') {
                [[NSNotificationCenter defaultCenter] postNotificationName:@"error" object:nil];
                return;
            }
        }
        BracFlage = 0;
        if (ch == '(') {
            BracFlage = 1;
        }
    }
    [self CGFloatToNSString:[_Num Pop]];
}

- (void) CGFloatToNSString:(CGFloat)answer {
    NSMutableString* answerString = [NSMutableString stringWithFormat:@"%lf", answer];
    if (![answerString isEqualToString:@"0"]) {
        for (NSInteger i = answerString.length - 1; i >= 0; i--) {
            NSString* s = [answerString substringWithRange:NSMakeRange(i, 1)];
            if ([s isEqualToString:@"0"]) {
                [answerString deleteCharactersInRange:NSMakeRange(i, 1)];
            } else if ([s isEqualToString:@"."]) {
                [answerString deleteCharactersInRange:NSMakeRange(i, 1)];
                break;
            } else {
                break;;
            }
        }
    }
    
    NSDictionary* answerDict = [NSDictionary dictionaryWithObject:answerString forKey:@"Value"];
    
    [[NSNotificationCenter defaultCenter] postNotificationName:@"answer" object:nil userInfo:answerDict];
}

@end

注:我使用两个flag分辨正负号和加减号。我们需要将加减号当作正负处理的情况只有一种,就是在左括号后紧跟的加减号。我们一个flag检测左括号,一个flag检测加减号。如果我们在检测到左括号后紧跟着检测到加减号,就见此次加减号当作正负号处理。

原文地址:https://blog.csdn.net/m0_63852285/article/details/127129013

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若转载,请注明出处:http://www.7code.cn/show_9315.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱:suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注