아래는 지금까지 작성한 프로그램입니다.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#pragma warning (disable:4996)
char *cStack;
int cSize;
int cTop;
void cInitStack(int aSize)
{
cSize = aSize;
cStack = (char *)malloc(cSize*sizeof(char));
cTop = -1;
}
void cFreeStack()
{
free(cStack);
}
int cPush(char data)
{
if (cTop < cSize - 1) {
cTop++;
cStack[cTop] = data;
return 1;
}
else {
return 0;
}
}
char cPop()
{
if (cTop >= 0) {
return cStack[cTop--];
}
else {
return -1;
}
}
double *dStack;
int dSize;
int dTop;
void dInitStack(int aSize)
{
dSize = aSize;
dStack = (double *)malloc(dSize*sizeof(double));
dTop = -1;
}
void dFreeStack()
{
free(dStack);
}
int dPush(double data)
{
if (dTop < dSize - 1) {
dTop++;
dStack[dTop] = data;
return 1;
}
else {
return 0;
}
}
double dPop()
{
if (dTop >= 0) {
return dStack[dTop--];
}
else {
return -1;
}
}
int GetPriority(int op)
{
switch (op) {
case '(':
return 0;
case '+':
case '-':
return 1;
case '*':
case '/':
case '%':
return 2;
case '^':
return 3;
}
return 100;
}
void MakePostfix(char *postfixExp, const char *infixExp) {
const char *m = infixExp;
char *p = postfixExp, c;
cInitStack(256);
while (*m) {
// 숫자 - 그대로 출력하고 뒤에 공백 하나를 출력한다.
if (isdigit(*m)) {
while (isdigit(*m) || *m == '.') *p++ = *m++;
*p++ = ' ';
}
// 연산자 - 스택에 있는 자기보다 높은 연산자를 모두 꺼내 출력하고 자신은 푸시한다.
else if (strchr("^*/%+-", *m)) {
while (cTop != -1 && GetPriority(cStack[cTop]) >= GetPriority(*m)) {
*p++ = cPop();
}
cPush(*m++);
}
else
// 여는 괄호 - 푸시한다.
if (*m == '(') {
cPush(*m++);
}
// 닫는 괄호 - 여는 괄호가 나올 때까지 팝해서 출력하고 여는 괄호는 버린다.
else if (*m == ')') {
for (;;) {
c = cPop();
if (c == '(') break;
*p++ = c;
}
m++;
}
else {
m++;
}
}
// 스택에 남은 연산자들 모두 꺼낸다.
while (cTop != -1) {
*p++ = cPop();
}
*p = 0;
cFreeStack();
}
double CalcPostfix(const char *postfixExp)
{
const char *p = postfixExp;
double num;
double left, right;
dInitStack(256);
while (*p) {
// 숫자는 스택에 넣는다.
if (isdigit(*p)) {
num = atof(p);
dPush(num);
for (; isdigit(*p) || *p == '.'; p++) { ; }
}
else {
// 연산자는 스택에서 두 수를 꺼내 연산하고 다시 푸시한다.
if (strchr("^*/%+-", *p)) {
right = dPop();
left = dPop();
switch (*p) {
case '+':
dPush(left + right);
break;
case '-':
dPush(left - right);
break;
case '*':
dPush(left*right);
break;
case '/':
if (right == 0.0) {
dPush(0.0);
}
else {
dPush(left / right);
}
break;
case '%':
if (right == 0) {
dPush(0);
}
else {
dPush((int)left % (int)right);
}
break;
case '^':
dPush(pow(left, right));
break;
}
}
// 연산 후 또는 연산자가 아닌 경우 다음 문자로
p++;
}
}
if (dTop != -1) {
num = dPop();
}
else {
num = 0.0;
}
dFreeStack();
return num;
}
int CheckExp(const char *infixExp) {
const char *p;
int count;
for (p = infixExp, count = 0; *p; p++) {
if (*p == '(') count++;
if (*p == ')') count--;
}
return count;
}
int main(void) {
char infixExp[256];
char postfixExp[256];
int Error;
double result;
printf("\n");
printf("\n");
printf("*************************\n");
printf(" STACK 계 산 기\n");
printf("*************************\n");
printf("\n");
printf("\n");
system("pause");
system("cls");
while (1) {
printf("수식 입력(끝내려면, exit 를 입력)\n ->");
gets(infixExp);
if (strcmp(infixExp, "exit") == 0) break;
Error = CheckExp(infixExp);
if (Error != 0)
printf("수식이 잘못되었습니다.\n");
else {
printf("Infix: %s\n", infixExp);
MakePostfix(postfixExp, infixExp);
result = CalcPostfix(postfixExp);
printf("Postfix: %s\n", postfixExp);
printf("Result: %.2f\n", result);
}
}
}