当前位置: 首页 > news >正文

【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框架&#xff0c;接着在各个模块中实现各自的任务。首先要创建好UI界面&#xff0c;接着根据UI界面的元素来与数据进行互动&#xff0c;其中创建UI界面需要用到Masonry布局。 二、实现方法 在calcu…...

公安机关警务vr综合实战模拟训练提高团队合作能力

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

MySQL-1(12000字详解)

一&#xff1a;数据库的引入 数据库在我们以后工作中是一个非常常用的知识&#xff0c;数据库用来存储数据&#xff0c;但是有些同学可能就会疑惑了&#xff0c;存储数据用文件就可以了&#xff0c;为什么还要弄个数据库呢&#xff1f; 文件保存数据有以下几个缺点&#xff1…...

voc数据集格式与yolo数据集格式的区别及相互转化

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

超详细!Android Termux上如何安装MySQL,内网穿透实现公网远程访问

文章目录 前言1.安装MariaDB2.安装cpolar内网穿透工具3. 创建安全隧道映射mysql4. 公网远程连接5. 固定远程连接地址 前言 Android作为移动设备&#xff0c;尽管最初并非设计为服务器&#xff0c;但是随着技术的进步我们可以将Android配置为生产力工具&#xff0c;变成一个随身…...

TSNE降维学习

在学习使用Cora数据集时&#xff0c;输入的初始为[2708, 1433], 输入一共有2708个点&#xff0c;每个节点有1433个特征。测试集的大小为[1000, 1433]最后的输出为[1000, 7]&#xff0c;表示每个点的类别。 我们要的就是查看这个[1000, 7]的预测结果。想要将他展示在一个平面上是…...

基于Python+Selenium的web自动化测试框架详解

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

C (1094) : DS双向链表—前驱后继

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

mp4视频太大怎么压缩变小?

mp4视频太大怎么压缩变小&#xff1f;确实&#xff0c;很多培训和教学都转向了线上模式&#xff0c;这使得我们需要下载或分享大量的在线教学视频。然而&#xff0c;由于MP4视频文件通常较大&#xff0c;可能会遇到无法打开或发送的问题。为了解决这个问题&#xff0c;我们可以…...

利用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&#xff0c;这是一种全新的微调方法&#xff0c;可以增强大语言模型的上下文能力&#xff0c;而无需消耗大量算力资源。 通常&#xff0c;想增加大语言模型的上下文处理能力&#xff0c;需要更多的算力支持。例如&#xff0c;将…...

【漏洞复现】某 NVR 视频存储管理设备远程命令执行

漏洞描述 NUUO NVR是中国台湾NUUO公司旗下的一款网络视频记录器&#xff0c;该设备存在远程命令执行漏洞&#xff0c;攻击者可利用该漏洞执行任意命令&#xff0c;进而获取服务器的权限。 免责声明 技术文章仅供参考&#xff0c;任何个人和组织使用网络应当遵守宪法法律&am…...

若依前端-应用路径发布和使用

官网的路径&#xff1a;前端手册 | RuoYi 应用路径 有些特殊情况需要部署到子路径下&#xff0c;例如&#xff1a;https://www.ruoyi.vip/admin&#xff0c;可以按照下面流程修改。 1、修改vue.config.js中的publicPath属性 publicPath: process.env.NODE_ENV "produ…...

Mojo 正式发布,Rust 能否与之匹敌?

9 月 7 日&#xff0c;Modular 公司宣布正式发布 Mojo&#xff1a;Mojo 现在已经开放本地下载——初步登陆 Linux 系统&#xff0c;并将很快提供 Mac 与 Windows 版本。据介绍&#xff0c;Mojo 最初的目标是比 Python 快 35000 倍&#xff0c;近日该团队表示&#xff0c;Mojo 将…...

opencv实现抠图,图像拼接,图像融合

在OpenCV中&#xff0c;你可以使用图像拼接、抠图和将图像的一部分放在另一张图片的指定位置。以下是示例代码&#xff0c;演示如何执行这些操作&#xff1a; 图像拼接 要将两张图像拼接在一起&#xff0c;你可以使用 cv::hconcat&#xff08;水平拼接&#xff09;和 cv::vco…...

照片处理软件Lightroom Classic mac中文版功能介绍(Lrc2021)

Lightroom Classic 2022 mac是一款桌面编辑工具&#xff0c;lrc2021 mac包括提亮颜色、使灰暗的摄影更加生动、删除瑕疵、将弯曲的画面拉直等。您可以在电脑桌面上轻松整理所有照片。使用Lightroom Classic&#xff0c; 轻松整理编辑照片&#xff0c;为您的作品锦上添花。 Ligh…...

asp.net高校留学生信息管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

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

C# - Opencv应用(1) 之VS下环境配置详解

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

rsync 远程同步实现快速、安全、高效的异地备份

目录 1 rsync 远程同步 1.1 rsync是什么&#xff1f; 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…...

医学访问学者面试技巧

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

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

STM32标准库-DMA直接存储器存取

文章目录 一、DMA1.1简介1.2存储器映像1.3DMA框图1.4DMA基本结构1.5DMA请求1.6数据宽度与对齐1.7数据转运DMA1.8ADC扫描模式DMA 二、数据转运DMA2.1接线图2.2代码2.3相关API 一、DMA 1.1简介 DMA&#xff08;Direct Memory Access&#xff09;直接存储器存取 DMA可以提供外设…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

laravel8+vue3.0+element-plus搭建方法

创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...

LRU 缓存机制详解与实现(Java版) + 力扣解决

&#x1f4cc; LRU 缓存机制详解与实现&#xff08;Java版&#xff09; 一、&#x1f4d6; 问题背景 在日常开发中&#xff0c;我们经常会使用 缓存&#xff08;Cache&#xff09; 来提升性能。但由于内存有限&#xff0c;缓存不可能无限增长&#xff0c;于是需要策略决定&am…...

Web后端基础(基础知识)

BS架构&#xff1a;Browser/Server&#xff0c;浏览器/服务器架构模式。客户端只需要浏览器&#xff0c;应用程序的逻辑和数据都存储在服务端。 优点&#xff1a;维护方便缺点&#xff1a;体验一般 CS架构&#xff1a;Client/Server&#xff0c;客户端/服务器架构模式。需要单独…...

wpf在image控件上快速显示内存图像

wpf在image控件上快速显示内存图像https://www.cnblogs.com/haodafeng/p/10431387.html 如果你在寻找能够快速在image控件刷新大图像&#xff08;比如分辨率3000*3000的图像&#xff09;的办法&#xff0c;尤其是想把内存中的裸数据&#xff08;只有图像的数据&#xff0c;不包…...

在 Spring Boot 项目里,MYSQL中json类型字段使用

前言&#xff1a; 因为程序特殊需求导致&#xff0c;需要mysql数据库存储json类型数据&#xff0c;因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...