#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
// token의 타입
typedef enum
{
// 정수 및 실수
INT,
FLT
} kind;
struct number
{
kind t;
union
{
int i;
float f;
} val;
};
int perfect = 1;
struct number num;
enum
{
NULL_T,
NUMBER,
PLUS,
STAR,
// 빼기(-)
MINUS,
// 나누기(/)
SLASH,
LP,
RP,
END
} token;
struct number expression();
struct number term();
struct number factor();
void get_token();
void error(int i);
void warning();
void main()
{
struct number result;
get_token();
result = expression();
if (token != END)
error(3);
else
{
if (perfect == 0)
warning();
if (result.t == INT)
// 정수
printf("%d \n", result.val.i);
else
// 실수
printf("%f \n", result.val.f);
}
}
struct number expression()
{
struct number result, tmp_term;
result = term();
while (token == PLUS || token == MINUS)
{
int operation = token;
get_token();
tmp_term = term();
if (result.t == INT && tmp_term.t == INT)
{
if (operation == PLUS)
result.val.i = result.val.i + tmp_term.val.i;
else
result.val.i = result.val.i - tmp_term.val.i;
}
else
{
if (result.t == INT)
{
perfect = 0;
result.val.f = (float)result.val.i;
}
if (tmp_term.t == INT)
{
perfect = 0;
tmp_term.val.f = (float)tmp_term.val.i;
}
if (operation == PLUS)
result.val.f = result.val.f + tmp_term.val.f;
else
result.val.f = result.val.f - tmp_term.val.f;
result.t = FLT;
}
}
return (result);
}
struct number term()
{
struct number result, tmp_factor;
result = factor();
while (token == STAR || token == SLASH)
{
int operation = token;
get_token();
tmp_factor = factor();
if (result.t == INT && tmp_factor.t == INT)
{
if (operation == STAR)
result.val.i = result.val.i * tmp_factor.val.i;
else
result.val.i = result.val.i / tmp_factor.val.i;
}
else
{
if (result.t == INT)
{
perfect = 0;
result.val.f = (float)result.val.i;
}
if (tmp_factor.t == INT)
{
perfect = 0;
tmp_factor.val.f = (float)tmp_factor.val.i;
}
if (operation == STAR)
result.val.f = result.val.f * tmp_factor.val.f;
else
result.val.f = result.val.f / tmp_factor.val.f;
result.t = FLT;
}
}
return (result);
}
struct number factor()
{
struct number result;
if (token == NUMBER)
{
if (num.t == INT)
{
result.t = INT;
result.val.i = num.val.i;
}
else
{
result.t = FLT;
result.val.f = num.val.f;
}
get_token();
}
else if (token == LP)
{
get_token();
result = expression();
if (token == RP)
get_token();
else
error(2);
}
else
{
error(1);
}
return (result);
}
void get_token()
{
// next token --> token
char ch = getchar();
if (isdigit(ch))
{
token = NUMBER;
// number value --> num
num.val.i = ch - '0';
while (isdigit(ch = getchar()))
{
num.val.i = num.val.i * 10 + (ch - '0');
}
num.t = INT;
if (ch == '.')
{
num.t = FLT;
num.val.f = num.val.i;
float fraction = 1.0;
while (isdigit(ch = getchar()))
{
num.val.f = num.val.f + (ch - '0') * (fraction /= 10.0);
}
}
ungetc(ch, stdin);
}
else if (ch == '+')
token = PLUS;
else if (ch == '*')
token = STAR;
else if (ch == '-')
token = MINUS;
else if (ch == '/')
token = SLASH;
else if (ch == '(')
token = LP;
else if (ch == ')')
token = RP;
else if (ch == '\n' || ch == EOF)
token = END;
else
token = NULL_T;
}
void error(int i)
{
switch (i)
{
case 1:
printf("Error: expected a number or a left parenthesis\n");
break;
case 2:
printf("Error: expected a right parenthesis\n");
break;
case 3:
printf("Error: expected end of input\n");
break;
}
exit(1);
}
void warning()
{
// 혼합연산
printf("Warning: Mixed operation with float and int.\n");
}
댓글