实现四则运算的算法思路是:首先输入的是中缀表达式的字符串,然后将其转为计算机可以理解的后缀表达式,然后将后缀表达式求值:
中缀转后缀表达式思路参考:《数据结构》:中缀表达式转后缀表达式 + 后缀表达式的计算
在该思路的基础上,会遇见以下几个问题:
//定义一个全局变量n,用于记录后缀表达式数组的下标
static int n = 0;
//栈的定义和初始化以及入栈出栈等操作
typedef struct result {
char stack[10000];
int top;
char nBoLan[10000];
}Result;
Result* CreatStack(void) {
Result *stack = (Result*)malloc(sizeof(Result));
stack->top = -1;
return stack;
}
void PushStack(Result *obj, char val) {
obj->stack[++obj->top] = val;
}
void PopStack(Result *obj) {
if (obj->top >= 0) {
obj->top--;
}
}
char GetTopStack(Result *obj) {
if (obj->top >= 0) {
return obj->stack[obj->top];
}
return 0;
}
//将中缀表达式转为后缀表达式
void caoZuoStack(char a, Result *obj) {
if (a == '+' || a == '-') {
if (obj->stack[obj->top] == '-') {
while(obj->stack[obj->top] != '(' && obj->top >= 0) {
obj->nBoLan[n++] = GetTopStack(obj);
PopStack(obj);
}
PushStack(obj, a);
obj->nBoLan[n++] = ',';
} else if (obj->stack[obj->top] == '(') {
PushStack(obj, a);
obj->nBoLan[n++] = ',';
} else if (obj->stack[obj->top] == '*' || obj->stack[obj->top] == '/') {
while (obj->stack[obj->top] != '(' && obj->top >= 0) {
obj->nBoLan[n++] = GetTopStack(obj);
PopStack(obj);
}
PushStack(obj, a);
obj->nBoLan[n++] = ',';
} else {
PushStack(obj, a);
obj->nBoLan[n++] = ',';
}
} else if (a == '*' || a == '/'){
if (obj->stack[obj->top] == '/') {
obj->nBoLan[n++] = GetTopStack(obj);
PopStack(obj);
PushStack(obj, a);
obj->nBoLan[n++] = ',';
} else if (obj->stack[obj->top] == '(') {
PushStack(obj, a);
obj->nBoLan[n++] = ',';
} else {
PushStack(obj, a);
obj->nBoLan[n++] = ',';
}
} else if (a == ')') {
while(obj->stack[obj->top] != '(') {
obj->nBoLan[n++] = GetTopStack(obj);
PopStack(obj);
}
PopStack(obj);
} else if (a == '(') {
PushStack(obj, a);
} else if (a != '=' && a != ')' && a != '(') {
obj->nBoLan[n++] = a;
}
if (a == '=') {
while(obj->top >= 0) {
obj->nBoLan[n++] = GetTopStack(obj);
PopStack(obj);
}
}
printf("%s\n", obj->nBoLan);
}
//后缀表达式求值
double evalRPN(char *tokens, int tokensSize){
int top = -1;
double stack[100];
for (int i = 0; i < tokensSize; i++) {
if (tokens[i] == ',' || tokens[i] == '(' || tokens[i] == ')') {
continue;
}
if (tokens[i] == '+') {
stack[top - 1] = stack[top] + stack[top - 1];
top--;
continue;
}
if (tokens[i] == '-') {
stack[top - 1] = stack[top - 1] - stack[top];
top--;
continue;
}
if (tokens[i] == '*') {
stack[top - 1] = stack[top] * stack[top - 1];
top--;
continue;
}
if (tokens[i] == '/') {
stack[top - 1] = stack[top - 1] / stack[top];
top--;
continue;
} else {
int sum = 0;
char *s = (char*)malloc(sizeof(char) * 2 * (sum+1));
while (tokens[i] != ',' && tokens[i] != '+' && tokens[i] != '-' && tokens[i] != '*' && tokens[i] != '/' && tokens[i] != '(' && tokens[i] != ')') {
s[sum++] = tokens[i];
i++;
}
if (tokens[i] == '+' || tokens[i] == '-' || tokens[i] == '*' || tokens[i] == '/' || tokens[i] == '(' || tokens[i] == ')') {
i--;
}
char *t;
double theNum = strtod(s, &t);
stack[++top] = theNum;
}
continue;
}
return stack[top];
}
//将计算器输入的字符串传给上面两个函数
- (double)jiSuan: (NSString*)putInStr {
NSLog(@"%@", putInStr);
n = 0;
Result *obj = CreatStack();
//对负数进行判断
for (int i = 0; i < [putInStr length]; i++) {
if ((i == 0 && [putInStr characterAtIndex:0] == '-') || ([putInStr characterAtIndex:i] == '-' && ([putInStr characterAtIndex:i-1] == '+' || [putInStr characterAtIndex:i-1] == '-' || [putInStr characterAtIndex:i-1] == '*' || [putInStr characterAtIndex:i-1] == '/' || [putInStr characterAtIndex:i-1] == '('))) {
caoZuoStack('(', obj);
caoZuoStack('0', obj);
caoZuoStack('-', obj);
i++;
while (([putInStr characterAtIndex:i] >= 48 && [putInStr characterAtIndex:i] <= 57) || [putInStr characterAtIndex:i] == '.') {
caoZuoStack([putInStr characterAtIndex:i], obj);
i++;
}
caoZuoStack(')', obj);
i--;
continue;
}
caoZuoStack([putInStr characterAtIndex:i], obj);
}
int tokensSize = (int)strlen(obj->nBoLan);
printf("%lf", evalRPN(obj->nBoLan, tokensSize));
//返回结果
return evalRPN(obj->nBoLan, tokensSize);
}
本次计算机的仿写我使用的是mvc模式,并且布局使用了Masonry框架。
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface Model : NSObject
@property (nonatomic, strong) NSMutableString *StrNum;
@property (nonatomic, assign) int a;
@end
NS_ASSUME_NONNULL_END
#import "Model.h"
@implementation Model
- (Model*)init {
self.a = 0;
if (self = [super init]) {
self.StrNum = [[NSMutableString alloc] init];
}
return self;
}
@end
#import <UIKit/UIKit.h>
#import "Masonry.h"
NS_ASSUME_NONNULL_BEGIN
@interface View : UIView
@property (nonatomic, strong) UILabel *label;
@property (nonatomic, strong) UIButton *Button;
@end
NS_ASSUME_NONNULL_END
#import "View.h"
#import "Masonry.h"
#define MAS_SHORTHAND
#define MAS_SHORTHAND_GLOBALS
@implementation View
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
self.backgroundColor = [UIColor blackColor];
//显示在计算器上方的label,用于显示表达式及结果
self.label = [[UILabel alloc] init];
[self addSubview:self.label];
self.label.textColor = [UIColor whiteColor];
self.label.textAlignment = NSTextAlignmentRight;
[self.label mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(25);
make.top.mas_equalTo(270);
make.height.mas_equalTo(@100);
make.width.mas_equalTo(360);
}];
self.label.font = [UIFont systemFontOfSize:50];
//for循环创建button,button的点击事件用来触发通知传值
for (int i = 0; i < 5; i++) {
for (int j = 0; j < 4; j++) {
self.Button = [UIButton buttonWithType:UIButtonTypeCustom];
[self addSubview:self.Button];
[self.Button mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(102 * j + 15);
make.top.mas_equalTo(102 * i + 375);
make.width.and.height.mas_equalTo(@90);
}];
[self.Button addTarget:self action:@selector(pressPutin:) forControlEvents:UIControlEventTouchUpInside];
self.Button.layer.cornerRadius = 45;
self.Button.layer.masksToBounds = YES;
self.Button.titleLabel.font = [UIFont systemFontOfSize:40];
self.Button.tag = i * 4 + j;
if (self.Button.tag == 0) {
[self.Button setTitle:@"AC" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor grayColor]];
}
if (self.Button.tag == 1) {
[self.Button setTitle:@"(" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor grayColor]];
}
if (self.Button.tag == 2) {
[self.Button setTitle:@")" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor grayColor]];
}
if (self.Button.tag == 3) {
[self.Button setTitle:@"/" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor orangeColor]];
}
if (self.Button.tag == 4) {
[self.Button setTitle:@"7" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor darkGrayColor]];
}
if (self.Button.tag == 5) {
[self.Button setTitle:@"8" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor darkGrayColor]];
}
if (self.Button.tag == 6) {
[self.Button setTitle:@"9" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor darkGrayColor]];
}
if (self.Button.tag == 7) {
[self.Button setTitle:@"*" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor orangeColor]];
}
if (self.Button.tag == 8) {
[self.Button setTitle:@"4" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor darkGrayColor]];
}
if (self.Button.tag == 9) {
[self.Button setTitle:@"5" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor darkGrayColor]];
}
if (self.Button.tag == 10) {
[self.Button setTitle:@"6" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor darkGrayColor]];
}
if (self.Button.tag == 11) {
[self.Button setTitle:@"-" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor orangeColor]];
}
if (self.Button.tag == 12) {
[self.Button setTitle:@"1" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor darkGrayColor]];
}
if (self.Button.tag == 13) {
[self.Button setTitle:@"2" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor darkGrayColor]];
}
if (self.Button.tag == 14) {
[self.Button setTitle:@"3" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor darkGrayColor]];
}
if (self.Button.tag == 15) {
[self.Button setTitle:@"+" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor orangeColor]];
}
if (self.Button.tag == 16) {
[self.Button setTitle:@"0" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor darkGrayColor]];
[self.Button mas_updateConstraints: ^(MASConstraintMaker *make) {
make.left.mas_equalTo(102 * j + 15);
make.top.mas_equalTo(102 * i + 375);
make.width.mas_equalTo(@192);
make.height.mas_equalTo(@90);
}];
}
if (self.Button.tag == 17) {
[self.Button setTitle:@"." forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor darkGrayColor]];
[self.Button mas_updateConstraints: ^(MASConstraintMaker *make) {
make.left.mas_equalTo(102 * (j+1) + 15);
make.top.mas_equalTo(102 * i + 375);
make.width.and.height.mas_equalTo(@90);
}];
}
if (self.Button.tag == 18) {
[self.Button setTitle:@"=" forState:UIControlStateNormal];
[self.Button setBackgroundColor:[UIColor orangeColor]];
[self.Button mas_updateConstraints: ^(MASConstraintMaker *make) {
make.left.mas_equalTo(102 * (j+1) + 15);
make.top.mas_equalTo(102 * i + 375);
make.width.and.height.mas_equalTo(@90);
}];
}
}
}
return self;
}
//通知传值
- (void)pressPutin: (UIButton*)Button {
//NSLog(@"OK");
NSDictionary *dict =[NSDictionary dictionaryWithObject:Button forKey:@"btn"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"NumGo" object:nil userInfo:dict];
}
@end
#import "ViewController.h"
#include
#include
#include
#include
#include
@interface ViewController ()
@property (nonatomic, strong) View *aView;
@property (nonatomic, strong) Model *model;
@end
static int pointNum = 0;
static int kuoHaoNum = 0;
static int fuHaoNum = 0;
static int jianHao = 0;
static int numAKuoHao = 1;
static int inKuoHao = 0;
static int dengYu = 0;
static int point = 1;
static int dengYuNum = 0;
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.aView = [[View alloc] initWithFrame:self.view.bounds];
[self.view addSubview:self.aView];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pressNum:) name:@"NumGo" object:nil];
self.model = [[Model alloc] init];
[self.model addObserver:self forKeyPath:@"a" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
self.aView.label.text = [NSString stringWithFormat:@"%@",self.model.StrNum];
self.aView.label.adjustsFontSizeToFitWidth = YES;
}
- (void)pressWanCheng {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (void)pressNum: (NSNotification*)sender{
UIButton *Button = sender.userInfo[@"btn"];
if(Button.tag == 0) {
pointNum = 0;
kuoHaoNum = 0;
fuHaoNum = 0;
jianHao = 0;
numAKuoHao = 1;
inKuoHao = 0;
dengYu = 0;
point = 1;
dengYuNum = 0;
NSUInteger a = [self.model.StrNum length];
[self.model.StrNum deleteCharactersInRange:NSMakeRange(0, a)];
}
if (Button.tag == 1) {
if(numAKuoHao) {
[self.model.StrNum appendFormat:@"("];
pointNum = 0;
kuoHaoNum++;
fuHaoNum = 0;
jianHao = 1;
numAKuoHao = 1;
inKuoHao = 0;
dengYu = 0;
point = 1;
dengYuNum++;
} else {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"输入格式错误" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alert animated:YES completion:nil];
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(pressWanCheng) userInfo:nil repeats:NO];
}
}
if (Button.tag == 2) {
if(fuHaoNum && inKuoHao && kuoHaoNum != 0) {
[self.model.StrNum appendFormat:@")"];
pointNum = 0;
kuoHaoNum--;
fuHaoNum = 1;
jianHao = 1;
numAKuoHao = 0;
dengYu = 1;
point = 1;
dengYuNum++;
} else {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"输入格式错误" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alert animated:YES completion:nil];
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(pressWanCheng) userInfo:nil repeats:NO];
}
}
if (Button.tag == 3) {
if(fuHaoNum) {
[self.model.StrNum appendFormat:@"/"];
pointNum = 0;
fuHaoNum = 0;
jianHao = 1;
numAKuoHao = 1;
inKuoHao = 1;
dengYu = 0;
point = 1;
dengYuNum++;
} else {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"输入格式错误" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alert animated:YES completion:nil];
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(pressWanCheng) userInfo:nil repeats:NO];
}
}
if(Button.tag == 4) {
[self.model.StrNum appendFormat:@"7"];
pointNum = 1;
fuHaoNum = 1;
jianHao = 2;
numAKuoHao = 0;
dengYu = 1;
}
if(Button.tag == 5) {
[self.model.StrNum appendFormat:@"8"];
pointNum = 1;
fuHaoNum = 1;
jianHao = 2;
numAKuoHao = 0;
dengYu = 1;
}
if(Button.tag == 6) {
[self.model.StrNum appendFormat:@"9"];
pointNum = 1;
fuHaoNum = 1;
jianHao = 2;
numAKuoHao = 0;
dengYu = 1;
}
if (Button.tag ==7) {
if(fuHaoNum) {
[self.model.StrNum appendFormat:@"*"];
pointNum = 0;
fuHaoNum = 0;
jianHao = 1;
numAKuoHao = 1;
inKuoHao = 1;
dengYu = 0;
point = 1;
dengYuNum++;
} else {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"输入格式错误" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alert animated:YES completion:nil];
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(pressWanCheng) userInfo:nil repeats:NO];
}
}
if(Button.tag == 8) {
[self.model.StrNum appendFormat:@"4"];
pointNum = 1;
fuHaoNum = 1;
jianHao = 2;
numAKuoHao = 0;
dengYu = 1;
}
if(Button.tag == 9) {
[self.model.StrNum appendFormat:@"5"];
pointNum = 1;
fuHaoNum = 1;
jianHao = 2;
numAKuoHao = 0;
dengYu = 1;
}
if(Button.tag == 10) {
[self.model.StrNum appendFormat:@"6"];
pointNum = 1;
fuHaoNum = 1;
jianHao = 2;
numAKuoHao = 0;
dengYu = 1;
}
if (Button.tag == 11) {
if ([self.model.StrNum length] == 0) {
[self.model.StrNum appendFormat:@"-"];
pointNum = 0;
fuHaoNum = 0;
jianHao = 0;
numAKuoHao = 1;
dengYu = 0;
point = 1;
} else if(jianHao) {
[self.model.StrNum appendFormat:@"-"];
pointNum = 0;
fuHaoNum = 0;
jianHao--;
numAKuoHao = 1;
inKuoHao = 1;
dengYu = 0;
point = 1;
dengYuNum++;
} else {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"输入格式错误" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alert animated:YES completion:nil];
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(pressWanCheng) userInfo:nil repeats:NO];
}
}
if(Button.tag == 12) {
[self.model.StrNum appendFormat:@"1"];
pointNum = 1;
fuHaoNum = 1;
jianHao = 2;
numAKuoHao = 0;
dengYu = 1;
}
if(Button.tag == 13) {
[self.model.StrNum appendFormat:@"2"];
pointNum = 1;
fuHaoNum = 1;
jianHao = 2;
numAKuoHao = 0;
dengYu = 1;
}
if(Button.tag == 14) {
[self.model.StrNum appendFormat:@"3"];
pointNum = 1;
fuHaoNum = 1;
jianHao = 2;
numAKuoHao = 0;
dengYu = 1;
}
if (Button.tag == 15) {
if(fuHaoNum) {
[self.model.StrNum appendFormat:@"+"];
pointNum = 0;
fuHaoNum = 0;
jianHao = 1;
numAKuoHao = 1;
inKuoHao = 1;
dengYu = 0;
point = 1;
dengYuNum++;
} else {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"输入格式错误" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alert animated:YES completion:nil];
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(pressWanCheng) userInfo:nil repeats:NO];
}
}
if(Button.tag == 16) {
[self.model.StrNum appendFormat:@"0"];
pointNum = 1;
fuHaoNum = 1;
jianHao = 2;
numAKuoHao = 0;
dengYu = 1;
}
if (Button.tag == 17) {
if(point && fuHaoNum && pointNum) {
[self.model.StrNum appendFormat:@"."];
pointNum = 0;
fuHaoNum = 0;
jianHao = 0;
numAKuoHao = 0;
dengYu = 0;
point = 0;
} else {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"输入格式错误" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alert animated:YES completion:nil];
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(pressWanCheng) userInfo:nil repeats:NO];
}
}
if (Button.tag == 19) {
if(dengYuNum && kuoHaoNum == 0 && dengYu) {
[self.model.StrNum appendFormat:@"="];
NSLog(@"%@", self.model.StrNum);
double b = [self jiSuan:self.model.StrNum];
NSUInteger a = [self.model.StrNum length];
[self.model.StrNum deleteCharactersInRange:NSMakeRange(0, a)];
[self.model.StrNum appendFormat:@"%.9g", b];
if ([self.model.StrNum isEqual: @"inf"]) {
NSUInteger a = [self.model.StrNum length];
[self.model.StrNum deleteCharactersInRange:NSMakeRange(0, a)];
[self.model.StrNum appendFormat:@"不能除以0"];
}
} else {
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:@"输入格式错误" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alert animated:YES completion:nil];
[NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(pressWanCheng) userInfo:nil repeats:NO];
}
}
self.model.a++;
}
/*此处插入上面四则运算的代码*/
@end