STACKÀ» »ç¿ëÇÏÁö ¾Ê´Â »çÄ¢¿¬»ê
°è»ê±â
ÀÛ¼º: ±èÁøÈ«
¿¬»êÀÇ ¿ì¼±¼øÀ§¸¦ À§ÇØ Á¦ÇѾøÀÌ °ýÈ£¸¦ »ç¿ëÇÒ ¼ö ÀÖ´Ù.
/*
* A CALCULATOR
*
* Coded by kim jin hong
*/
#include <stdio.h>
#include <stdlib.h>
#define MAXDATA 300 /* maximum readable characters */
#define ID_VALUE 0
#define ID_OPENPARENTHESIS 1
#define ID_CLOSEPARENTHESIS 2
#define ID_ADD 3
#define ID_SUBTRACT 4
#define ID_MULTIPLY 5
#define ID_DIVIDE 6
#define P_AS 1 /* signal for ADD or SUBTRACT */
#define P_MD 2 /* signal for MULTIPLY or DIVIDE */
#define P_UP 100 /* weight for priority */
struct datatype { /* standard united data type */
int level; /* priority of token */
int id; /* token name */
double data; /* a data; I used only double type */
} token[MAXDATA];
int itemn=0; /* total item number */
int nlength(char *); /* return length of the value */
void cpy(char *, char *, int, int); /* copy string */
int isnumber(char); /* return true if the item is a value */
void classify(char *); /* classify all the items */
void error(int); /* print error msg and quit if error occured */
void setuplevel(void); /* set up priorities all of the items */
void cpytoken(struct datatype *, struct datatype); /* copy a token */
void eliminatep(void); /* eliminate all parenthesises from the token[] */
int selectmaxlevel(void); /* select an item which has the highest priority */
double calculate(void); /* return double-type calculated data */
void eliminatespace(char *); /* eliminate white-space in the string */
void process(char *); /* call all processes before call calculate() */
void getline(char *); /* get one line from console */
void checksides(int); /* cause error if both side of the item aren't VALUE */
void main(int argc, int *argv[])
{
char str[MAXDATA];
int t;
/* you can input your expressions(with no white-space) in the parameter */
if (argc < 2) {
printf("INPUT YOUR EXPRESSIONS (MAXIMUM %d ITEMS ALLOWED)\n", MAXDATA);
getline(str);
process(str);
} else process(argv[1]);
}
void getline(char *str)
{
char c;
int idx=0;
while ((c=getchar()) != '\n' && idx < MAXDATA)
str[idx++]=c;
str[idx]=NULL;
}
void process(char *str)
{
eliminatespace(str);
classify(str);
setuplevel();
eliminatep();
printf("RESULT: %f\n", calculate());
}
int nlength(char *str)
{
int cnt=0;
if ((*str == '-') || (*str == '+')) {
cnt++;
str++;
}
while (1) {
if ((*str >= '0' && *str <= '9') || (*str == '.')) cnt++;
else break;
str++;
}
return cnt;
}
void cpy(char *dst, char *src, int from, int to)
{
int t;
for (t=from; t<=to; t++)
dst[t-from]=src[t];
dst[t]=NULL;
}
int isnumber(char c)
{
if (c >= '0' && c <= '9' || c == '.') return 1;
return 0;
}
void classify(char *str)
{
int idx=0, nlen;
char buf[30]; /* temporarily need */
while (*str != NULL) {
switch (*str) {
case '(':
token[itemn].id=ID_OPENPARENTHESIS;
itemn++;
str++;
break;
case ')':
token[itemn].id=ID_CLOSEPARENTHESIS;
itemn++;
str++;
break;
case '+':
token[itemn].id=ID_ADD;
itemn++;
str++;
break;
case '-':
token[itemn].id=ID_SUBTRACT;
itemn++;
str++;
break;
case '*':
token[itemn].id=ID_MULTIPLY;
itemn++;
str++;
break;
case '/':
token[itemn].id=ID_DIVIDE;
itemn++;
str++;
break;
default:
/* cause error if found nonuse token */
if (!isnumber(*str)) error(3);
/* cause error if found these exprs., '1(2)': this should be '1*(2)'
if (isnumber(*str) && *(str-1)==')' || *(str+1)=='(')
error(3);
/* check about the value has unary operation */
if ( (*(str-1) == '-' || *(str-1) == '+') && (!isnumber(*(str-2)))
&& (*(str-2) != ')')) {
itemn--;
str--;
}
nlen=nlength(str);
cpy(buf, str, 0, nlen-1);
token[itemn].id=ID_VALUE;
token[itemn].data=atof(buf);
itemn++;
str+=nlen;
break;
}
idx++;
}
/* cause error, if total item number below 3 */
if (itemn < 3) error(2);
/* cause error if last item is not VALUE */
if (token[itemn-1].id == ID_ADD || token[itemn-1].id == ID_SUBTRACT ||
token[itemn-1].id == ID_MULTIPLY || token[itemn-1].id == ID_DIVIDE)
error(3);
}
void error(int en)
{
switch(en) {
case 0:printf("Fatal error: Divide by zero!\n"); break;
case 1:printf("Syntax error: Not matched parenthesis.\n"); break;
case 2:printf("Syntax error: Not enough expression.\n"); break;
case 3:printf("Syntax error: Not allowed expression.\n"); break;
}
exit(1); /* exit. we can't process further more */
}
void setuplevel()
{
int t, curprior=0;
for (t=0; t<itemn; t++) {
switch(token[t].id) {
case ID_OPENPARENTHESIS:
curprior+=P_UP;
break;
case ID_CLOSEPARENTHESIS:
curprior-=P_UP;
break;
}
token[t].level=curprior;
switch(token[t].id) {
case ID_ADD :
case ID_SUBTRACT :token[t].level+=P_AS; break;
case ID_MULTIPLY :
case ID_DIVIDE :token[t].level+=P_MD; break;
default :token[t].level=0; break;
}
}
/* if curprior is not zero, that means parenthesises in the token[]
are not matched */
if (curprior != 0) error(1);
}
void cpytoken(struct datatype *dst, struct datatype src)
{
dst->level=src.level;
dst->id=src.id;
dst->data=src.data;
}
void eliminatep()
{
int t, nitemn=0;
for (t=0; t<itemn; t++)
if (token[t].id != ID_OPENPARENTHESIS &&
token[t].id != ID_CLOSEPARENTHESIS) {
cpytoken(&token[nitemn], token[t]);
nitemn++;
}
itemn=nitemn;
}
int selectmaxlevel()
{
int t, m=0;
for (t=1; t<itemn; t++)
if (token[m].level < token[t].level) m=t;
return m;
}
void checksides(int m)
{
if (m == 0 || token[m-1].id != ID_VALUE ||
token[m+1].id != ID_VALUE) error(3);
}
double calculate()
{
double acc=0.0;
int maxlevel, t;
/* if total item number is below 3... */
if (itemn < 3) error(2);
while (itemn > 1) {
maxlevel=selectmaxlevel();
checksides(maxlevel);
switch(token[maxlevel].id) {
case ID_ADD:
acc=token[maxlevel-1].data + token[maxlevel+1].data;
break;
case ID_SUBTRACT:
acc=token[maxlevel-1].data - token[maxlevel+1].data;
break;
case ID_MULTIPLY:
acc=token[maxlevel-1].data * token[maxlevel+1].data;
break;
case ID_DIVIDE:
if (token[maxlevel+1].data == 0.0) error(0);
acc=token[maxlevel-1].data / token[maxlevel+1].data;
break;
}
token[maxlevel-1].data=acc;
token[maxlevel-1].level=0;
token[maxlevel-1].id=ID_VALUE;
itemn-=2;
for (t=maxlevel; t<itemn; t++)
cpytoken(&token[t], token[t+2]);
}
return acc;
}
void eliminatespace(char *str)
{
char buf[MAXDATA];
char *ptr=str;
int idx=0;
while (*str != NULL) {
if (*str != ' ') {
buf[idx]=*str;
idx++;
}
str++;
}
buf[idx]=NULL;
cpy(ptr, buf, 0, idx-1);
}