Maker Pro
Maker Pro

infix to postfix negation

lady_krizzie

Aug 2, 2012
30
Joined
Aug 2, 2012
Messages
30
I am trying to make a calculator program. But I have a problem with the negative sign. I fixed the program to do expression of (0-5)+12 if I want 5 to be negative. But I want and I am expecting it to do -5+12 Please help...Thank you in advance.

Code:
#define MAX_CHAR 64

#define LP 10
#define RP 20
#define OPERATOR 30
#define OPERAND 40
#define UNARY 50

#define LPP 0
//#define LPP 1// Left parentheses precedence. Minimum of all
#define RPP 1
#define AP 2// Addition Subtraction precedence. Minimum among all operator precedence
#define SP AP
#define MP 4// Multiplication divisor precedence.
#define DP MP
#define REMP 2// Remainder precedence.
#define NONE 9

char input_string[MAX_CHAR] = {};
char out_string[MAX_CHAR*2]= {}; //input_string
char bufer_string[MAX_CHAR] = {};
double stack_string[MAX_CHAR] = {};
char *next;
int input_index = 0;
int bufer_index = 0;
int stack_index = 0;

int foo = 0;
int isanumber = 0;

int num = 0;
//int num = 0;
int error = 0;	
	
void infixtopostfix(void);     /** POSTFIX CONVERSION FUNCTION **/
int gettype(char);             /** TYPE OF EXPRESSION GENERATOR **/
void push1(char);               /** PUSH FUNCTION **/
void push2 (int);
char pop1(void);                /** POP FUNCTION **/
int pop2 (void);
int getprec(char);             /** PRECEDENCE CHECKER FUNCTION **/
int getValue(void);
/************************************************************************/
/*                                                                                        */
/************************************************************************/
void infixtopostfix(void)
{
	int i,p,l,type,prec;
	//char next;
	i=p=0;
	l=strlen(input_string);
	while(i<l)
	{
		type=gettype(input_string[i]);
		switch(type)
		{
		case LP:
			push1(input_string[i]);
			break;
		case RP:
				//while((next=pop1())!='(')
				//out_string[p++]=next;
				out_string [p++]= ' ';
				out_string [p++]= pop1();
				pop1() != '(';
			break;
		case OPERAND:
			out_string[p++]=input_string[i];
			break;
		case UNARY:
			push1(input_string[i]);
			break;	
		case OPERATOR:
		default:
			out_string[p++] = ' ';
			prec=getprec(input_string[i]);
			while(stack_index>-1 && prec <= getprec(stack_string[stack_index]))
			{
				//out_string[p++] = ' ';
				out_string[p++]=pop1();
				out_string [p++] = ' ';
			}			

			push1(input_string[i]);
			break;
		}
		i++;
	}
	while(stack_index>-1)
	{
		out_string[p++] = ' ';
		out_string[p++]=pop1();
	}	
	out_string[p]='\0';
}


int gettype(char num)
{
	int i,p;
	i= 0;		
	switch(num)
	{
		case '(':
			return(LP);
		case ')':
			return(RP);
		case '*':
		case '/':
		case '+':
		case '-':
			if ((input_string == OPERATOR) || (input_string == '\0') && (input_string== '-'))	//a minus sign followed by a  or null is a unary
				{
				return (UNARY);
				} 
				
			else
				{
				return (OPERATOR);
				}			
				
		case '%':
		case '\t':
			return(OPERATOR);
		/*case '-':
			return(UNARY);*/
		default :
			return(OPERAND);
	}
}

/***************************************************/
void push1(char num)
{
	if(stack_index > MAX_CHAR)
	{
		printf("\nStack is full\n");
		exit(0);
	}
	else
	stack_string[++stack_index]=num;
}

char pop1(void)
{
	if(stack_index<=-1)
	{
		printf("\nStack is empty\n");
		exit(0);
	}
	else
	return(stack_string[stack_index--]);
}


void push2(int num)
{
	 if (stack_index > MAX_CHAR)
    {
        printf("error: push to full stack\n");
        error = 1;
    }
    else
    {
        stack_string[stack_index++] = num;
    }
}


int pop2(void)
{
    int retval = 0;

    if (--stack_index < 0)
	//if (stack_index<=-1)
    {
        error = 1;
        printf("error: pop empty stack\n");
		//exit(0);
    }
    else
    {
        retval = stack_string[stack_index];
        stack_string[stack_index] = '\0';
    }

    return retval;
}

/******************************************************/
int getprec(char num)
{
	switch(num)
	{
		case '(':
			return(LPP);
		case ')':
			return (RPP);
		case '*':
			return(MP);
		case '/':
			return(DP);
		case '+':
			return(AP);
		case '-':
			return(SP);
			//return(UNARY);
		case '%':
			return(REMP);
		default :
			return(NONE);
	}
}


int getValue(void)//return an integer input.  next points to first digit
{					//allows a negative answer, second digit or operand is lesser than the first operand
	int value = 0;

	while(isdigit(*next))
	{
		value = 10 * value + *next - '0';
		++next;
	}

	return value;
}


/************************************************************************/
/*                                                                                        */
/************************************************************************/

int main (void)
{
	USART_Init(51);
	stdout = &uart_output;
	stdin  = &uart_input;
	char choice;
	int r; // repeat
	char garbage;
	int bar;
	int ch;
	do
	{
		stack_index=-1;
		printf("\nEnter an infix expression\n");
		scanf("%[^\t]s", input_string);
		infixtopostfix();
		printf("\ninfix = %s\npost fix =%s\n",input_string,out_string);
	
		bar = 0;
		while(bar < strlen(stack_string))
		{
			stack_string[bar++] = '\0';
		}
		stack_index = 0;

		input_index = 0;
		while (input_index < strlen(out_string)) //while operand is not reach
		{
			bufer_index = 0;
			if (isdigit(out_string[input_index]))
			{
				isanumber = 1;			//a digit is found
				
				for (foo=input_index; foo<strlen(out_string); foo++)
				{
					if (isdigit(out_string[foo]))
					bufer_string[bufer_index++] = out_string[foo];
					else
					break;
				}
				input_index = foo + 1;
			}
			else
			{
				isanumber = 0;
				bufer_string[bufer_index++] = out_string[input_index++];
			}
			bufer_string[bufer_index] = '\0';

			if (isanumber)
			{
				// if element is a number, push to stack
				//push(bufer_string);
				push2(atol(bufer_string));
				asm volatile ("nop"::);
			}
			else
			{
				// if not a number, check if valid operator
				switch (bufer_string[--bufer_index])
				{
					case '+':
						push2(pop2() + pop2());
						break;
					case '-':
						if (isdigit(*(next + 1)))
							{
								++next;
								push2(-getValue());
							}
						else if ('-' == UNARY) // unary operator
							{
								push2(pop2() * 1);
							}
						else
							num = pop2();
							push2(pop2() - num);
							break;
					case '*':
						push2(pop2() * pop2());
						break;
					case '/':
						if (num != 0)
							{
								num = pop2();
								push2(pop2()/num);
								printf(" ");
							}	
						else if ('-' == UNARY) // unary operator
							{
								push2(pop2() * -1);
							}
						else
							{
								num=0;
								printf("MATH ERROR \n");
							}							
						break;
					case '%':
						num = pop2();
						push2(pop2() % num);
						break;
					default:
						break;
				}
				bufer_index++;
			}

			// check for error
			if (error == 1)
			break;
		}

		if (error == 0)
			printf("\nAnswer: %d", pop2());	
		
	printf("\nNew Operand [y/n]");
	if(choice=='y'||choice=='Y')
	scanf("%d" , &r);
	}
	while( (getchar()!='n') && (getchar()!='N') );
		return 0;
}
 

dahhal

Jul 17, 2012
58
Joined
Jul 17, 2012
Messages
58
would a quick hack would be to detect that the first character is an - and to add 0 in front of it.

this wouldn't work well for when you + and - number like 5+-2. though this could be solved by another routine that looks for double operators ++, +-, -- and to change it to + -, and + respectively. This could all occur before your current code.
 
Top