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

【iOS】计算器仿写

文章目录

  • 前言
  • 一、构建View界面
  • 二、Model中进行数据处理
  • 三、Controller层实现View与Model交互
  • 总结


前言

在前两周组内进行了计算器的仿写,计算器仿写主要用到了MVC框架的思想以及数据结构中用栈进行四则运算的思想,还有就是对OC中的字符串进行各种判错操作处理
接下来笔者将简单介绍一下利用OC实现计算机的基本思路

一、构建View界面

我们先来看一下计算机界面实现的具体效果:
在这里插入图片描述

在实现View界面时,笔者使用了Masonry进行布局,因为计算器界面按钮的排序是有规律的,因此使用Masonry能让我们的布局更加轻松。

下面给出创建部分按钮的示例:

    for (int i = 0; i < 4; i++) {//先循环创建16个按钮for (int j = 0; j < 4; j++) {_baseButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];_baseButton.layer.cornerRadius = SIZE / 2;//圆形按钮_baseButton.titleLabel.font = [UIFont systemFontOfSize:42];_baseButton.tag = j + 4 + i * 4;[self addSubview:_baseButton];[_baseButton mas_makeConstraints:^(MASConstraintMaker *make) {//从底部开始约束make.bottom.equalTo(self).offset(-(75 + (SIZE + 17) * (i + 1)));make.left.equalTo(self).offset(5 + [UIScreen mainScreen].bounds.size.width / 4 * j);make.width.equalTo(@SIZE);make.height.equalTo(@SIZE);}];if (j < 3) {//竖列if (i < 3) {//横行[_baseButton setBackgroundColor:[UIColor colorWithWhite:0.15 alpha:1]];[_baseButton setTitle:[NSString stringWithFormat:@"%d", j + 1 + i * 3]  forState:UIControlStateNormal];[_baseButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];} else {[_baseButton setBackgroundColor:[UIColor lightGrayColor]];[_baseButton setTitle:grayArray[j] forState:UIControlStateNormal];[_baseButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];}} else {//橘色符号[_baseButton setBackgroundColor:[UIColor colorWithRed:0.9 green:0.58 blue:0 alpha:1]];[_baseButton setTitle:orangeArray[i] forState:UIControlStateNormal];[_baseButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];}if (j == 0 && i == 3) {_baseButton.titleLabel.font = [UIFont systemFontOfSize:34];}}}

二、Model中进行数据处理

根据MVC框架的思想,我们的Model层是负责提供数据接口给controller使用,因此我们需要将处理好的数据返回给controller层。我们在此对其进行四则运算的逻辑操作。

这里简单介绍一下我们的四则运算,本质上是使用运算符号优先级来判断是否入栈出栈,笔者后面会单独写博客讲述。这里有人会先将中缀表达式转为后缀表达式再去计算结果,笔者这里直接使用中缀表达式计算结果

代码:

- (instancetype)init {self = [super init];if (self) {self.stackArray = [NSMutableArray arrayWithCapacity:Maxsize];self.stackSize = Maxsize;}return self;
}char Precede(char theta1, char theta2) {int i, j;char pre[7][7] = {{'>', '>', '<', '<', '<', '>', '>'},{'>', '>', '<', '<', '<', '>', '>'},{'>', '>', '>', '>', '<', '>', '>'},{'>', '>', '>', '>', '<', '>', '>'},{'<', '<', '<', '<', '<', '=', '0'},{'>', '>', '>', '>', '0', '>', '>'},{'<', '<', '<', '<', '<', '0', '='}};switch (theta1) {case '+': i = 0; break;case '-': i = 1; break;case '*': i = 2; break;case '/': i = 3; break;case '(': i = 4; break;case ')': i = 5; break;case '=': i = 6; break;}switch (theta2) {case '+': j = 0; break;case '-': j = 1; break;case '*': j = 2; break;case '/': j = 3; break;case '(': j = 4; break;case ')': j = 5; break;case '=': j = 6; break;}return pre[i][j];
}double Operate(double a, char theta, double b) {switch (theta) {case '+': return a + b;case '-': return a - b;case '*': return a * b;case '/':if (b != 0) {return a / b;} else {NSLog(@"Divisor can not be zero!");exit(0);}}return 0;
}int In(char c) {switch (c) {case '+':case '-':case '*':case '/':case '(':case ')':case '=':return 1;default:return 0;}
}- (NSString *) evaluateExpression:(NSString *)exp {_OPND = [[Model alloc] init];//数字栈_OPTR = [[Model alloc] init];//符号栈double a, b, theta, X1, X2;char ch;NSInteger i = 0;NSInteger fuhaoFlag = 0;NSInteger kuohaoFlag = 0;NSInteger fuhaoBegin = 0;[_OPTR push:'='];ch = [exp characterAtIndex:i++];if (ch == '-') {ch = [exp characterAtIndex:i++];fuhaoFlag = 1;}while (ch != '=' || [_OPTR getTop] != '=') {if (In(ch)) {if (ch == '(') {kuohaoFlag = 1;}if (ch == '-' && [exp characterAtIndex:i - 2] == '(') {fuhaoFlag = 1;kuohaoFlag = 0;ch = [exp characterAtIndex:i++];continue;}switch (Precede([_OPTR getTop], ch)) {case '<':[_OPTR push:ch];ch = [exp characterAtIndex:i++];break;case '>':[_OPTR pop:&theta];[_OPND pop:&b];[_OPND pop:&a];if (theta == '/' && b == 0) {return @"error";}[_OPND push:Operate(a,theta,b)];break;case '=':[_OPTR pop:&theta];ch = [exp characterAtIndex:i++];break;}} else if (isdigit(ch)) {X1 = ch - '0';[_OPND push:X1];X2 = X1;ch = [exp characterAtIndex:i++];while (isdigit(ch)) {X1 = ch - '0';X2 = 10 * X2 + X1;ch = [exp characterAtIndex:i++];}if (ch == '.') {ch = [exp characterAtIndex:i++];double decimal = 0.0;double j = 1;while (isdigit(ch)) {double f = (double)(ch - '0');decimal = f / (pow(10, j));j++;ch = [exp characterAtIndex:i++];X2 += decimal;}}if (fuhaoFlag == 0 && fuhaoBegin == 0) {double tmpX1;[_OPND pop:&tmpX1];[_OPND push:X2];} else {double tmpX1;[_OPND pop:&tmpX1];[_OPND push:-X2];fuhaoFlag = 0;fuhaoFlag = 0;}} else {return @"error";}}double result = [_OPND getTop];NSString *resultString = [NSString stringWithFormat:@"%f", result];resultString = [self removeFloatAllZeroByString:resultString];return resultString;
}

在OC中我们初始化两个栈,一个存储数字,一个存储符号,然后不断将符号与数字入栈出栈,直至碰到“=”。


一些判错操作:

我们也需要对我们的表达式进行一些判错处理,例如运算符相连或事括号数量的不匹配等问题,演示结果如下:
在这里插入图片描述
或是小数点不匹配与结果末尾有多余0的情况:
在这里插入图片描述

这些判错操作的部分是计算器最复杂的部分,需要多多琢磨。


三、Controller层实现View与Model交互

在MVC中我们的Controller的作用是实现View与Model交互,因此我们需要在Controller层中实现我们界面按钮的点击事件并将其转换为字符串同时将生成的字符串传入Model层进行数据处理,如果没有判错则将其结果输出

- (void)viewDidLoad {[super viewDidLoad];_calculatorView= [[View alloc] init];_calculatorView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);[self.view addSubview:_calculatorView];//为视图中的按钮在controller中添加事件for (UIView *subview in self.calculatorView.subviews) {if ([subview isKindOfClass:[UIButton class]]) {UIButton *button = (UIButton *)subview;[button addTarget:self action:@selector(pressButton:) forControlEvents:UIControlEventTouchUpInside];}}_calculatorModel= [[Model alloc] init];}

这里需要注意,因为笔者理解的MVC中View只负责界面的绘制,并不用处理界面的逻辑,例如界面中控件的点击事件,因此这里需要再controller中使用如下代码对其进行点击事件的添加:

    for (UIView *subview in self.calculatorView.subviews) {if ([subview isKindOfClass:[UIButton class]]) {UIButton *button = (UIButton *)subview;[button addTarget:self action:@selector(pressButton:) forControlEvents:UIControlEventTouchUpInside];}}

接下来给出一些对按钮中的点击事件的代码:

//左右括号if (btn.tag == 17) {if (![_calculatorView.printfLabel.text isEqual: @"0"]) {_calculatorView.printfLabel.text = [_calculatorView.printfLabel.text stringByAppendingString:@"("];} else {_calculatorView.printfLabel.text = @"(";}    }if (btn.tag == 18) {if (![_calculatorView.printfLabel.text isEqual: @"0"]) {_calculatorView.printfLabel.text = [_calculatorView.printfLabel.text stringByAppendingString:@")"];} else {_calculatorView.printfLabel.text = @")";}    }if (btn.tag == 3) {if ([_calculatorModel error:_calculatorView.printfLabel.text] == 1 ) {_calculatorView.printfLabel.text = @"error";} else {_calculatorView.printfLabel.text = [_calculatorView.printfLabel.text stringByAppendingString:@"="];NSString *result = [_calculatorModel evaluateExpression:_calculatorView.printfLabel.text];NSLog(@"%@", result);_calculatorView.printfLabel.text = result;}}

这里需要注意我们在VIew中创建按钮时已经对其tag进行赋值,因此可在controller文件中直接使用


总结

计算器的仿写其实不难,最难的部分是对表达式的处理,有许多细节需要注意

相关文章:

【iOS】计算器仿写

文章目录 前言一、构建View界面二、Model中进行数据处理三、Controller层实现View与Model交互总结 前言 在前两周组内进行了计算器的仿写&#xff0c;计算器仿写主要用到了MVC框架的思想以及数据结构中用栈进行四则运算的思想&#xff0c;还有就是对OC中的字符串进行各种判错操…...

华为认证 | 华为HCIE认证该怎样备考?

华为HCIE认证是华为认证的最高级别&#xff0c;拥有了华为HCIE认证就代表拥有了华为官方认可的专家级技术水平。 因此HCIE认证的考试难度是非常高的&#xff0c;备考华为认证HCIE需要一定的准备和规划。 整理了一些简单易懂的指南&#xff0c;希望对各位备考的小伙伴一些帮助…...

10月份stable diffusion animatediff等插件使用指南,又来更新了

插件一直会更新&#xff0c;包含了基本市面上流行的90%插件&#xff0c;好用的插件更是不会错过&#xff0c;往期插件请看往期文章&#xff0c;如果你没有时间一直关注sd更新的进展&#xff0c;请关注我&#xff0c;一个月用几个小时看一下我的文章&#xff0c;最短时间跟进sd。…...

抓包工具charles修改请求和返回数据

数据篡改的主要使用场景&#xff1a; &#xff08;1&#xff09;mock场景&#xff0c;mock入参和返回值参数&#xff0c;实现mock测试 &#xff08;2&#xff09;安全测试&#xff0c;对于支付金额等比较重要的字段&#xff0c;可以修改请求参数来进行安全测试 1.首先选择要…...

matlab中绘制 维诺图(Voronoi Diagram)

1.专业术语&#xff08;相关概念&#xff09;&#xff1a; 基点Site&#xff1a;具有一些几何意义的点 细胞Cell&#xff1a;这个Cell中的任何一个点到Cell中基点中的距离都是最近的&#xff0c;离其他Site比离内部Site的距离都要远。 Cell的划分&#xff1a;基点Site与其它的…...

Mybatis TypeHandler 介绍及使用

Mybatis TypeHandler类型转换器是负责Java类和jdbc类型之间的转换 主要涉及到下面这几个类&#xff1a; TypeHandler 类型转换器的顶层接口BaseTypeHandler 抽象类继承自TypeHandler&#xff0c;Mybatis中所有的类型转换器实现均继承他。TypeHandlerRegistry 类型转换器注册器…...

Linux SVN 命令详解

1、将文件 checkout 到本地目录 svn checkout path&#xff08;path是服务器上的目录&#xff09; 例如&#xff1a;svn checkout svn://192.168.1.1/pro/domain 简写&#xff1a;svn co 2、往版本库中添加新的文件 svn add file 例如&#xff1a;svn add test.php(添加test.…...

Maven依赖引入的优先机制

xxxx待持续更新...

全开源无加密跨境电商购物网站系统源码(无货源模式+多语言+多货币)

在全球化的时代背景下&#xff0c;跨境电商成为了越来越受欢迎的消费方式&#xff0c;而建立一个源码无加密多语言跨境购物网站系统是一个具有挑战性的任务&#xff0c;但完全可行。以下是这个过程的一些主要步骤&#xff1a; 1. 确定需求和功能规划&#xff1a;先确定网站需要…...

Python常用视频编辑操作——读取与保存视频、更改帧数、拼接视频、视频语音合并、视频与图像互转等

1.更改视频帧数 降低视频帧数&#xff0c;简单的操作只能降低视频帧数&#xff0c;如果要增加视频帧数&#xff0c;那就要使用深度学习进行插帧处理&#xff1a; import cv2 from moviepy.editor import * def change_fps(inpt_path,output_path,fps):# 加载视频video Video…...

从javascript到vue再到react的演变

当提到前端开发中的框架时&#xff0c;JavaScript、Vue.js和React.js是三个最常见的名词。它们代表了Web开发中不同的技术选择和演变过程。本文将探讨JavaScript从原生到Vue.js再到React.js的演变&#xff0c;以及每个阶段的特点和优势。 JavaScript: 动态语言的基础 JavaScr…...

50个渗透(黑客)常用名词及解释

目录 前言一、渗透测试1. 渗透测试&#xff1a;2. 黑盒测试&#xff1a;3. 白盒测试&#xff1a;4. 社会工程学&#xff1a;5. 缓冲区溢出&#xff1a;6. 拒绝服务攻击&#xff1a;7. DDoS攻击&#xff1a;8. XSS攻击&#xff1a;9. CSRF攻击&#xff1a;10. SQL注入&#xff1…...

开源游戏引擎和模拟器的项目合集 | 开源专题 No.38

yuzu-emu/yuzu Stars: 26.2k License: GPL-3.0 yuzu是一款全球最受欢迎的开源Nintendo Switch模拟器&#xff0c;由Citra创建者编写。它采用C语言编写&#xff0c;并具有可移植性&#xff0c;在Windows和Linux上进行积极维护。该模拟器能够全速运行大多数商业游戏&#xff0c…...

ELK + Filebeat 分布式日志管理平台部署

ELK Filebeat 分布式日志管理平台部署 1、前言1.1日志分析的作用1.2需要收集的日志1.3完整日志系统的基本特征 2、ELK概述2.1ELK简介2.2为什么要用ELK?2.3ELK的组件 3、ELK组件详解3.1Logstash3.1.1简介3.1.2Logstash命令常用选项3.1.3Logstash 的输入和输出流3.1.4Logstash配…...

Stable Diffusion原理

一、Diffusion扩散理论 1.1、 Diffusion Model&#xff08;扩散模型&#xff09; Diffusion扩散模型分为两个阶段&#xff1a;前向过程 反向过程 前向过程&#xff1a;不断往输入图片中添加高斯噪声来破坏图像反向过程&#xff1a;使用一系列马尔可夫链逐步将噪声还原为原始…...

2022年亚太杯APMCM数学建模大赛A题结晶器熔剂熔融结晶过程序列图像特征提取及建模分析求解全过程文档及程序

2022年亚太杯APMCM数学建模大赛 A题 结晶器熔剂熔融结晶过程序列图像特征提取及建模分析 原题再现&#xff1a; 连铸过程中的保护渣使钢水弯液面隔热&#xff0c;防止钢水在连铸过程中再次氧化&#xff0c;控制传热&#xff0c;为铸坯提供润滑&#xff0c;并吸收非金属夹杂物…...

金融网站如何做好安全防护措施?

联网的发展为当代很多行业的发展提供了一个更为广阔的平台&#xff0c;而对于中国的金融业来说&#xff0c;互联网金融这一新兴理念已经为 人们所接受&#xff0c;且发展迅速。我们也都知道金融行业对互联网技术是非常严格的&#xff0c;这对互联网的稳定性和可靠性提出了较高的…...

2023年中国恋爱社区未来发展趋势分析:多元化盈利模式实现可持续发展[图]

恋爱社区指满足情侣之间互动、记录及娱乐需求&#xff0c;以维护情侣恋爱关系的虚拟社区。恋爱社区行业主要以线上APP的虚拟形式为用户提供相关服务&#xff0c;其业务包括情侣记录、情侣互动、情侣娱乐、公共社区、线上购物、增值服务。 恋爱社区主要业务 资料来源&#xff1…...

Elasticsearch:生成式人工智能带来的社会转变

作者&#xff1a;JEFF VESTAL 了解 Elastic 如何走在大型语言模型革命的最前沿 – 通过提供实时信息并将 LLM 集成到数据分析的搜索、可观察性和安全系统中&#xff0c;帮助用户将 LLM 提升到新的高度。 iPhone 社会转变&#xff1a;新时代的黎明 曾几何时&#xff0c;不久前…...

服务器数据恢复-RAID5中磁盘被踢导致阵列崩溃的服务器数据恢复案例

服务器数据恢复环境&#xff1a; 一台3U的某品牌机架式服务器&#xff0c;Windows server操作系统&#xff0c;100块SAS硬盘组建RAID5阵列。 服务器故障&#xff1a; 服务器有一块硬盘盘的指示灯亮黄灯&#xff0c;这块盘被raid卡踢出后&#xff0c;raid阵列崩溃。 服务器数据…...

从ET1100迁移到AX58100:我的EtherCAT从站代码需要重写多少?

从ET1100迁移到AX58100&#xff1a;EtherCAT从站代码重构实战指南 当你的产品线需要从百兆升级到千兆EtherCAT网络&#xff0c;或者要支持时间敏感网络(TSN)功能时&#xff0c;从经典的ET1100切换到AX58100几乎是必然选择。但作为经历过完整迁移周期的开发者&#xff0c;我必须…...

Ostrakon-VL像素终端效果展示:8-bit风格UI下高精度OCR识别动图

Ostrakon-VL像素终端效果展示&#xff1a;8-bit风格UI下高精度OCR识别动图 1. 像素特工终端概览 在零售与餐饮行业的数字化转型浪潮中&#xff0c;我们开发了这款基于Ostrakon-VL-8B多模态大模型的Web交互终端。与传统工业级UI不同&#xff0c;这款终端采用了充满活力的8-bit…...

Pixel Epic · Wisdom Terminal 部署与压测:使用.accelerate库优化推理性能

Pixel Epic Wisdom Terminal 部署与压测&#xff1a;使用.accelerate库优化推理性能 1. 引言 如果你正在使用Pixel Epic Wisdom Terminal进行AI推理任务&#xff0c;可能会遇到性能瓶颈问题。今天我们就来聊聊如何用Hugging Face的.accelerate库来提升推理速度&#xff0c;…...

完整贡献指南:如何为endoflife.date添加新的产品支持信息

完整贡献指南&#xff1a;如何为endoflife.date添加新的产品支持信息 【免费下载链接】endoflife.date Informative site with EoL dates of everything 项目地址: https://gitcode.com/gh_mirrors/en/endoflife.date 你是否想为开源项目贡献自己的力量&#xff0c;但不…...

别再手动写Excel了!用Coze+GPT-4o,5分钟把Word需求文档变成测试用例表格

从Word到Excel&#xff1a;零代码打造智能测试用例生成流水线 每次产品需求文档更新后&#xff0c;测试团队最头疼的莫过于手动编写成百上千条测试用例。传统方式下&#xff0c;测试工程师需要反复阅读PRD文档&#xff0c;逐条提取功能点&#xff0c;再按照固定模板填充到Excel…...

【vue】二、vue2仿去哪儿网app——首页开发实战:从零搭建到性能优化

1. 项目初始化与页面结构设计 开始一个Vue2仿去哪儿网App首页项目&#xff0c;首先要搭建基础框架。我习惯用vue-cli脚手架快速初始化项目&#xff0c;这个工具能帮我们处理好webpack配置、基础目录结构等繁琐工作。执行vue init webpack qunar-app命令后&#xff0c;会生成标…...

Kandinsky-5.0-I2V-Lite-5s企业应用:HR招聘海报→候选人互动式动态介绍视频生成

Kandinsky-5.0-I2V-Lite-5s企业应用&#xff1a;HR招聘海报→候选人互动式动态介绍视频生成 1. 引言&#xff1a;让招聘海报"活"起来 想象一下这样的场景&#xff1a;你的HR团队精心设计了一份招聘海报&#xff0c;但投递量却不如预期。问题可能出在传统静态海报难…...

SM4算法在嵌入式平台的轻量化移植与优化实践

1. SM4算法与嵌入式平台适配挑战 SM4作为我国自主设计的商用分组密码标准&#xff0c;在物联网设备安全领域应用广泛。但直接将OpenSSL中的SM4实现移植到STM32等嵌入式平台时&#xff0c;开发者常会遇到三大难题&#xff1a; 代码体积膨胀&#xff1a;OpenSSL的SM4实现依赖大量…...

信创协同办公价格与成本:这样选,性价比直接拉满!

“一套信创协同办公到底多少钱&#xff1f;”“是按人头收费&#xff0c;还是按项目打包算&#xff1f;”“前期买着便宜&#xff0c;后期维护会不会无底洞&#xff1f;”不管是政企单位采购&#xff0c;还是企业选型&#xff0c;这三个问题几乎是所有人的核心顾虑。毕竟信创办…...

Qwen3-ASR-1.7B效果展示:实测多语言语音识别,准确率超高

Qwen3-ASR-1.7B效果展示&#xff1a;实测多语言语音识别&#xff0c;准确率超高 1. 开篇&#xff1a;一款让人惊艳的语音识别模型 最近测试了Qwen3-ASR-1.7B这款语音识别模型&#xff0c;结果让我大吃一惊。作为一款中等规模的模型&#xff0c;它在多语言识别上的表现完全不输…...