iOS——仿写计算器

四则运算:中缀表达式转后缀表达式+后缀表达式求值

实现四则运算的算法思路是:首先输入的是中缀表达式的字符串,然后将其转为计算机可以理解的后缀表达式,然后将后缀表达式求值:
中缀转后缀表达式思路参考:《数据结构》:中缀表达式转后缀表达式 + 后缀表达式的计算
在该思路的基础上,会遇见以下几个问题:

  1. 输入多位数时无法识别出该多位数,可能求值时计算成好几位一位数。我的解决方法是将输入的数字使用",“分隔开,因为每两个相邻的运算符之间只会有一个数,所以在转为后缀表达式时,每当遍历到的字符是一个运算符,就再为存储我们得到的后缀表达式的那个数组中添加一个”,“将数字分隔开,然后在后缀求值的部分,每当读取到一个”,“,就continue掉,然后在读到数字的时候,就先定义一个动态数组,然后使用一个while循环一直循环将当前数字存入数组中,直到遍历到的元素是下一个”,",此时就跳出循环,然后将该动态数组存入栈中,实现多位数的计算。
  2. 小数点的判断:小数点的判断和多位数一样,将小数点的判定条件和数字一样,存入动态数组时也是一样。存入数组后,我们使用c语言中的strtod函数可以将一个字符串识别为浮点数,便可以很简单的完成小数点的读取。
  3. 括号的判断:括号的判断在这里是一个非常复杂的点:首先在转化为后缀表达式的部分,如果遇到的是左括号,就直接入栈(注:左括号入栈后优先级降至最低)。如果遇到的字符为右括号,就直接出栈,并将出栈字符依次送入后缀表达式,直到栈顶字符为左括号(左括号也要出栈,但不送入后缀表达式)。总结就是:只要满足栈顶为左括号即可进行最后一次出栈。
  4. 负数的判断:对于负数的判断,我的思路是将原本的中缀表达式理解为:-x = (0-x)来进行转化后缀表达式的操作。即在将当前字符串元素传入中缀转后缀表达式的函数中时,判断当前元素是否是"-“,然后判断该元素的上一个元素是否为运算符/括号或者该元素是否是字符串的第一个元素,如果是,就可以将该字符串的这一部分理解为负数。找到为负数的”-“后,首先不将该”-“传入转后缀的函数,而是先依次将”(“,“0"传入,然后再传入当前的”-”,然后再使用一个while循环依次将负数的数字部分的元素传入(记得此时也要一直更改着遍历字符串的下标位置),直到读到的元素为运算符/括号时跳出循环,然后再传入一个")"到转后缀的函数中,至此,我们得到的后缀表达式就是可以正确计算负数的后缀表达式了。然后再计算后缀表达式的部分不用修改,因为负数部分会计算为(0-x)的。
    以下是我四则运算部分的代码实现:
//定义一个全局变量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框架。

  • 在model层:我使用了一个可变数组来存储表达式以及结果,当在计算器上点击输入表达式时,点击的合法的按钮的会传相应的值到该字符串中,点击AC按钮时将会清空该字符串,点击“=”按钮后将会先计算表达式的结果,然后清空该字符串,然后再将得到的结果传入该字符串。model层和controller层使用KVO传值,但是该KVO传值的监听对象并不是该可变数组对象,因为前面学过KVO只是监听setter方法,但是向可变数组添加元素的方法它不属于setter方法,所以即使你向数组中add多少个元素也不会有监听反应。所以这里我的操作是再model层再声明一个int类型的a属性,并在初始化的时候给其赋值为0,然后使用KVO监听该a属性,在controller层中,每当点击了按钮,就将该a属性自增使得其值改变,由此就可以触发监听事件。在监听事件中,将view层声明的label属性的text属性赋值为该可变字符串,这样就可以实现每当点击按钮,上面的表达式可以随时改变。
    代码实现:
#import <Foundation/Foundation.h>NS_ASSUME_NONNULL_BEGIN@interface Model : NSObject@property (nonatomic, strong) NSMutableString *StrNum;
@property (nonatomic, assign) int a;@endNS_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
  • 在view层:我使用了一个for循环循环创建button,并为每个button的tag赋值,并使用Masonry框架等对其布局。布局这块直接看代码就行了不多赘述。在view层和controller层之间的交互我是使用了通知传值,在view层将button存入一个字典然后用通知传值传给controller层,在controller中对传来的button的tag值进行判断。
    代码实现:
#import <UIKit/UIKit.h>
#import "Masonry.h"NS_ASSUME_NONNULL_BEGIN@interface View : UIView@property (nonatomic, strong) UILabel *label;
@property (nonatomic, strong) UIButton *Button;@endNS_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
  • controller层:在controller层中我要对传来的button的tag进行判断并改变可变数组,并且要对按钮的点击进行限制,而且要将前面我们写过的四则运算式子写在这里。对按钮输入限制的判断:我定义了很多个全局变量,例如fuHaoNum,如果点击了ac按钮,就将其赋为初值0,因为字符串中没有元素时不能输入运算符(负号除外)。如果点击了运算符和括号,就将该值赋为0,因为除了负号外,其他运算符和括号不能连续两个相邻。如果点击了数字,就将该值赋为1,因为数字后面可以跟运算符,如果点击了小数点,就将该值赋为0…由此实现限制。
    代码实现:
#import "ViewController.h"#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
#include<math.h>@interface ViewController ()@property (nonatomic, strong) View *aView;
@property (nonatomic, strong) Model *model;@endstatic 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

结果:
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/150660.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

现货白银图表分析的依据

现货白银的行情图表分析其实与股票的差不多&#xff0c;投资者可以结合均线、k线的变化&#xff0c;来分析实时的行情走势。当走势图的均线呈多头排列&#xff0c;即短期、中期、长期均线依次从上到下排列并向右上方运行&#xff0c;且白银价格沿各均线向右上方拉升&#xff0c…

数据产品读书笔记——认识数据产品经理

&#x1f33b;大家可能听说的更多是产品经理这个角色&#xff0c;对数据产品经理可能或多或少了解一些&#xff0c;但又不能准确的描述数据产品经理的主要职能和与其他产品的不同&#xff0c;因此通过读一些书来对数据产品经理有一个准确且全面的认知。 目录 1. 数据的产品分类…

基于生物地理学优化的BP神经网络(分类应用) - 附代码

基于生物地理学优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码 文章目录 基于生物地理学优化的BP神经网络&#xff08;分类应用&#xff09; - 附代码1.鸢尾花iris数据介绍2.数据集整理3.生物地理学优化BP神经网络3.1 BP神经网络参数设置3.2 生物地理学算法应用 4…

Vue中如何进行图像识别与人脸对比(如百度AI、腾讯AI)

Vue中的图像识别与人脸对比 在现代Web应用程序中&#xff0c;图像识别和人脸对比技术越来越受欢迎。它们可以用于各种用途&#xff0c;如人脸识别门禁系统、图像分类和验证等。百度AI和腾讯AI是两个流行的人工智能平台&#xff0c;它们提供了强大的图像识别和人脸对比API。本文…

Sketch for mac v98.3(ui设计矢量绘图)

Sketch是一款为用户提供设计和创建数字界面的矢量编辑工具。它主要用于UI/UX设计师、产品经理和开发人员&#xff0c;帮助他们快速设计和原型各种应用程序和网站。 Sketch具有简洁直观的界面&#xff0c;以及丰富的功能集&#xff0c;使得用户可以轻松地创建、编辑和共享精美的…

【华为OD机考】统计监控、需要打开多少监控器(JAVA题解——也许是全网最优)

前言 本人是算法小白&#xff0c;甚至也没有做过Leetcode。所以&#xff0c;我相信【同为菜鸡的我更能理解作为菜鸡的你们的痛点】。 题干 OD&#xff0c;B 卷 100 分题目【OD 统一考试&#xff08;B 卷&#xff09;】 1. 题目描述 某长方形停车场每个车位上方都有一个监控…

Kafka快速实战以及基本原理详解

这一部分主要是接触 Kafka &#xff0c;并熟悉 Kafka 的使用方式。快速熟练的搭建 kafka 服务&#xff0c;对于快速验证一些基于Kafka 的解决方案&#xff0c;也是非常有用的。 一、 Kafka 介绍 ChatGPT 对于 Apache Kafka 的介绍&#xff1a; 1 、 MQ 的作用 MQ &#xff1a;…

网络原理 - 详解

一&#xff0c;网络通信基础 1.1 IP地址 描述一个设备在网络上的地址&#xff0c;一般使用4个0~255之间的数字&#xff0c;并且使用三给 . 进行分割&#xff0c;如&#xff1a;127.0.0.0 1.2 端口号 端口号是一个2个字节的整数&#xff0c;用来区分一个主机上的不同应用程序…

No168.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

Docker linux 安装

sudo yum update sudo yum clean all sudo yum makecache#安装依赖 sudo yum install -y yum-utils device-mapper-persistent-data lvm2 #添加官方存储库 sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo#安装-跳过一些异常依赖…

阿里云轻量应用服务器有月流量限制吗?

阿里云轻量应用服务器限制流量吗&#xff1f;部分限制&#xff0c;2核2G3M和2核4G4M这两款轻量应用服务器不限制月流量&#xff0c;其他的轻量服务器套餐有月流量限制。 腾讯云轻量应用服务器价格便宜&#xff0c;活动页面&#xff1a;aliyunbaike.com/go/tencent 细心的同学看…

HTML5+CSS3+移动web 前端开发入门笔记(二)HTML标签详解

HTML标签&#xff1a;排版标签 排版标签用于对网页内容进行布局和样式的调整。下面是对常见排版标签的详细介绍&#xff1a; <h1>: 定义一级标题&#xff0c;通常用于标题栏或页面主要内容的标题。<p>: 定义段落&#xff0c;用于将文字分段展示&#xff0c;段落之…

办公技巧:Excel日常高频使用技巧

目录 1. 快速求和&#xff1f;用 “Alt ” 2. 快速选定不连续的单元格 3. 改变数字格式 4. 一键展现所有公式 “CTRL ” 5. 双击实现快速应用函数 6. 快速增加或删除一列 7. 快速调整列宽 8. 双击格式刷 9. 在不同的工作表之间快速切换 10. 用F4锁定单元格 1. 快速求…

CSS学习笔记

目录 1.CSS简介1.什么是CSS2.为什么使用CSS3.CSS作用 2.基本用法1.CSS语法2.CSS应用方式1. 内部样式2.行内样式3.外部样式1.使用 link标签 链接外部样式文件2.import 指令 导入外部样式文件3.使用举例 3.选择器1.基础选择器1.标签选择器2.类选择器3.ID选择器4.使用举例 2.复杂选…

计算机视觉: 基于隐式BRDF自编码器的文生三维技术

论文链接: MATLABER: Material-Aware Text-to-3D via LAtent BRDF auto-EncodeR 背景 得益扩散模型和大量的text - image 成对的图片&#xff0c; 现在文生2D的模型已经比较成熟的框架和模型&#xff0c;主流的技术比如说stable diffusion 和 midjourney 以及工业领域runway 等…

ElasticSearch环境准备

Elasticsearch 是一个基于 Apache Lucene™ 的开源搜索引擎。不仅仅是一个全文搜索引擎&#xff0c;它还是一个分布式的搜索和分析引擎&#xff0c;可扩展并能够实时处理大数据。以下是关于 Elasticsearch 的一些主要特点和说明&#xff1a; 1.实时分析&#xff1a;Elasticsear…

反爬虫机制与反爬虫技术(一)

反爬虫机制与反爬虫技术一 1、网络爬虫的法律与道德问题2、反爬虫机制与反爬虫技术2.1、User-Agent伪装2.2、代理IP2.3、请求频率控制2.4、动态页面处理2.5、验证码识别3、反爬虫案例:豆瓣电影Top250爬取3.1、爬取目标3.2、库(模块)简介3.3、翻页分析3.4、发送请求3.5、数据…

【Solidity】智能合约案例——①食品溯源合约

目录 一、合约源码分析&#xff1a; 二、合约整体流程&#xff1a; 1.部署合约 2.管理角色 3.食品信息管理 4.食品溯源管理 一、合约源码分析&#xff1a; Producer.sol:生产者角色的管理合约&#xff0c;功能为&#xff1a;添加新的生产者地址、移除生产者地址、判断角色地址…

基于支持向量机SVM和MLP多层感知神经网络的数据预测matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 一、支持向量机&#xff08;SVM&#xff09; 二、多层感知器&#xff08;MLP&#xff09; 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 matlab2022a 3.部分核心程序 .…

vue3前端开发-flex布局篇

文章目录 1.传统布局与flex布局优缺点传统布局flex布局建议 2. flex布局原理2.1 布局原理 3. flex常见属性3.1 父项常见属性3.2 子项常见属性 4.案例实战(携程网首页) 1.传统布局与flex布局优缺点 传统布局 兼容性好布局繁琐局限性&#xff0c;不能再移动端很好的布局 flex布…