IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> [iOS]计算器问题总结 -> 正文阅读

[移动开发][iOS]计算器问题总结

用到的知识点:

  1. Masonry布局[iOS]-Masonry的使用
  2. MVC设计模式[iOS]- MVC模式基础
  3. 栈的思想实现四则运算C语言-栈的四则运算(带小数点和括号)

整体思路:

UI界面的创建:

  1. 前四行都是四个小按钮,使用四个for循环创建,每次建立一行,最后一行的三个按钮单独建立
  2. 每个按钮的位置使用Masonry约束,以保证兼容多个机型

代码如下:

//下面只给出第一行的按钮和0按钮单个按钮的建立代码
//第一行的四个按钮
    for (int i = 1; i <= 4; ++i) {
        NSString *string = [NSString stringWithFormat:@"1%d.jpg", i];
        
        _firstGroup = [UIButton buttonWithType:UIButtonTypeCustom];
        [_firstGroup setImage:[UIImage imageNamed:string] forState:UIControlStateNormal];
        [_firstGroup addTarget:self action:@selector(pressButtonFirst:)  forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:_firstGroup];
        
        [_firstGroup mas_makeConstraints:^(MASConstraintMaker *make) {
            make.top.mas_offset(self.frame.size.height * 0.380);
            make.left.mas_equalTo(self.frame.size.width * (0.035 + 0.241 * (i - 1)));
            make.size.mas_equalTo(CGSizeMake(self.frame.size.width * 0.206, self.frame.size.height * 0.095));
        }];
        
        _firstGroup.tag = 10 + i;
    }

//0按钮
    _zeroButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [_zeroButton setImage:[UIImage imageNamed:@"0.jpg"] forState:UIControlStateNormal];
    
    [_zeroButton addTarget:self action:@selector(pressButtonZero:) forControlEvents:UIControlEventTouchUpInside];
    
    [self addSubview:_zeroButton];
    
    _zeroButton.tag = 51;
    
    [_zeroButton mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_offset(self.frame.size.height * 0.824);
        make.left.mas_equalTo(self.frame.size.width * 0.035);
        make.size.mas_equalTo(CGSizeMake(self.frame.size.width * 0.447, self.frame.size.height * 0.095));
    }];

其中Masonry约束的写法以约束top、left、size三个条件为规范
且每个按钮的事件函数同样写在V中,每次按下按钮时触发事件函数,利用协议传值将相应按钮的tag值传至C中分情况进行操作
四则运算思路:

  1. 每按下一个按钮就将按钮的相应元素添加至可变字符串中,待按下等号按钮时调用M中的运算函数进行计算
  2. 首先进行判错处理,如果通过判错处理则进行实际运算过程
  3. 实际的运算过程是遍历此可变字符串,对每个字符分情况处理

处理逻辑如下:
每次对一个元素进行判断和操作,一共两个栈(一个数字栈,一个符号栈)
(1)如果是数字就入数字栈,然后继续操作下一个字符串中的元素
下面是对括号的一些操作:
如果是左括号,就进符号栈,然后继续操作下一个字符串中的元素
如果是右括号,就让符号栈栈顶元素出栈,让数字栈栈顶和次栈顶的两个元素出栈进行运算,并将运算结果入数字栈,一直循环此操作直至遇见符号栈栈顶为左括号为止,遇见左括号后将其出符号栈,并继续操作下一个字符串中的元素
(2)如果是符号:
如果符号栈为空,就直接入符号栈
如果符号栈栈顶的符号的优先级大于当前正在操作的字符串中的元素,就将符号栈栈顶符号出栈,将数字栈栈顶和次栈顶的两个元素出栈,进行运算后将结果入数字栈
如果符号栈栈顶的符号的优先级小于当前正在操作的字符串中的元素,就入符号栈
(3)当字符串中的元素全部遍历完后如果符号栈仍然有元素,就继续从符号栈栈顶出一个元素,从数字栈栈顶出两个元素,计算后将结果入数字栈,循环此操作直至符号栈为空为止

具体代码详见上方超链接中的四则运算博客,实际的计算器编写中可根据需求添加判错
注意的点:
OC的栈我们用可变数组来代替,具体代码如下:

//进数字栈
- (void) pushNum: (double) num {
    if (_numArray.count == 50) {
        NSLog(@"进栈失败");
        return;
    }
    [_numArray addObject:[NSString stringWithFormat:@"%f",num]];
    return;
}

//进符号栈
- (void) pushChar: (char) str {
    if (_strArray.count == 50) {
        NSLog(@"进栈失败");
        return;
    }
    [_strArray addObject:[NSString stringWithFormat:@"%c", str]];
//    NSLog(@"$$$$$%c", str);
    return;
}

//出数字栈
- (double) popNum {
    double t;
    t = [self backNum:_numArray[_numArray.count - 1]];
    [_numArray removeLastObject];
    return t;
}

//出符号栈
- (char) popChar {
    char ch;
    ch = [_strArray[_strArray.count - 1] characterAtIndex:0];
    [_strArray removeLastObject];
    //NSLog(@"$$$$$%c", ch);
    return ch;
}

//返回数字栈栈顶
- (double) topNum {
    return [self backNum:_numArray[_numArray.count - 1]];
}

//返回符号栈栈顶
- (char) topChar {
    return [_strArray[_strArray.count - 1] characterAtIndex:0];
}

可以看到我们入数字栈的时候实际上入的是字符串,所以需要编写一个函数出数字栈的时候将字符串转为实际的数字,该函数如下:

//转换数组中的字符串为数字
- (double) backNum:(NSString *) string {
	//这里的flag用来判断需要出栈的数字是否为负数,若flag为0则为正数,若flag为1则为负数
    int flag = 0;
    double res;
    if ([string characterAtIndex:0] == '-') {
        flag = 1;
    }
    if (flag == 0) {
        int i = 0;
        double x = 0;
        while ([string characterAtIndex:i] >= '0' && [string characterAtIndex:i] <= '9' && i < string.length) {
            x *= 10;
            x += (double)[string characterAtIndex:i] - '0';
            ++i;
        }
        
        //计算是小数的情况
        if (i < string.length && [string characterAtIndex:i] == '.') {
            double d = 0.1;
            ++i;
            while (i < string.length) {
                x += ((double)[string characterAtIndex:i] - '0') * d;
                d *= 0.1;
                ++i;
            }
        }
        res = x;
    } else {
        int i = 1;
        double x = 0;
        while ([string characterAtIndex:i] >= '0' && [string characterAtIndex:i] <= '9' && i < string.length) {
            x *= 10;
            x += (double)[string characterAtIndex:i] - '0';
            ++i;
        }
        
        //计算是小数的情况
        if (i < string.length && [string characterAtIndex:i] == '.') {
            double d = 0.1;
            ++i;
            while (i < string.length) {
                x += ((double)[string characterAtIndex:i] - '0') * d;
                d *= 0.1;
                ++i;
            }
        }
        res = x;
    }
    
    if (flag == 0) {
        return res;
    } else {
        return -res;
    }
}

比较符号优先级和计算结果的函数代码如下:

//比较符号优先级
- (NSInteger) compare:(char) str {
    if (str == '+' || str == '-') {
        return 1;
    } else if (str == '*' || str == '/') {
        return 2;
    } else {
        return 0;
    }
}

//计算函数
- (double) counter:(double) first :(double) second :(char) strSecond {
    double ans = 0.0;
    if (strSecond == '+') {
        ans = first + second;
    } else if (strSecond == '-') {
        ans = first - second;
    } else if (strSecond == '*') {
        ans = first * second;
    } else {
        ans = first / second;
    }
    return ans;
}

有了以上函数,我们就可以编写计算的主函数,在主函数中调用以上函数实现计算最终结果的功能了。主函数具体逻辑参考上方四则运算博客

一些细节问题:

我们定义了一个可变字符串,用于存最终的运算结果,最后将屏幕上UI Label的text设置为该可变字符串即可在屏幕上显示最终结果
计算等相关函数写在M中,在C中调用产生效果

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-10-09 16:23:57  更:2021-10-09 16:24:24 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:42:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码