#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include <math.h>
struct stack {
	int alpha;
	struct stack *nxtPTR;
};

typedef struct stack  Stack;

typedef  Stack *node;

	struct stack_2 {
	
	long	double alpha;
	
	struct stack *nxtPTR_2;
	};

typedef struct stack_2  Stack_2;

typedef  Stack_2 *node_2;

node   topPTR = NULL;

node_2 topPTR_2 = NULL;

char check_stack(node data);

int isOperator(char c);

int precedence(char data_1, char   data_2);

void push_stack(node *topPTR, int value);

void push_stack_2(node_2 *topPTR_2,  double value);

int pop(node *fix) ;

double pop_2(node_2 *fix);


char infix[2][200];

double end_line( char ( *data ) [200] );

int in_line(char  ( *data ) [200]  , int  lng  );
int main(void) {


	sprintf((char *) infix,"(34.31 - 24.313) ^ 25 -  (24+24.31) + 21.31 +(21.63 ^ 3.42) / 24 ^ 31 / 13.63 - 25.31 * (24 ^ 3.21 + (24.42 - 24.35 ^ 5.31)  * (24.14 /  25.31))" );


	
int  k = strlen( (char * )  infix    );
 double sl = 0;	

 
 if (in_line( infix , k ) == 1){
 	
	sl =   end_line(  infix);
	printf("%.2f\n", sl );
 }

	



return 0;
}

double end_line( char ( *data ) [200] ){

double x = 0 , y = 0, sum = 0,ml = 0    ; 
char	*point =   strtok(  (*data + 200), " " );
							 
	
	while( point   ){
			
		if(isdigit(  *point ) ){
			
			ml  = atof( (char *)  point  )  ;
			push_stack_2( &topPTR_2,ml);
			
			}	
			
		else if ( isOperator ( *point ) == 1 ){
				 
			y =	pop_2(&topPTR_2);
			x = pop_2(&topPTR_2);	 	
		
		if( *point  == '^' ){
			
			sum  =  pow(x, y) 	  ;
			push_stack_2(  &topPTR_2, sum  );
			}
					
					
			if( *point  == '*' ){
			 
				
				 push_stack_2(&topPTR_2,    	x * y         );
			 }
				 		
		 	if( *point == '+' ){
	
				 push_stack_2(&topPTR_2, 	x + y  	 );
			}
				 
	     	if(  *point == '/' ){
			 	
				push_stack_2(&topPTR_2, x / y    );
			 }
				 
			 if(   *point == '-' ){
				 
						 push_stack_2(&topPTR_2,   x - y     );
				}
			}
				
			point = strtok(NULL , " " ) ;
				}
	
	
	return    pop_2(&topPTR_2);
}


int in_line(char ( *data ) [200] , int  lng ){
	

int j = 0  , k = 0 , d = 0;
	
	
	
	(*(*data + lng  ) ) = ')';
    push_stack(&topPTR, '(');
	

	for (k = 0; check_stack((void *) &topPTR) != 1   ; k++)  {

		if (  isdigit(  	(*(*data + k  ) )  ) ||  	(*(*data + k  ) ) == '.'  ) {

				*(*data + 200 + j++ )   = 	(*(*data + k  ) );
	
		}

		if (	(*(*data + k  ) ) == '(') {

			push_stack(&topPTR, (*(*infix + k  ) ) ) ;

		}
			if (isOperator((*(*data + k  ) )  ) == 1) {
				*(*data + 200 + j++ )  = ' ';
			for (;         precedence(topPTR->alpha, (*(*data + k  ) )  ) != -1 ; ) {
		
			*(*data + 200 + j++ )= pop(&topPTR);
			*(*data + 200 + j++ )  = ' ';	
		}
				
			push_stack(&topPTR, 	(*(*data + k  ) ) );
			push_stack(&topPTR, ' ' );
			
		}

		if (	(*(*data + k  ) ) == ')') {
	
		d = pop(&topPTR);
			for (; d != '('     ; 	d = pop(&topPTR)) {
					*(*data + 200 + j++ )  = d;
				
				}
			}
		
		else if (isalpha((*(*data + k  ) )   ) ) {
			puts ("error");
			return 0;
		}
		
		}

	return 1;
	}


void push_stack(node *topPTR, int value) {

	node newPTR = malloc(sizeof(Stack));

	if (newPTR != NULL) {

		newPTR->alpha = value;
		newPTR->nxtPTR = *topPTR;
		*topPTR = newPTR;

	}
	else {

		puts("error");
	}
}

void push_stack_2(node_2 *topPTR_2,  double value) {

	node_2 newPTR = malloc(sizeof(Stack_2));

	if (newPTR != NULL) {

		newPTR->alpha = value;
		newPTR->nxtPTR_2 = (void *)  *topPTR_2;
		*topPTR_2 = newPTR;

	}
	else {

		puts("error");
	}
}

int pop(node *fix) {
	
	int  value = 0;
	node temp = *fix;
	value = (*fix)->alpha;
	*fix = (*fix)->nxtPTR;
	free(temp);

return value;
}

double pop_2(node_2 *fix) {
	
	double  value = 0;
	node_2 temp = *fix;
	value = (*fix)->alpha;
	*fix = (void *)   (*fix)->nxtPTR_2;
	free(temp);

return value;
}



char check_stack(node data) {

	return data->alpha   ==  0  ;

}

int isOperator(char c) {

	return c == '/' || c == '*' || c == '-' || c == '+' || c == '^' ;

}

int precedence(char data_1, char  data_2) {
		
	switch(data_1){
		case '(':	
	
		return -1;
		case '^':
	
			if(data_2 == '^' ){
				return    0;
				} 
			
	 	case 	'/' : 
        case 	'*':        
			
			if(data_2 == '^' ){
					return    -1;
				} 
			
			else if( data_2 == '/' || data_2 == '*'     ){
					return    0;
					}	
				
			else if( data_2 == '+' || data_2 == '-'     ){
						return     1;
					}
		case  ' ':
		case  '+':
		case  '-':		
		
		if(data_2 == '^'  || data_2 == '/' || data_2 == '*'        ){
			return    -1;
				} 
		else{
			return     0;
		}
	}
return 0;
}
