【iOS】——仿写计算器
文章目录
- 一、实现思路
- 二、实现方法
- 三、判错处理
一、实现思路
先搭建好MVC框架,接着在各个模块中实现各自的任务。首先要创建好UI界面,接着根据UI界面的元素来与数据进行互动,其中创建UI界面需要用到Masonry布局。
二、实现方法
在calculationView文件中只涉及到UI界面。
首先创建两个UITextField对象,一个用来显示输入到表达式,一个用来输出运算结果,接着创建一个数组用来存放button的名称,接着循环创建button对象即可。
创建button时需要设置button的tag属性,因为后面需要通过button的tag属性来进行逻辑判断。
self.textField01 = [[UITextField alloc] init];
self.textField01.backgroundColor = [UIColor blackColor];
self.textField02 = [[UITextField alloc] init];
self.textField02.backgroundColor = [UIColor blackColor];
self.buttonArray = [NSMutableArray arrayWithObjects:@"AC", @"(", @")", @"/", @"1", @"2", @"3", @"+", @"4", @"5", @"6", @"-", @"7", @"8", @"9", @"*", @"0", @".", @"=", nil];for (int i = 0; i < 4; i++) {for (int j = 0; j < 4; j++) {self.calculatorButton = [UIButton buttonWithType:UIButtonTypeCustom];NSString* buttonString = self.buttonArray[i * 4 + j];[self.calculatorButton setTitle:buttonString forState:UIControlStateNormal];self.calculatorButton.titleLabel.font = [UIFont systemFontOfSize:43];self.calculatorButton.titleLabel.textColor = [UIColor whiteColor];self.calculatorButton.backgroundColor = [UIColor grayColor];[self.calculatorButton addTarget:self action:@selector(pressButton:) forControlEvents:UIControlEventTouchUpInside];self.calculatorButton.layer.borderWidth = 2.0;self.calculatorButton.layer.cornerRadius = ButtonSize / 2;self.calculatorButton.layer.masksToBounds = YES;self.calculatorButton.tag = 100 + j + i*4;if (i == 0 && j < 3) {self.calculatorButton.backgroundColor = [UIColor colorWithWhite:0.6 alpha:0.9];self.calculatorButton.titleLabel.textColor = [UIColor blackColor];}if (j == 3) {self.calculatorButton.backgroundColor = [UIColor orangeColor];}[self addSubview:self.calculatorButton];[self.calculatorButton mas_makeConstraints:^(MASConstraintMaker *make) {make.top.equalTo(self).offset(90 + HEIGHT / 6 + HEIGHT / 8 + (ButtonSize + SideSize) * i);make.left.equalTo(self).offset(SideSize + (ButtonSize + SideSize) * j);make.width.equalTo(@ButtonSize);make.height.equalTo(@ButtonSize);}];}}
还需要在当前文件触发button的事件函数,因为要通过button的事件函数将当前button传值到CalculationViewController文件中。
我使用的协议传值进行
定义协议及协议方法
@protocol ButttonDelegate <NSObject>- (void)returnButton:(UIButton*)button;@end
定义代理对象
@property (nonatomic, weak)id<ButttonDelegate>delegate;
button事件函数触发代理方法
- (void)pressButton:(UIButton*)button {[self.delegate returnButton:button];
}
在CalculationViewController中定义协议方法
- (void)returnButton:(UIButton*)button;
在CalculationViewController中设置代理对象
self.calculationView.delegate = self;
在CalculationViewController中实现协议方法
- (void)returnButton:(UIButton*)button {
- NSString* buttonStr = button.titleLabel.text;NSInteger buttonTag = button.tag;if (buttonTag == 100) {self.calculationView.textField01.text = @"";self.calculationView.textField02.text = @"";self.yunsuanStr = [[NSMutableString alloc] init];self.jieguoStr = [[NSString alloc] init];} else if (buttonTag == 118) {//四则运算}//
}
对于四则运算,我使用中缀表达式转后缀表达式,再利用后缀表达式进行计算。中缀转后缀定义一个符号栈,一个结果栈。
char resultStack[100];int resultTop = -1;char operationStack[100];int operationTop = -1;NSString* ocStr = self.yunsuanStr;const char* strs = [ocStr UTF8String];char str[1000] ;strcpy(str, strs) ;int length = (int)strlen(str);
后缀进行四则运算时定义一个新栈。
double Stack[100];int StackTop = -1;char* token = strtok(resultStack, " ");while (token != NULL) {if (strcmp(token, "+") == 0) {double a = Stack[StackTop--];double b = Stack[StackTop--];double c = b + a;Stack[++StackTop] = c;}else if (strcmp(token, "-") == 0) {double a = Stack[StackTop--];double b = Stack[StackTop--];double c = b - a;Stack[++StackTop] = c;}else if (strcmp(token, "*") == 0) {double a = Stack[StackTop--];double b = Stack[StackTop--];double c = b * a;Stack[++StackTop] = c;}else if (strcmp(token, "/") == 0) {double a = Stack[StackTop--];double b = Stack[StackTop--];double c = b / a;Stack[++StackTop] = c;}else if (strcmp(token, "!") == 0) {double c = Stack[StackTop--];c = -c;Stack[++StackTop] = c;}else {double num = atof(token);Stack[++StackTop] = num;}token = strtok(NULL, " ");}double result = Stack[StackTop--];
这里使用了atof()函数可以将字符串中的数字识别为double类型的浮点数。使用strtok()函数将结果栈的元素通过空格分割方便进行识别和运算。
对于负数的运算,我是将与“(”相邻的“-”转换为“!”,并用“!”进行负数转变,其中需要将“!“的优先级设置为最高
int Compare(char str) {if (str == '(' || str == ')') {return 0;}else if (str == '+' || str == '-') {return 1;}else if (str == '*' || str == '/') {return 2;} else if (str == '!') {return 3;} else {return -1;}
}
接着在输入字符串时进行识别
for (int i = 0; i < length; ++i) {if (str[i] == '(' && str[i + 1] == '-') {str[i + 1] = '!';}}
三、判错处理
对于括号匹配问题,我使用栈来处理,当读到“(”则入栈,读到“)”则栈顶元素出栈,最后判断栈是否为空即可。
- (int)kuoHaoMatch:(NSMutableString*)mutableString {const char* cstr = [mutableString UTF8String];int length = (int)strlen(cstr);char stack[100];int stackTop = -1;for (int i = 0; i < length; i++) {if (cstr[i] == '(') {stack[++stackTop] = cstr[i];}if (cstr[i] == ')') {stack[stackTop--];}}if (stackTop == -1) {return 1;}return 0;
}
对于符号匹配问题,两个运算符不能相邻,第一个位置不能为运算符(-除外),最后一个位置不能为运算符
- (int)fuHaoMatch:(NSMutableString*)mutableString {const char* cstr = [mutableString UTF8String];int length = (int)strlen(cstr);if (cstr[0] == '*' || cstr[0] == '/' || cstr[0] == '+') {return 0;}for (int i = 0; i < length; i++) {if ((cstr[i] == '*' && cstr[i+1] == '/') || (cstr[i] == '/' && cstr[i+1] == '*')) {return 0;}if ((cstr[i] == '*' && cstr[i+1] == '-') || (cstr[i] == '*' && cstr[i+1] == '+')) {return 0;}if ((cstr[i] == '/' && cstr[i+1] == '-') || (cstr[i] == '/' && cstr[i+1] == '+')) {return 0;}if ((cstr[i] == '+' && cstr[i+1] == '/') || (cstr[i] == '+' && cstr[i+1] == '*')) {return 0;}if ((cstr[i] == '-' && cstr[i+1] == '/') || (cstr[i] == '-' && cstr[i+1] == '*')) {return 0;}if ((cstr[i] == '-' && cstr[i+1] == '-') || (cstr[i] == '-' && cstr[i+1] == '+')) {return 0;}if ((cstr[i] == '+' && cstr[i+1] == '+') || (cstr[i] == '+' && cstr[i+1] == '-')) {return 0;}}if (cstr[length - 1] == '+' || cstr[length - 1] == '-' ||cstr[length - 1] == '*' || cstr[length - 1] == '/') {return 0;}return 1;
}
对于数字和括号的相邻问题,数字后不能直接跟左括号,右括号不能直接跟数字
- (int)numberAndkuoHao:(NSMutableString*)mutableString {const char* cstr = [mutableString UTF8String];int length = (int)strlen(cstr);int flag = 0;for (int i = 0; i < length; i++) {if ((cstr[i]>= '0' && cstr[i] <= '9') &&cstr[i+1] == '(') {flag++;}if (cstr[i] == ')' && (cstr[i + 1]>= '0' && cstr[i + 1] <= '9')) {flag++;}}if (flag == 0) {return 1;}return 0;
}
对于只有括号没有数字的问题,直接遍历整个字符串如果有数字则标志变量加一,最后判断标志变量
- (int)numberJudge:(NSMutableString*)mutableString {const char* cstr = [mutableString UTF8String];int length = (int)strlen(cstr);int flag = 0;for (int i = 0; i < length; i++) {if (cstr[i]>= '0' && cstr[i] <= '9') {flag++;}}if (flag != 0) {return 1;}return 0;;
}
对于除零问题
if ([self.jieguoStr isEqualToString:@"nan"]) {self.jieguoStr = @"错误";}if ([self.jieguoStr isEqualToString:@"inf"]) {self.jieguoStr = @"错误";}
对于小数点异常处理
int pointFlag = 0;
for (int i = 0; i < resultTop; i++) {if (resultStack[i] == '.') {for (int j = i + 1; resultStack[j] != ' '; j++) {if (resultStack[j] == '.') {pointFlag++;}}}}if (pointFlag != 0) {self.jieguoStr = @"错误";pointFlag = 0;}
对于如何删除多余的零
NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString: self.jieguoStr];NSDecimalNumberHandler *roundHandler = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundUp scale:8 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];NSDecimalNumber *roundedNumber = [number decimalNumberByRoundingAccordingToBehavior:roundHandler];self.jieguoStr = [roundedNumber stringValue];
相关文章:

【iOS】——仿写计算器
文章目录 一、实现思路二、实现方法三、判错处理 一、实现思路 先搭建好MVC框架,接着在各个模块中实现各自的任务。首先要创建好UI界面,接着根据UI界面的元素来与数据进行互动,其中创建UI界面需要用到Masonry布局。 二、实现方法 在calcu…...

公安机关警务vr综合实战模拟训练提高团队合作能力
公安出警VR虚拟仿真培训软件是VR公司利用VR虚拟现实和web3d开发技术,对警务执法过程中可能发生的各种场景进行还原、模拟、演练,结合数据分析,实施量化考核,提高学员的心理承压、应急处突、遇袭反应和临危处置综合能力。 公安出警…...

MySQL-1(12000字详解)
一:数据库的引入 数据库在我们以后工作中是一个非常常用的知识,数据库用来存储数据,但是有些同学可能就会疑惑了,存储数据用文件就可以了,为什么还要弄个数据库呢? 文件保存数据有以下几个缺点࿱…...

voc数据集格式与yolo数据集格式的区别及相互转化
Pascal VOC数据集是目标检测领域最常用的标准数据集之一,几乎所有检测方向的论文都会给出其在VOC数据集上训练并评测的效果。VOC数据集包含的信息非常全,它不仅被拿来做目标检测,也可以拿来做分割等任务,因此除了目标检测所需的文…...

超详细!Android Termux上如何安装MySQL,内网穿透实现公网远程访问
文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备,尽管最初并非设计为服务器,但是随着技术的进步我们可以将Android配置为生产力工具,变成一个随身…...
TSNE降维学习
在学习使用Cora数据集时,输入的初始为[2708, 1433], 输入一共有2708个点,每个节点有1433个特征。测试集的大小为[1000, 1433]最后的输出为[1000, 7],表示每个点的类别。 我们要的就是查看这个[1000, 7]的预测结果。想要将他展示在一个平面上是…...

基于Python+Selenium的web自动化测试框架详解
简介 随着Web应用程序的广泛应用和不断发展,Web自动化测试已经成为软件质量保证中的一个重要环节。而PythonSelenium作为一组强大的工具和框架,已经成为Web自动化测试领域中的热门技术之一。PythonSelenium可以帮助我们快速、准确地模拟用户行为和操作&…...

C (1094) : DS双向链表—前驱后继
Description 在双向链表中,A有一个指针指向了后继节点B,同时,B又有一个指向前驱节点A的指针。这样不仅能从链表头节点的位置遍历整个链表所有节点,也能从链表尾节点开始遍历所有节点。 对于给定的一列数据,按照给定的…...

mp4视频太大怎么压缩变小?
mp4视频太大怎么压缩变小?确实,很多培训和教学都转向了线上模式,这使得我们需要下载或分享大量的在线教学视频。然而,由于MP4视频文件通常较大,可能会遇到无法打开或发送的问题。为了解决这个问题,我们可以…...
利用easy excel 实现文件导出
一.创建实体类 package com.siact.product.jwp.module.report.dto;import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.write.style.ColumnWidth; import com.alibaba.excel.annotation.write.style.ContentRowHeight; import com.alib…...

LongLoRA:超长上下文,大语言模型高效微调方法
麻省理工学院和香港中文大学联合发布了LongLoRA,这是一种全新的微调方法,可以增强大语言模型的上下文能力,而无需消耗大量算力资源。 通常,想增加大语言模型的上下文处理能力,需要更多的算力支持。例如,将…...

【漏洞复现】某 NVR 视频存储管理设备远程命令执行
漏洞描述 NUUO NVR是中国台湾NUUO公司旗下的一款网络视频记录器,该设备存在远程命令执行漏洞,攻击者可利用该漏洞执行任意命令,进而获取服务器的权限。 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律&am…...
若依前端-应用路径发布和使用
官网的路径:前端手册 | RuoYi 应用路径 有些特殊情况需要部署到子路径下,例如:https://www.ruoyi.vip/admin,可以按照下面流程修改。 1、修改vue.config.js中的publicPath属性 publicPath: process.env.NODE_ENV "produ…...

Mojo 正式发布,Rust 能否与之匹敌?
9 月 7 日,Modular 公司宣布正式发布 Mojo:Mojo 现在已经开放本地下载——初步登陆 Linux 系统,并将很快提供 Mac 与 Windows 版本。据介绍,Mojo 最初的目标是比 Python 快 35000 倍,近日该团队表示,Mojo 将…...
opencv实现抠图,图像拼接,图像融合
在OpenCV中,你可以使用图像拼接、抠图和将图像的一部分放在另一张图片的指定位置。以下是示例代码,演示如何执行这些操作: 图像拼接 要将两张图像拼接在一起,你可以使用 cv::hconcat(水平拼接)和 cv::vco…...

照片处理软件Lightroom Classic mac中文版功能介绍(Lrc2021)
Lightroom Classic 2022 mac是一款桌面编辑工具,lrc2021 mac包括提亮颜色、使灰暗的摄影更加生动、删除瑕疵、将弯曲的画面拉直等。您可以在电脑桌面上轻松整理所有照片。使用Lightroom Classic, 轻松整理编辑照片,为您的作品锦上添花。 Ligh…...

asp.net高校留学生信息管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio
一、源码特点 asp.net 高校留学生信息管理系统 是一套完善的web设计管理系统,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为vs2010,数据库为sqlserver2008,使 用c#语言开发 asp.net留学生信息管理系…...

C# - Opencv应用(1) 之VS下环境配置详解
C# - Opencv应用(1) 之VS下环境配置详解 有时候,单纯c#做前端时会联合C实现的dll来落地某些功能由于有时候会用C - Opencv实现算法后封装成dll,但是有时候会感觉麻烦,不如直接通过C#直接调用Opencv在此慢慢总结下C# -…...

rsync 远程同步实现快速、安全、高效的异地备份
目录 1 rsync 远程同步 1.1 rsync是什么? 1.2 rsync同步方式 1.3 rsync的特性 1.4 rsync的应用场景 1.5 rsync与cp、scp对比 1.6 rsync同步源 2 配置rsync源服务器 2.1 建立/etc/rsyncd.conf 配置文件 3 发起端 4 发起端配置 rsyncinotify 4.1 修改rsync…...

医学访问学者面试技巧
医学访问学者面试是一个非常重要的环节,它决定了你是否能够获得这个宝贵的机会去国外的大学或研究机构学习和研究。在这篇文章中,知识人网小编将分享一些关于医学访问学者面试的技巧,帮助你在面试中表现出色。 1. 准备充分 在参加医学访问学…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
FastAPI 教程:从入门到实践
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于构建 API,支持 Python 3.6。它基于标准 Python 类型提示,易于学习且功能强大。以下是一个完整的 FastAPI 入门教程,涵盖从环境搭建到创建并运行一个简单的…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
Java - Mysql数据类型对应
Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3
一,概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本:2014.07; Kernel版本:Linux-3.10; 二,Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01),并让boo…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

uniapp手机号一键登录保姆级教程(包含前端和后端)
目录 前置条件创建uniapp项目并关联uniClound云空间开启一键登录模块并开通一键登录服务编写云函数并上传部署获取手机号流程(第一种) 前端直接调用云函数获取手机号(第三种)后台调用云函数获取手机号 错误码常见问题 前置条件 手机安装有sim卡手机开启…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

水泥厂自动化升级利器:Devicenet转Modbus rtu协议转换网关
在水泥厂的生产流程中,工业自动化网关起着至关重要的作用,尤其是JH-DVN-RTU疆鸿智能Devicenet转Modbus rtu协议转换网关,为水泥厂实现高效生产与精准控制提供了有力支持。 水泥厂设备众多,其中不少设备采用Devicenet协议。Devicen…...