Iphone表示式計算器

下面是用OC寫的一個表示式計算器:(思路跟Android表示式計算器差不多。)

1.中綴表示式轉字尾表示式

//convert infix Expression into Posfix Expression
-(ExpStack *)infixExpToPostfixExp:(NSString*) infixExp
{
// get a number ?
Boolean gerANumber = false;
// get numbers and operators from nsstring
char tempChar = ' ';
NSString *tempStr = @"";
ExpStack *myStack = [[ ExpStack alloc ] init ];
for( int i=0; i<[ infixExp length]; i   )
{
tempChar = [ infixExp characterAtIndex:i ];
//is not a operator
// when previous characters is number, '-' should be regarded as operator
// else '-' should be regarded as a part of a number.
if( (!gerANumber && '-'==tempChar) || ![ self isOperator:tempChar ])
{
tempStr = [ tempStr stringByAppendingFormat:@"%c", tempChar];
// this charachters must be a number
gerANumber = true;
}
else//is a operator
{
//push the number to stack
if( ![tempStr isEqualToString:@""] )
{
[ myStack push:tempStr ];
}
//get the operator
tempStr = @"";
tempStr = [ tempStr stringByAppendingFormat:@"%c", tempChar];
[ myStack push:tempStr ];
//clear tempStr
tempStr = @"";
// this charachters must be a Operator
gerANumber = false;
}
}
if( 0 != [ tempStr length] )
{
//push the number to stack
[ myStack push:tempStr ];
}
//debug info
[ myStack showStack ] ;
NSLog(@"%@", @"\n-------------------------");
//upside down mystack (now we get infix expression)
ExpStack *myinfixExp = [[ ExpStack alloc ] init ];
while( ![ myStack isEmpty ] )
{
[ myinfixExp push: [myStack getTop] ];
[ myStack pop ];
}
//debug info
[ myinfixExp showStack ] ;
NSLog(@"%@", @"\n-------------------------");
//converting (myStack is Empty now)
//get posfix Expression
ExpStack *myPosfixExp = [[ ExpStack alloc ] init ];
while( ![ myinfixExp isEmpty ] )
{
tempStr = [ myinfixExp getTop ];
if( [ self isNumber:tempStr ] )  // is number
{
[ myPosfixExp push:tempStr ];
}
else if( [ tempStr isEqualToString:@"("] ) // is open brackerts
{
[ myStack push:tempStr ];
}
else if( [ tempStr isEqualToString:@")"] ) // is close brackerts
{
if( [ myStack isEmpty ] )
{
NSLog(@"%@", @"Expression is wrong...");
return nil;
}
else
{
while(  ![ [ myStack getTop ] isEqualToString:@"(" ] ) 
{
[ myPosfixExp push: [myStack getTop] ];
[ myStack pop ];
if ( [ myStack isEmpty ] )
{
NSLog(@"%@", @"Expression is wrong...");
return nil;
}
}
if( [[myStack getTop] isEqualToString:@"("] )
{
[myStack pop];
}
}
}
else if ( [self isCaculaOperator:tempStr] ) // is caculate operator
{
/*int operatorcompareResult = [ self compareCaculatorOperator:[myStack getTop] :tempStr ];
if( -1 == operatorcompareResult )
{
NSLog(@"%@ infixExp Operator: %@ Stack Operator: %@", @"wrong caculator operator: ",
tempStr, [myStack getTop]);
return nil;
}
*/
while ( (![ myStack isEmpty]) &&
(![[ myStack getTop ] isEqualToString:@"(" ]) &&
(  [ self compareCaculatorOperator:[myStack getTop] :tempStr ] > 0 ) )
{
[ myPosfixExp push: [myStack getTop] ];
[ myStack pop ];
}
[ myStack push:tempStr ];
}
[ myinfixExp pop ];
}
while( ![myStack isEmpty ])
{
if( [[myStack getTop ] isEqualToString:@"(" ])
{
NSLog(@"%@", @"Expression is wrong...");
return nil;
}
[ myPosfixExp push:[myStack getTop] ];
[ myStack pop ];
}
//debug info
[myPosfixExp showStack ] ;
NSLog(@"%@", @"\n-------------------------");
return myPosfixExp;
}

2.計算表示式的值:

// caculate the expression
-(double) caculate
{
// remember caculte string
undoStr = caculateTextView.text;
//through filter we get infix Expression
NSString *infixExp = [self caculateStrFilter:caculateTextView.text];
ExpStack *myStack = [self infixExpToPostfixExp: infixExp];
if( nil == myStack )
{
[ self showError:@"Error" ];
NSLog(@"%@", @"Expression is wrong...");
return 0;
}
//caculate Expression value
ExpStack *posfixStack = [[ ExpStack alloc ] init ];
// up side down stack, get posfix expression
while( ![ myStack isEmpty ])
{
[posfixStack push:[ myStack getTop] ];
[myStack pop];
}
//debug info
[ posfixStack showStack ] ;
NSLog(@"%@", @"\n-------------------------");
// now myStack is empty, caculate resulte using posfix expression
NSString *numberStr1 = @"";
NSString *numberStr2 = @"";
while( ![posfixStack isEmpty ])
{
if(  [ self isNumber:[posfixStack getTop ] ] )
{
[ myStack push:[posfixStack getTop] ];
}
else if ( [ self isCaculaOperator:[posfixStack getTop] ] )
{
numberStr1 = [myStack getTop];
[myStack pop ];
numberStr2 = [myStack getTop];
[myStack pop ];
// caculate
if( [[posfixStack getTop] isEqualToString:@" " ])
{
double temDou = [numberStr1 doubleValue]   [numberStr2 doubleValue];
numberStr1 = @"";
numberStr1 = [ numberStr1 stringByAppendingFormat:@"%.15f", temDou ];
[ myStack push:numberStr1 ];
}
else if( [[posfixStack getTop] isEqualToString:@"-"])
{
double temDou = [numberStr2 doubleValue] - [numberStr1 doubleValue];
numberStr1 = @"";
numberStr1 = [ numberStr1 stringByAppendingFormat:@"%.15f", temDou ];
[ myStack push:numberStr1 ];
}
else if( [[posfixStack getTop] isEqualToString:@"*"])
{
double temDou = [numberStr1 doubleValue] * [numberStr2 doubleValue];
numberStr1 = @"";
numberStr1 = [ numberStr1 stringByAppendingFormat:@"%.15f", temDou ];
[ myStack push:numberStr1 ];
}
else if( [[posfixStack getTop] isEqualToString:@"/"])
{
double temDou = [numberStr1 doubleValue];
if( temDou-0 < 1e-20)
{
[ self showError:@"inf" ] ;
NSLog(@"%@", @"Cannot divide 0...");
return 0.;
}
temDou = [numberStr2 doubleValue] / temDou;
numberStr1 = @"";                                 /* there is different */
numberStr1 = [ numberStr1 stringByAppendingFormat:@"%.15f", temDou ];
[ myStack push:numberStr1 ];
}
else if( [[posfixStack getTop] isEqualToString:@"^"])
{
double temDou = pow( [numberStr2 doubleValue], [numberStr1 doubleValue] );
numberStr1 = @"";
numberStr1 = [ numberStr1 stringByAppendingFormat:@"%.15f", temDou ];
[ myStack push:numberStr1 ];
}
}
[posfixStack pop];
}
if( 1 != myStack.size )
{
[ self showError:@"Error" ];
NSLog(@"%@", @"Stack Size Error...");
}
else//show resulte
{
if( enableScientificNotation )
{
[ self showResultWhenEnableSN:[ myStack getTop ]];
}
else
{
[ self showResult:[ myStack getTop ] ];
}
NSLog(@"\n%@%@", @"-----------Result:", [myStack getTop]);
}
return 0.;
}

.M檔案:

http://pan.baidu.com/share/link?uk=1158831200&shareid=783048007