#include<stdio.h>
#include<stdlib.h>//문자열을 정수형으로 변환함
#include<math.h>//x값보다 가장 작은 정수값을 구함
#include<malloc.h>//메모리할당
#include<conio.h>//현재텍스트 윈도우의 내용을 지운후 커서를 왼쪽위로 이동시킴
#include<dos.h>
#include<ctype.h>//문자를 분류하는 함수들을 정의


#define MAX 100   //배열의 최대개수를 지정
#define MAX_ROW 100  //화면의 최대 행의 수
#define MAX_COL 100  //화면의 최대 열의 수

typedef struct s_item
{
 char value;
 struct s_item *back;
}//구조체 s_item


STACK;   /*스택을 구성하는 노드는
      (데이타, 그 전 노드를 가르키는 포인터)로 구성*/

STACK *top ; //스택의 최상위를 가르키는 포인터

void make_stack(void);

void delete_stack(void);  //스택을 malloc와 free를 사용하여 생성,소멸시킴

int create_to_stack(int push); //노드를 하나 더 생성
int delete_to_stack(void);  //노드를 지움(free사용)
int check_top_stack(void);  //스택의 꼭대기에 있는 값을 체크
int check_empty_stack(void); //스택이 비었는지 체크

void in_to_post(char *before,char *after);
//intofix형태의 수식을 postfix형식으로 고치를 함수

int calculator(char *ques);
//after에 있는 수식을 계산하여 그 값을 리턴

int operator01(int opr1);  //operator01값 부여
int operator02(int opr2);  //operator02값 부여


void main(void)
{
 char infix[MAX];  //처음에 입력받은 수식을 넣음
 char postfix[MAX];  //후에 변환된 수식을 넣음
 int result;    //결과값을 넣어둠
    printf("\n");
 printf("컴퓨터정보학과 2006270181 이재정\n");
 printf("중위 표기법에서 후위 표기법으로 변환 후 계산하기!!!\n\n");

 printf("중위 표기법으로 입력하시오 : ");
 scanf("%s",infix);  //입력받는 수식을 문자열로 받음
 in_to_post(infix,postfix);//함수 in_to_post를 호출함

 printf("후위 표기법으로 계산한 값 : %s\n",postfix);

 in_to_post(infix,postfix);

 result = calculator(postfix);//함수 calculator에서 계산된 값을 가져옴
 printf("결과 값 : %d\n\n끝\n",result);//출력


}

//스택 형성
void make_stack(void)
{
 top = (STACK *)malloc(sizeof(STACK));
 //동적 메모리 할당
 top->value = -1;
 top->back = NULL;
}

//스택 삭제: free를 사용하여 메모리에 반환
void delete_stack(void)
{
 free(top);//동적 메모리 할당 취소
}

//스택 추가
int create_to_stack(int push_value)
{
 STACK *addptr;
 addptr = (STACK *)malloc(sizeof(STACK));
 if(addptr == NULL)
 {
  printf(" E R R O R \n");
  exit(1);
 }
 addptr->value = push_value;
 addptr->back = top;
 top = addptr;
 return push_value;
}

//스택에서 값을 catch
int delete_to_stack(void)
{
 int pop_value;
 int delptr;

 if(top->back ==NULL)
 {
  printf(" E R R O R \n");
  exit(1);
 }
 delptr = top;
 pop_value = top->value;
 top = top->back;
 free(delptr);
 return pop_value;
}

//스택의 꼭대기에 있는 값을 리턴해주거나 비었으면 -1을 리턴
int check_top_stack(void)
{
 if(top->back == NULL) return -1;
 else return top->value;
}

//스택이 비었으면 참값을 그렇지 않으면 거짓값을 리턴해준다.   
int check_stack_empty(void)
{
 return (top->back == NULL);
}

//각각의 연산자들에 operator01값을 넣어줌(계산에 쓰이는 연산자)
int operator01(int opr1)
{
 switch(opr1)
 {
  case '^':return 3;
  case '*':return 2;
  case '/':return 2;
  case '+':return 1;
  case '-':return 1;
 }
 return 0;
}

//각각의 연산자들에 operator02값을 넣어줌(계산에 쓰이는 연산자)
int operator02(int opr2)
{
 switch(opr2)
 {
  case '^':return 4;
  case '*':return 2;
  case '/':return 2;
  case '+':return 1;
  case '-':return 1;
 }
 return 0;
}

//infix -> postfix 형식으로 바꾸어주는 함수
void in_to_post(char *before, char *after)
{
 make_stack();    //default노드를 생성
 while(*before)
 {  
  //입력된 문자열의 끝에 도달할 때까지 검사
  switch(*before)
  {
   //입력된 문자열을 하나 하나 검사
   case '\0': while (!check_stack_empty())
   {
    *after++ = delete_to_stack();
    *after++ = ' ';
   }
   *after = '\0';
     break;
   case ' ':before++;
     break;
    //빈칸이면 건너 뛴다.
   case '(':create_to_stack(*before);
     before++;
     break;
    //'('면 그냥 스택에 push 한다.
   case ')':while(check_top_stack()!='(')/*if ) -> to see ( -> loop */
   {
    *after++ = delete_to_stack();
    *after++ = ' ';
   }
    delete_to_stack();
    before++;
    break;
    //')' 면 '('를 만날 때 까지 pop 한다.
   case '+':

   case '-':

   case '*':

   case '/':

   //스택에 있는 연산자의 operator01과 들어오는 연산자의 operator02를 비교
   case'^': while(operator01(check_top_stack()) >= operator02(*before))
   {
    *after++ = delete_to_stack();
    *after++ = ' ';
   }
   //결과가 크거나 값으면 POP한다.
   create_to_stack(*before);
   //그렇지 않으면 PUSH한다.
     before++;
     break;
   default: //operand 인 경우
     // 1자리 이상의 숫자가 들어 올 수 있으므로
     while(*before >= '0' && *before <= '9')
     *after++ = *before++;
     *after++ = ' ';
  }
 }
   //문자열의 끝이므로, 스택에 남아 있는 값들을 pop한다.
 while(!check_stack_empty())
 {
  *after++ = delete_to_stack();
  *after++ = ' ';
 }
 after--;
 *after = 0;
}

//수식을 연산함
int calculator(char *ques)
{
 int oper1;
 int oper2;
 int operand;
 make_stack();  //operand의 임시 대피 장소

 //수식의 끝을 만날 때까지 검사
 while(*ques)
 {
  switch(*ques)
  {
   case ' ':ques++;
      break;
   case '+':   // +이면 두 번 pop하여 더한다.
      oper1 = delete_to_stack();
      oper2 = delete_to_stack();
      create_to_stack(oper1 + oper2);
      ques++;
      break;
   case '*':   // *이면 두 번 pop하여 곱한다.  
      oper1 = delete_to_stack();
      oper2 = delete_to_stack();
      create_to_stack(oper1 * oper2);
      ques++;
      break;
   case '-':   // -이면 후에 pop한 값에서 처음에 pop한 값을 뺀다.
      oper1 = delete_to_stack();
      oper2 = delete_to_stack();
      create_to_stack(oper2 - oper1);
      ques++;
      break;
   case '/':   // '/'면 후에 pop한 값에서 처음에 pop한 값을 나눈다.
      oper1 = delete_to_stack();
      oper2 = delete_to_stack();
      create_to_stack(oper2/oper1);
      ques++;
      break;
   case '^':   // ^면 후에 pop한 값을 처음에 pop한 값으로 pow한다.
      oper1 = delete_to_stack();
      oper2 = delete_to_stack();
      create_to_stack(pow(oper2,oper1));
      ques++;
      break;
   default:   // 현재 숫자가 문자로 인식되고 있으므로
        //char -> int형으로 바꿔주는 작업이 필요.
      operand = 0;
     do{
       operand = operand*10 + *ques - '0';
       ques++;
       }while(*ques >= '0' && *ques <= '9');
     create_to_stack(operand);
     break;
   }
 }
 // 그 결과 값을 리턴해준다.
 return delete_to_stack();
}

// 자료구조 과목에서 후달리면 나중에 알고리즘 과목가서 개후달립니다.
// 자료구조는 100% 마스터 해주는 센스

Posted by 정훈승