一.用到的知识点:
1.MVC设计模式
2.Masonry布局
3.简单四则运算
4.中缀表达式转后缀表达式
二.基本思路:
首先创建一个字符串,对应计算器中的按钮点击,点击什么给该字符串添加什么字符,一切输入完毕之后按下=
就表示输入完毕,再进行下面操作,首先对最后得到的字符串进行判断,判断该字符串的格式是否正确,然后再对其进行中缀转后缀的操作,最后进行计算操作返回最后的得数,将它显示在计算器的现实屏上计算器就完成了。
写计算器没有什么太大的难度,最重要的是对前面所说的知识点的合理利用,让自己吸收之前自己学习到的知识,为之后打好基础。其中的难点就是对MVC模式中的各种数据传递和最终字符串错误的判断。
三. 基础代码:
1.判断字符串是否正确:
给一个数组每个单位分别存储数字和运算符,然后对这个数组进行判断。
- (void)checkErrors:(NSMutableArray *)floatArray {
//计算可变数组的长度
NSInteger length = 0;
while (![floatArray[length] isEqualToString:@"="]) {
length++;
}
//判断字符串的第一个字符是不是运算符
if (OCCompare(floatArray[0]) == 1 || OCCompare(floatArray[0]) == 2) {
self.search = 1;
return;
}
//除法运算的分母不为0
NSInteger i = 0;
while (i < length - 1) {
if ([floatArray[i] isEqualToString:@"/"] && [floatArray[i + 1] isEqualToString:@"0"]) {
self.search = 1;
return;
}
i++;
}
//括号匹配,判断字符串中的括号是否都对应
NSMutableArray *symbolArray = [[NSMutableArray alloc] init];
NSInteger symbolTop = -1;
for (int i = 0; i < length; i++) {
if ([floatArray[i] isEqualToString:@"("]) {
[symbolArray addObject:@"("];
symbolTop++;
} else if ([floatArray[i] isEqualToString:@")"] && symbolTop != -1) {
[symbolArray removeLastObject];
symbolTop--;
} else if ([floatArray[i] isEqualToString:@")"] && symbolTop == -1) {
self.search = 1;
} else if ([floatArray[i] isEqualToString:@"("] && [floatArray[i + 1] isEqualToString:@")"]) {
self.search = 1;
return;
}
}
if (symbolTop != -1) {
self.search = 1;
return;
}
//运算符,判断字符串中的是否存在相连的运算符
for (int i = 0; i < length - 1; i++) {
if (OCCompare(floatArray[i]) < 4 && OCCompare(floatArray[i]) && OCCompare(floatArray[i + 1]) < 4 && OCCompare(floatArray[i + 1])) {
self.search = 1;
return;
}
}
}
//OC的比较,给出一个比较的标准,便于比较运算级的优先顺序
NSInteger OCCompare(NSString *str) {
if ([str isEqualToString:@"+"] || [str isEqualToString:@"-"]) {
return 1;
} else if ([str isEqualToString:@"*"] || [str isEqualToString:@"/"]) {
return 2;
} else if ([str isEqualToString:@"("] || [str isEqualToString:@")"]) {
return 4;
} else if ([str isEqualToString:@"="]) {
return 3;
} else {
return 0;
}
}
2.中缀表达式转后缀表达式:
给一个待转换的字符串,最终返回一个转换完毕的字符串,详细的方法看我之前的博客。
//中缀转后缀
NSMutableArray* changeBehind(NSMutableArray *changeArray) {
//计算可变数组的长度
NSInteger length = 0;
while (![changeArray[length] isEqualToString:@"="]) {
length++;
}
//后缀
NSMutableArray *behindArray = [[NSMutableArray alloc] init];
//符号
NSMutableArray *symbolArray = [[NSMutableArray alloc] init];
NSInteger symbolTop = -1;
NSInteger i = 0;
while (i <= length) {
if ([changeArray[i] isEqualToString:@"("]) { //左括号就直接存入操作符栈
[symbolArray addObject:changeArray[i]];
i++;
symbolTop++;
} else if ([changeArray[i] isEqualToString:@")"]) { //右括号就将括号中的内容逐一弹出存入后缀栈
while (![symbolArray[symbolTop] isEqualToString:@"("]) {
[behindArray addObject:symbolArray[symbolTop--]];
[symbolArray removeLastObject];
}
[symbolArray removeLastObject];
symbolTop--;
i++;
} else if (!OCCompare(changeArray[i])) { //数字就直接存入后缀栈
if ([changeArray[i] isEqualToString:@"="]) {
break;
}
[behindArray addObject:changeArray[i]];
i++;
} else { //遇到操作符
if ([changeArray[i] isEqualToString:@"="]) {
while (symbolTop != -1) {
[behindArray addObject:symbolArray[symbolTop--]];
[symbolArray removeLastObject];
}
}
if (symbolTop == -1 || OCCompare(symbolArray[symbolTop]) < OCCompare(changeArray[i]) || OCCompare(symbolArray[symbolTop]) == 4) {
//操作符栈为空或者字符串中的操作符优先级大于操作符栈顶操作符的优先级就将该操作符压入操作符栈中
[symbolArray addObject:changeArray[i]];
i++;
symbolTop++;
} else {
[behindArray addObject:symbolArray[symbolTop]];
[symbolArray removeLastObject];
symbolTop--;
}
}
}
[behindArray addObject:@"="];
return behindArray;
}
3.最终将转化后的字符串根据简单的四字运算进行计算:
给一个待计算的数组,最终返回一个最终得数。
//计算结果
float endCalculation(NSMutableArray *newArray) {
//计算可变数组的长度
NSInteger length = 0;
while (![newArray[length] isEqualToString:@"="]) {
length++;
}
//计算栈
NSMutableArray *endArray = [[NSMutableArray alloc] init];
NSInteger endTop = -1;
int i = 0;
while (i < length) {
if ([newArray[i] isEqualToString:@"="]) {
break;
}
if (!OCCompare(newArray[i])) {
[endArray addObject:newArray[i]];
endTop++;
i++;
} else {
NSMutableArray *transArray = [[NSMutableArray alloc] init];
[transArray addObject:endArray[endTop]];
endTop--;
[endArray removeLastObject];
[transArray addObject:endArray[endTop]];
endTop--;
[endArray removeLastObject];
[transArray addObject:newArray[i]];
i++;
float num = Calculation(transArray);
[endArray addObject:[NSString stringWithFormat:@"%f", num]];
endTop++;
}
}
return [endArray[0] floatValue];
}
代码地址:计算器