#include<stdio.h>
#include "arith_expr.h"
#include<assert.h>
#include<ctype.h>
#include<stdlib.h>
#ifndef True
#define True 1
#define False 0
#endif
#define NS_LEN 100
#define OS_LEN 100
struct ns
{
struct NUM nums[NS_LEN];
int top;
};
struct os
{
char ops[OS_LEN];
int top ;
};
struct os opstack;
struct ns numstack;
FILE * listing;
char * str ;
int pos;
void setNum(struct NUM * pn1,struct NUM * pn2)
{
pn1->type = pn2->type;
if (pn1->type == 0)
pn1->value.ivalue = pn2->value.ivalue;
else if (pn1->type == 1)
pn1->value.fvalue = pn2->value.fvalue;
};
int nspush(struct NUM *num)
{
int rel = False;
(numstack.top)++;
if (numstack.top == NS_LEN)
fprintf(listing,"push error:the number stack is full/n");
else
{
(numstack.nums[numstack.top]).type = num->type;
(numstack.nums[numstack.top]).value = num->value; //
rel =True;
}
return(rel);
};
int nspop(struct NUM *num)
{
int rel = False;
if (numstack.top <0)
fprintf(listing,"error:the number stack is empty to pop/n");
else
{
num->type = numstack.nums[numstack.top].type;
num->value = numstack.nums[numstack.top].value;
rel = True;
}
return(rel);
};
char getNextChar()
{
return(str[pos++]);
};
void ungetNextChar()
{ pos--;
};
void getNum(char c)
{
char strvalue[50];
int i,pointnum=0;
struct NUM num;
i = 0;
while (isdigit(c)&&i<=49)
{
strvalue[i++] = c;
c = getNextChar();
}
if (c=='.'&&pointnum==0)
{
pointnum++;
strvalue[i++] = c;
c = getNextChar();
if (!isdigit(c))
{
fprintf(listing,"error.this num has a point .it may be a float,but after the point there is no digit/n ");
return;
}
while(isdigit(c))
{
strvalue[i++] = c;
c = getNextChar();
}
}
else if (c=='.'&&pointnum==1)
{
fprintf(listing,"error:tow points/n");
return;
}
ungetNextChar();
strvalue[i] = '/0';
if (pointnum==0)
{
num.type = 0; // integer
num.value.ivalue = strtol(strvalue,(char **)NULL,10);
}
else
{
num.type = 1; // float
num.value.fvalue = strtof(strvalue,(char**)NULL);
}
nspush(&num);
};
int ospush(char op)
{
opstack.top++;
if (opstack.top == OS_LEN)
{
fprintf(listing,"sorry,the operation statc is full,can not push/n");
return(False);
}
opstack.ops[opstack.top] = op;
return(1);
};
int ospop(char *op)
{
if (opstack.top<0)
{
fprintf(listing,"The operation stack is empty.can not pop/n");
return(False);
}
*op = opstack.ops[opstack.top--];
return(1);
};
void displayns() // to debug
{
int i = 0 ;
while (i <=numstack.top)
{
if (numstack.nums[i].type == 1)
fprintf(listing,"%4.2f/n",numstack.nums[i].value.fvalue);
else
fprintf(listing,"%4d/n",numstack.nums[i].value.ivalue);
i++;
}
};
void displayos() // to debug
{
int i=0;
while(i<=opstack.top)
{
printf("%c top = %-3d/n",opstack.ops[i],opstack.top);
i++;
}
};
int getPriority(char c)
{
if (c =='+'||c=='-')
return(0);
else if (c=='*'||c=='/')
return(1);
else if (c=='('||c==')')
return(2);
else
return(-1);
};
int IsHigh(char src,char des)
{
int s_prio,d_prio;
s_prio = getPriority(src);
d_prio = getPriority(des);
if (s_prio < d_prio)
return(-1);
else if (s_prio == d_prio)
return(0);
else
return(1);
};
void operate_int(int x1,int x2,char c)
{
switch (c)
{
case '+':
numstack.nums[numstack.top].value.ivalue = x1+x2;
return;
case '-':
numstack.nums[numstack.top].value.ivalue = x1-x2;
return;
case '*':
numstack.nums[numstack.top].value.ivalue = x1*x2;
return;
case '/':
numstack.nums[numstack.top].value.ivalue = x1/x2;
return;
}
};
void operate_float(float y1,float y2,char c)
{
switch(c)
{
case '+':
numstack.nums[numstack.top].value.fvalue = y1+y2;
return;
case '-':
numstack.nums[numstack.top].value.fvalue = y1-y2;
return;
case '*':
numstack.nums[numstack.top].value.fvalue = y1*y2;
return;
case '/':
numstack.nums[numstack.top].value.fvalue = y1/y2 ;
return;
}
};
void operate() // pop tow from number stack
{
int x1,x2;
float y1,y2;
char c;
ospop(&c);
if (numstack.nums[numstack.top].type==0 && numstack.nums[numstack.top-1].type==0) //integers
{
x2 = numstack.nums[numstack.top--].value.ivalue;
x1 = numstack.nums[numstack.top].value.ivalue;
operate_int(x1,x2,c);
}
else
{
if (numstack.nums[numstack.top].type==0)
y2 = (float)(numstack.nums[numstack.top--].value.ivalue);
else
y2 =numstack.nums[numstack.top--].value.fvalue;
if (numstack.nums[numstack.top].type==0)
y1 = (float)(numstack.nums[numstack.top].value.ivalue);
else
y1 = numstack.nums[numstack.top].value.fvalue;
numstack.nums[numstack.top].type = 1;
operate_float(y1,y2,c);
}//is
};
void getOp(char c)
{
int temp;
char ch;
if (c=='/0')
{
while (opstack.top>-1)
operate();
return;
}
if (c=='(')
ospush(c);
else if (c==')')
{
operate();
ospop(&c);// pop the '('
if (opstack.top<0) // empty stack
return;
}
else
{
if (opstack.top<0) // empty stack
{
ospush(c);
return;
}
temp = getPriority(opstack.ops[opstack.top]);
if (temp == 2)
{
ospush(c);
return;
}
temp = IsHigh(opstack.ops[opstack.top],c);
while(temp>=0)
{
operate(); // has poped one item
if (opstack.top<0) // empty stack
{
ospush(c);
return;
}
temp = IsHigh(opstack.ops[opstack.top],c);
}
if (temp<0)
ospush(c);
}
};
void init(FILE * fp,char * expr_str)
{
listing = fp;
str = expr_str;
pos = 0;
numstack.top = -1;
opstack.top = -1;
};
struct NUM * compute()
{
char c;
struct NUM * result = NULL;
c= getNextChar();
if (!(isdigit(c)|| c=='('||c==')'))
{
printf("error:the first character is not a digit/n");
return(result);
}
while (c!='/0')
{
if (isdigit(c))
getNum(c);
else if (c=='+'||c=='-'||c=='*'||c=='('||c==')')
getOp(c);
c = getNextChar();
}
getOp(c);
result = (struct NUM * )malloc(sizeof(struct NUM ));
assert(result != NULL);
setNum(result,numstack.nums+numstack.top);
return(result);
};
#include "arith_expr.h"
#include<assert.h>
#include<ctype.h>
#include<stdlib.h>
#ifndef True
#define True 1
#define False 0
#endif
#define NS_LEN 100
#define OS_LEN 100
struct ns
{
struct NUM nums[NS_LEN];
int top;
};
struct os
{
char ops[OS_LEN];
int top ;
};
struct os opstack;
struct ns numstack;
FILE * listing;
char * str ;
int pos;
void setNum(struct NUM * pn1,struct NUM * pn2)
{
pn1->type = pn2->type;
if (pn1->type == 0)
pn1->value.ivalue = pn2->value.ivalue;
else if (pn1->type == 1)
pn1->value.fvalue = pn2->value.fvalue;
};
int nspush(struct NUM *num)
{
int rel = False;
(numstack.top)++;
if (numstack.top == NS_LEN)
fprintf(listing,"push error:the number stack is full/n");
else
{
(numstack.nums[numstack.top]).type = num->type;
(numstack.nums[numstack.top]).value = num->value; //
rel =True;
}
return(rel);
};
int nspop(struct NUM *num)
{
int rel = False;
if (numstack.top <0)
fprintf(listing,"error:the number stack is empty to pop/n");
else
{
num->type = numstack.nums[numstack.top].type;
num->value = numstack.nums[numstack.top].value;
rel = True;
}
return(rel);
};
char getNextChar()
{
return(str[pos++]);
};
void ungetNextChar()
{ pos--;
};
void getNum(char c)
{
char strvalue[50];
int i,pointnum=0;
struct NUM num;
i = 0;
while (isdigit(c)&&i<=49)
{
strvalue[i++] = c;
c = getNextChar();
}
if (c=='.'&&pointnum==0)
{
pointnum++;
strvalue[i++] = c;
c = getNextChar();
if (!isdigit(c))
{
fprintf(listing,"error.this num has a point .it may be a float,but after the point there is no digit/n ");
return;
}
while(isdigit(c))
{
strvalue[i++] = c;
c = getNextChar();
}
}
else if (c=='.'&&pointnum==1)
{
fprintf(listing,"error:tow points/n");
return;
}
ungetNextChar();
strvalue[i] = '/0';
if (pointnum==0)
{
num.type = 0; // integer
num.value.ivalue = strtol(strvalue,(char **)NULL,10);
}
else
{
num.type = 1; // float
num.value.fvalue = strtof(strvalue,(char**)NULL);
}
nspush(&num);
};
int ospush(char op)
{
opstack.top++;
if (opstack.top == OS_LEN)
{
fprintf(listing,"sorry,the operation statc is full,can not push/n");
return(False);
}
opstack.ops[opstack.top] = op;
return(1);
};
int ospop(char *op)
{
if (opstack.top<0)
{
fprintf(listing,"The operation stack is empty.can not pop/n");
return(False);
}
*op = opstack.ops[opstack.top--];
return(1);
};
void displayns() // to debug
{
int i = 0 ;
while (i <=numstack.top)
{
if (numstack.nums[i].type == 1)
fprintf(listing,"%4.2f/n",numstack.nums[i].value.fvalue);
else
fprintf(listing,"%4d/n",numstack.nums[i].value.ivalue);
i++;
}
};
void displayos() // to debug
{
int i=0;
while(i<=opstack.top)
{
printf("%c top = %-3d/n",opstack.ops[i],opstack.top);
i++;
}
};
int getPriority(char c)
{
if (c =='+'||c=='-')
return(0);
else if (c=='*'||c=='/')
return(1);
else if (c=='('||c==')')
return(2);
else
return(-1);
};
int IsHigh(char src,char des)
{
int s_prio,d_prio;
s_prio = getPriority(src);
d_prio = getPriority(des);
if (s_prio < d_prio)
return(-1);
else if (s_prio == d_prio)
return(0);
else
return(1);
};
void operate_int(int x1,int x2,char c)
{
switch (c)
{
case '+':
numstack.nums[numstack.top].value.ivalue = x1+x2;
return;
case '-':
numstack.nums[numstack.top].value.ivalue = x1-x2;
return;
case '*':
numstack.nums[numstack.top].value.ivalue = x1*x2;
return;
case '/':
numstack.nums[numstack.top].value.ivalue = x1/x2;
return;
}
};
void operate_float(float y1,float y2,char c)
{
switch(c)
{
case '+':
numstack.nums[numstack.top].value.fvalue = y1+y2;
return;
case '-':
numstack.nums[numstack.top].value.fvalue = y1-y2;
return;
case '*':
numstack.nums[numstack.top].value.fvalue = y1*y2;
return;
case '/':
numstack.nums[numstack.top].value.fvalue = y1/y2 ;
return;
}
};
void operate() // pop tow from number stack
{
int x1,x2;
float y1,y2;
char c;
ospop(&c);
if (numstack.nums[numstack.top].type==0 && numstack.nums[numstack.top-1].type==0) //integers
{
x2 = numstack.nums[numstack.top--].value.ivalue;
x1 = numstack.nums[numstack.top].value.ivalue;
operate_int(x1,x2,c);
}
else
{
if (numstack.nums[numstack.top].type==0)
y2 = (float)(numstack.nums[numstack.top--].value.ivalue);
else
y2 =numstack.nums[numstack.top--].value.fvalue;
if (numstack.nums[numstack.top].type==0)
y1 = (float)(numstack.nums[numstack.top].value.ivalue);
else
y1 = numstack.nums[numstack.top].value.fvalue;
numstack.nums[numstack.top].type = 1;
operate_float(y1,y2,c);
}//is
};
void getOp(char c)
{
int temp;
char ch;
if (c=='/0')
{
while (opstack.top>-1)
operate();
return;
}
if (c=='(')
ospush(c);
else if (c==')')
{
operate();
ospop(&c);// pop the '('
if (opstack.top<0) // empty stack
return;
}
else
{
if (opstack.top<0) // empty stack
{
ospush(c);
return;
}
temp = getPriority(opstack.ops[opstack.top]);
if (temp == 2)
{
ospush(c);
return;
}
temp = IsHigh(opstack.ops[opstack.top],c);
while(temp>=0)
{
operate(); // has poped one item
if (opstack.top<0) // empty stack
{
ospush(c);
return;
}
temp = IsHigh(opstack.ops[opstack.top],c);
}
if (temp<0)
ospush(c);
}
};
void init(FILE * fp,char * expr_str)
{
listing = fp;
str = expr_str;
pos = 0;
numstack.top = -1;
opstack.top = -1;
};
struct NUM * compute()
{
char c;
struct NUM * result = NULL;
c= getNextChar();
if (!(isdigit(c)|| c=='('||c==')'))
{
printf("error:the first character is not a digit/n");
return(result);
}
while (c!='/0')
{
if (isdigit(c))
getNum(c);
else if (c=='+'||c=='-'||c=='*'||c=='('||c==')')
getOp(c);
c = getNextChar();
}
getOp(c);
result = (struct NUM * )malloc(sizeof(struct NUM ));
assert(result != NULL);
setNum(result,numstack.nums+numstack.top);
return(result);
};