Tour de 뚜르

관리자 | 글쓰기

Tour de 뚜르 » Search » Results » Articles

C언어와 관련된 글 1개

  1. 2009/10/29 사칙연산 계산기

Tour de 뚜르 » Study

사칙연산 계산기

뚜르 | 2009/10/29 11:33

#include
#include
#include
#include //삼각함수 선언 해더파일

#define MAX 100
#define M_PI 3.141592
#define RD(X) (X)*M_PI/180 //삼각 함수 구하는 공식

typedef enum { lparen, rparen, plus, minus, times, divide, mod, SIN, COS, TAN, eos, operand } precedence;

char stack[MAX]; // 후휘표기법으로 바꿀때 사용할 스택
double stack_eval[MAX]; // 연산시 사용할 스택 double형

int top, top_eval; // 스택의 top
char expr[MAX]; // 입력문자 전열 배열

precedence get_token(char *); // 연산자의 내용을 리턴하는 함수
double eval (char*); // 연산하는 함수
double change_value (char *,int *); // atof 함수
double push_eval(double); // 연산스택 push
double pop_eval(void); // 연산 스택 pop


void postfix(char *, char *); // 후위 표기법으로 바꾸는 함수
void init_stack(void); // 후위표기법의 스택의 초기화
char push(char);
char get_stack_top(void);
char is_stack_empty(void);
int is_operator(int);
int precedence_def(int);


void main()
{
double result; // 모든 연산의 결과값을 리턴받는다.
char c,str[MAX]; // 문자열로 입력받을 변수, 배열
int i; // 인덱스
printf("계산할 수식을 입력 하시오.\n");
for ( i=0 ; (c=getchar()) != '\n' ; i++ ) // 문자열을 받아서 배열에 넣는 루프
{
str[i] = c;
}
str[i] = '\0';

postfix(expr,str);
printf("후위표기식으로 변환한 수식은? '");
printf("%s '이다.\n",expr);
printf("연산한 갑은?\n");
result = eval (expr); // 최종 계산된 값을 리턴받는다.
printf("%lf\n", result);
}

double eval (char *expr) // 연산하는 함수
{
precedence token; // 변수 선언
double value, value_frist, value_secound;// 연산을 위해 필요한 변수
int i;
int top_eval = -1; // 스택의 초기화

for ( i=0 ; expr[i] != '\0' ; i++) // 배열을 끝까지 검색하면서 연산
{
if ( expr[i] == ' ' ) // 빈공간이면 다음칸으로 이동한다.
i++;
token = get_token(&expr[i]); // token값을 리턴받는다.

if ( token == operand )
{
value = change_value(&expr[i],&i);// 함수 숫자값(char)을 받아서 숫자값을(double) 리턴해주는 함수
push_eval(value); // 스택에 삽입
}
else if ( (token == SIN) || (token == COS) || (token == TAN) )
{
value_frist = pop_eval();//맨위의 숫자를 연산한다.
switch (token) // 삼각함수 연산시
{
case SIN : push_eval( sin( RD(value_frist)) );
break;
case COS : push_eval( cos( RD(value_frist)) );
break;
case TAN : push_eval( tan( RD(value_frist)) );
break;
}
}


else // 연산자가 들어 있다면
{
value_secound = pop_eval();// 맨위의 값이 나중 값이므로 두번째 변수에 삽입
value_frist = pop_eval();
switch (token) // 연산실시
{
case plus : push_eval(value_frist + value_secound);
break;
case minus : push_eval(value_frist - value_secound);
break;
case times : push_eval(value_frist * value_secound);
break;
case divide : push_eval(value_frist / value_secound);
break;
case mod : push_eval((int)value_frist % (int)value_secound);
break;
}


}

}
return pop_eval(); //스택에 마지막으로 남은 숫자를 리턴한다.

}
/*----------- 연산시 사용할 함수--------------------------------------- */
double push_eval(double t) // 연산 스택의 푸시
{
if (top_eval >= MAX - 1)
{
printf("\n Stack overflow.");
exit(1);
}
stack_eval[++top] = t;
return t;
}

double pop_eval(void) // 연산 스택의 팝
{
if (top_eval < 0)
{
printf("\n Stack underflow.");
exit(1);
}
return stack_eval[top--];
}

double change_value (char *num, int *index) // atof 함수
{
double value; // 임시저장 값
char temp[MAX]; // 임시 배열
int i,k;

for ( i=0 ; num[i] != ' ' ; i++ ) // 빈킨을 만날때 까지 배열을 검색
temp[i] = num[i]; // 임시 배열에 넣는다.
temp[i] ='\0';
value = atof (temp); //float값
k = *index;
*index = k+i; // eval함수에서 i(index)값 자체를 변환
return value; // 변환된 값을 리턴
}

precedence get_token (char *p) // 연산자 정의
{
switch ( *p )
{
case '(': return lparen;
case ')': return rparen;
case '+': return plus;
case '-': return minus;
case '*': return times;
case '/': return divide;
case '%': return mod;
case 's': return SIN;
case 'c': return COS;
case 't': return TAN;
case '\0': return eos;

default: return operand;
}
}
//----------------------------후위표기법으로의 변환시 사용할 함수--------------------------
void init_stack(void)
{
top = -1;
}

char push(char t)
{
if (top >= MAX - 1)
{
printf("\n Stack overflow.");
exit(1);
}
stack[++top] = t;
return t;
}

char pop(void)
{
if (top < 0)
{
printf("\n Stack underflow.");
exit(1);
}
return stack[top--];
}

char get_stack_top(void)
{
return (top < 0) ? -1 : stack[top];
}

char is_stack_empty(void)
{
return (top < 0);
}

int is_operator(int k)
{
return (k == '+' || k == '-' || k == '*' || k == '/');
}

int precedence_def(int op)
{
if (op == '(') return 0;
if (op == '+' || op == '-') return 1;
if (op == '*' || op == '/') return 2;
else return 3;
}

void postfix(char *dst, char *src) // 후위표기로의 변환
{
init_stack();
while (*src!='\0') // NULL까지 순환
{
if (*src == '(') // ( 만나면 푸시
{
push(*src);
src++;
}
else if (*src == ')')
{
while (get_stack_top() != '(') // 스택의 top이 '(' 아니냐?
{
*dst++ = pop(); // 아니면 연산자를 팝
*dst++ = ' '; // 빈킨을 만듬
}
pop();// '(' 이것을 지움
src++;
if ((get_stack_top() == 's') || (get_stack_top() == 'c') || (get_stack_top() == 't') )
{ // 괄호가 끝이난후 삼각함수의 연산자가 들어 있는지 검사
*dst++ = pop(); // true일경우 팝
*dst++ = ' ';
}
else;
}
else if (is_operator(*src)) // 연산자일 경우
{
if ((get_stack_top() == 's') || (get_stack_top() == 'c') || (get_stack_top() == 't') )
{// 스택의 탑이 삼각함수인지 검사. 이유 괄호다음의 우선순위는 삼각함수이다.
*dst++ = pop();
*dst++ = ' ';
}
while (!is_stack_empty() && precedence_def(get_stack_top()) >= precedence_def(*src))
{// 사칙연산의 우선순위를 정하는 루프
*dst++ = pop();
*dst++ = ' ';
}
push(*src);
src++;
}
else if (*src >= '0' && *src <= '9') // 숫자가 들어올경우
{
do
{
*dst++ = *src++; // 순자를 배열에 넣는다. 숫자가 아닌것이 나올떄 까지
} while ((*src >= '0' && *src <= '9') || *src == '.');
*dst++ = ' '; // 다한다음 빈공간을 넣는다.
}
else if ( *src == '.' )
*dst++ = *src++;
else if ( *src == 's' ) // sin을 만날경우 첫문자가 's'임으로 검사
{
push(*src);
src = src+3; // sin글씨 세게의 다음으로 이동
}
else if ( *src == 'c' )
{
push(*src);
src = src+3;
}
else if ( *src == 't' )
{
push(*src);
src = src+3;
}
else
src++; // 아무것도 경우에 없을경우는 다음으로
}

while (!is_stack_empty()) // 배열의 NULL까지 검사를 다한후 스택의 내용을 출력한다.
{
*dst++ = pop();
*dst++ = ' ';
}
dst--;
*dst = '\0'; // 후위표기법으로 바꾼 배열의 마지막에 MULL을 잊지 않는다.
}
2009/10/29 11:33 2009/10/29 11:33


태그 ,

(go to top)