下面代码实现可以计算 类似以下的字符窜。
@"(1+2*(3+4)+3)/2"
自写一个简单 stack 。不知道 OC为什么不提供Stack类。
#import <Foundation/Foundation.h> @interface MyStack : NSObject { } @property NSMutableArray* mArray ; @property int size ; -(id) pop ; -(void) push:(id)obj ; -(MyStack* )init ; @end
#import "MyStack.h" @implementation MyStack @synthesize mArray ; @synthesize size ; -(id) pop { id temp =mArray.lastObject ; [mArray removeLastObject] ; return temp ; } -(void) push:(id)obj { if(mArray!=nil && obj !=nil){ [mArray addObject:obj ]; } } -(MyStack* )init { self = [super init]; if(self!=nil&&self.mArray ==nil){ self.mArray = [[NSMutableArray alloc]init]; } return self ; } @end
编写计算类
#import "NSString+index.h" #import <Foundation/Foundation.h> @interface MyCalculater : NSObject
//计算子窜,没有括号的式子 +(NSNumber*)calculate:(NSString*) str;
//计算总窜 +(NSNumber*)compute:(NSString*)StringToCompute ; @end//
// MyCalculater.m // hellowWorld // // Created by hongtao on 2018/4/4. // Copyright © 2018年 hongtao. All rights reserved. // #import "MyCalculater.h" #import "MyStack.h" @implementation MyCalculater +(NSNumber*)compute:(NSString*)StringToCompute { MyStack *myStack = [[MyStack alloc]init]; NSNumber * result =nil; while (true) { Boolean needFinish = false; for (int i = 0; i<StringToCompute.length; i++) { if([StringToCompute characterAtIndex:i]=='('){ NSString * str = [StringToCompute substringWithRange:NSMakeRange(0, i)]; [myStack push:str]; NSString *strtemp = [StringToCompute substringWithRange:NSMakeRange(i+1, StringToCompute.length-i-1)]; StringToCompute = [[NSMutableString alloc]initWithString:strtemp]; break; } if([StringToCompute characterAtIndex:i]==')'){ NSString *strTemp = [StringToCompute substringToIndex:i]; StringToCompute =[StringToCompute substringWithRange:NSMakeRange(i+1,StringToCompute.length-i-1)]; NSMutableString * mstr = [[NSMutableString alloc]init]; [mstr appendString:[myStack pop] ]; [mstr appendString:[[MyCalculater calculate:strTemp] stringValue]] ; [mstr appendString:StringToCompute]; StringToCompute = [mstr copy]; mstr = nil; break; } if(i==StringToCompute.length-1){
//已没有括号
if([StringToCompute containsString:@"+"]||[StringToCompute containsString:@"-"]||[StringToCompute containsString:@"*"] ||[StringToCompute containsString:@"/"])
{
result= [MyCalculater calculate:StringToCompute]; NSLog(@"result:%@",result ); }else{ result =StringToCompute ; NSLog(@"result:%@", StringToCompute); } needFinish = true; } } if(needFinish){ break; } } return nil ; } +(NSNumber*)calculate:(NSString*) strTmp { //计算没有括号的式子。1.分离式子,分个因子放到数组。2.找到符号位,做左右两边计算,结果用来替换原来符号位,删除左右两个计算数。
NSMutableArray* array = [[NSMutableArray alloc]init]; while (true) { //先计算 * / Boolean needContinue = true; for (int i = 1; i<strTmp.length; i++) { char c= [strTmp characterAtIndex:i]; if(c=='+'||c=='-'||c=='*'||c=='/'){
//拆开式子 NSString * temp = [strTmp substringWithRange:NSMakeRange(0, i)]; [array addObject:temp]; temp = [strTmp substringWithRange:NSMakeRange(i, i)]; [array addObject:temp]; strTmp = [strTmp substringWithRange:NSMakeRange(i+1, strTmp.length - i-1)]; if(strTmp.length<=1){ needContinue = false; [array addObject:strTmp]; } break; } } if(!needContinue){ break; } } // NSLog(@"%@",array); while (true) {
//做 * 和 / Boolean needFinish = false; for (int i =0 ; i< array.count ; i++) { if([array[i] isEqual:@"/"]||[array[i] isEqual:@"*"]){ NSNumber *left = array[i-1]; NSNumber *right = array[i+1]; double result = 0.0 ; if([array[i] isEqual:@"/"]){ result = [left doubleValue]/[right doubleValue] ; } if([array[i] isEqual:@"*"]){ result = [left doubleValue]*[right doubleValue] ; } //替换符号位,删除左右元素。 array[i]=@(result); NSLog(@"%@",array); [array removeObjectAtIndex:i-1]; NSLog(@"%@",array); [array removeObjectAtIndex:i]; NSLog(@"%@",array); break; } if (i==array.count -1){ needFinish = true; } } if(needFinish){ NSLog(@"%@",array); break; } } while (true) { Boolean needFinish = false;
//做 + 和 - 运算 for (int i =0 ; i< array.count ; i++) { if([array[i] isEqual:@"+"]||[array[i] isEqual:@"-"]){ NSNumber *left = array[i-1]; NSNumber *right = array[i+1]; double result = 0.0 ; if([array[i] isEqual:@"+"]){ result = [left doubleValue]+[right doubleValue] ; } if([array[i] isEqual:@"-"]){ result = [left doubleValue]-[right doubleValue] ; } //基本与上面同理。 array[i]=@(result); NSLog(@"%@",array); [array removeObjectAtIndex:i-1]; NSLog(@"%@",array); [array removeObjectAtIndex:i]; NSLog(@"%@",array); break; } if (i==array.count -1){ needFinish = true; } } if(needFinish){ NSLog(@"%@",array); break; } } return (NSNumber*)array[0]; } @end
扩展NSString 方法,竟然没有 indexof lastIndexOf 方法。自写。
#import <Foundation/Foundation.h> @interface NSString (index) -(int) indexOf:(char)c ; -(int) lastIndexOf:(char)c ; @end
#import "NSString+index.h" @implementation NSString (index) -(int) indexOf:(char)c { int index = -1 ; for (int i =0; i< [self length]; i++) { if('c'== [self characterAtIndex:i]){ index = i ; break; } } return index ; } -(int) lastIndexOf:(char)c { int index = -1 ; for (int i =0; i< [self length]; i++) { if('c'== [self characterAtIndex:i]){ index = i ; } } return index ; } @end
可以是类方法,这里就不改了。
main 方法中调用。
#import "MyCalculater.h" int main(int argc, const char * argv[]) { @autoreleasepool { NSLog(@"%@",[MyCalculater compute:@"(1+2*(3+4)+3)/2"]); } return 0; }
匹配括号的思想是栈的使用。遇左括号截取对应部分压栈,遇右括号出栈并计算替换。
没有检查合法性。没有做代码优化。