记录一下最近写的一个计算器APP。
实现包含括号以及四则运算的简单计算器,利用MVC设计模式以及Masonry布局。 实现界面: 首先实现这个界面到了之前学过的Masonry第三方库,对按钮进行了屏幕比例的限制。
遇见的一些问题
在MVC设计模式中Button事件的处理
根据MVC的设计模式,Button事件应该加在C的代码中,这里一开始没有好的思路,后来问了下学长,学了一手。、 我们可以利用协议传值,在V的代码中添加事件,但事件函数是在C中实现的,每次点击Button时,C可以得到Button的tag值,以进行下一步处理。 部分代码:
#import <UIKit/UIKit.h>
@protocol viewDelegate <NSObject>
- (void) pressChange: (UIButton*) cButton;
@end
[_zeroButton addTarget:self action:@selector(return:) forControlEvents:UIControlEventTouchUpInside];
- (void) return: (UIButton*) cButton {
[_delegate pressChange:cButton];
}
// 在c中实现的pressChange:方法
int flag = 0;
int secondFlag = 0;
int thirdFlag = 0;
int zeroFlag = 0;
- (void) pressChange: (UIButton*) cButton {
if (cButton.tag == 101) {
[_changeArray removeAllObjects];
NSString *ansString = @"0";
_firstView.topLabel.text = ansString;
flag = 0;
secondFlag = 0;
thirdFlag = 0;
} else if (cButton.tag == 120) {
if (thirdFlag == 1) {
;
} else {
[_changeArray addObject:@"#"];
NSString *ansString = [_changeArray componentsJoinedByString:@""];
[_firstModel operation:ansString];
_firstView.topLabel.text = [_firstModel operation:ansString];;
[_changeArray removeAllObjects];
thirdFlag = 1;
}
} else if (cButton.tag == 119) {
if (flag == 0) {
flag = 1;
[_changeArray addObject:cButton.titleLabel.text];
NSString *ansString = [_changeArray componentsJoinedByString:@""];
_firstView.topLabel.text = ansString;
} else {
;
}
}
else {
if (cButton.tag == 104 || cButton.tag == 108 || cButton.tag == 112 || cButton.tag == 116 ) {
flag = 0;
if (secondFlag == 0) {
return;
} else {
secondFlag = 0;
}
} else if (cButton.tag != 102){
secondFlag = 1;
}
[_changeArray addObject:cButton.titleLabel.text];
NSString *ansString = [_changeArray componentsJoinedByString:@""];
_firstView.topLabel.text = ansString;
thirdFlag = 0;
}
}
一些判错处理和预处理
这里我参考手机计算器的一些限制非法输入。 1.当没有数字时无法输入符号。 2.不能连续输入两个符号 3.当已经又了一个小数点,但没有出现运算符的情况下,不能继续输入小数点。 4.左括号后不能立即添加符号 代码在上面的方法中
对于输入进来的数据处理
首先判断括号是否有效
当括号无效时,直接判断输入错误。 代码:
int compareReturn(char str1) {
if (str1 == '#') {
return 0;
} else if (str1 == '+' || str1 == '-') {
return 1;
} else if (str1 == '*' || str1 == '/') {
return 2;
} else if (str1 == '(' || str1 == ')') {
return 0;
}
else {
return -1;
}
}
int tureKH (const char* str) {
int top = 0;
for (int i = 0; i < strlen(str); i++) {
if (str[i] == '(') {
top++;
} else if (str[i] == ')') {
if (top == 0) {
return 0;
} else {
top--;
}
} else {
;
}
}
if (top == 0) {
return 1;
} else {
return 0;
}
}
中缀转后缀
这个我前面写过博客中缀表达式转后缀表达式。 只不过当时是用c语言实现的,这次是用OC实现的。 有些细微的区别,OC的数组并不能存储简单的数据类型,所以得将输入的数据转成一个个字符串对象再存入数组,由于输入的数据没有分隔符,所以如果直接将表达式转化为数组,那么会发现数组的第一个元素就是这个字符串整体对象,所以这里我先将字符串对象变为c风格的数组,然后再对其逐一处理进行转换。
- (BOOL) isSymbol:(NSString*) string {
if ([string isEqual:@"*"] || [string isEqual:@"+"] || [string isEqual:@"-"] || [string isEqual:@"/"] || [string isEqual:@"("] || [string isEqual:@")"] || [string isEqual:@"#"]) {
return YES;
} else {
return NO;
}
}
- (int) firstSymbol:(NSString*) string {
if ([string isEqual:@"-"] || [string isEqual:@"+"]) {
return 2;
} else if ([string isEqual:@"*"] || [string isEqual:@"/"]) {
return 3;
} else if ([string isEqual:@"#"]) {
return 1;
} else {
return 0;
}
}
- (NSMutableArray*)switchString :(const char *) outString {
int flag = 0;
self.ansArray = [[NSMutableArray alloc] init];
self.tempArray = [[NSMutableArray alloc] init];
NSMutableArray *textArray = [[NSMutableArray alloc] init];
for (int i = 0; i < strlen(outString); i++) {
NSString *str1 = [NSString stringWithFormat:@"%c", outString[i]];
[textArray addObject:str1];
}
NSMutableString* numberString = [[NSMutableString alloc] init];
for (int i = 0; i < textArray.count;) {
if ([self isSymbol:textArray[i]] == NO) {
[numberString appendString:textArray[i++]];
flag = 0;
} else {
if (flag == 0) {
NSMutableString* temp = [[NSMutableString alloc] init];
temp = [numberString copy];
[self.ansArray addObject:temp];
flag = 1;
[numberString deleteCharactersInRange:NSMakeRange(0, numberString.length)];
NSLog(@"%@", self.ansArray);
}
if ([textArray[i] isEqual:@"("]) {
[self.tempArray addObject:textArray[i++]];
} else if ([textArray[i] isEqual:@")"]) {
while (![self.tempArray[self.tempArray.count - 1] isEqual:@"("]) {
[self.ansArray addObject:self.tempArray[self.tempArray.count - 1]];
[self.tempArray removeLastObject];
}
[self.tempArray removeLastObject];
i++;
} else {
if (self.tempArray.count == 0) {
[self.tempArray addObject:textArray[i++]];
continue;
}
if (self.tempArray.count != 0 && [self firstSymbol:textArray[i]] > [self firstSymbol:self.tempArray[self.tempArray.count - 1]]) {
[self.tempArray addObject:textArray[i++]];
} else {
[self.ansArray addObject:self.tempArray[self.tempArray.count - 1]];
[self.tempArray removeLastObject];
}
}
}
}
NSLog(@"%@", self.ansArray);
return self.ansArray;
}
计算后缀表达式后有多余的0
在将字符串转为double计算后,再变为字符串,会出现多余0的问题,这里可以在最后再进行一次处理。
-(NSString*)removeZero:(NSString*)string {
NSString * testNumber = string;
NSString * ansNumber = [NSString stringWithFormat:@"%@",@(testNumber.doubleValue)];
return ansNumber;
}
做除法运算分母不能为0
设置一个比较奇怪的值,加判断返回输入有误
} else if ([symbol isEqual:@"/"]) {
if (y == 0) {
ans = -9999;
return ans;
}
ans = x / y;
}
完整代码地址
|