#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

struct node {
	int item;
	struct node* llink;
	struct node* rlink;
};

struct node* avail = NULL;

void addq(struct node*, int);
void deleteq(struct node*);
void listprintf(struct node*);
void erase(struct node*, struct node*);

int main()
{
	struct node* head;
	int cond, item;


	// dummy-node 생성
	head = (struct node*)malloc(sizeof(struct node));
	if (head == NULL)
	{
		fprintf(stderr, "The memory is full\n");
		exit(1);
	}

	//Queue 초기화
	head->llink = head;
	head->rlink = head;
	/*head->item = 0;*/

	while (1)
	{
		printf("1:insert\t2:delete\t3:output\t4:exit\n");
		scanf("%d", &cond);
		if (cond == 1)
		{
			printf("Input Item\n");
			scanf("%d", &item);
			addq(head, item);
		}
		else if (cond == 2)
			deleteq(head);
		else if (cond == 3)
			listprintf(head);
		else if (cond == 4)
		{
			erase(head, avail);
			break;
		}

		else
		{
			printf("Wrong Input\n");
			exit(1);
		}
	}


	return 0;
}

void listprintf(struct node* ptr)
{
	struct node* init_position = ptr;
	ptr = ptr->rlink;
	printf("-----------list---------------\n");

	for (; init_position != ptr; ptr = ptr->rlink)
		printf("%4d", ptr->item);
	printf("\n");
}

void addq(struct node* ptr, int item)
{
	//struct node* l_ptr = ptr->llink;
	struct node* r_ptr = ptr->rlink;
	struct node* temp = NULL;

	if (avail)
	{
		temp = avail;
		avail = avail->rlink;
		/*temp->llink = NULL;
		temp->rlink = NULL;*/
	}
	else
		temp = (struct node*)malloc(sizeof(struct node));


	if (temp == NULL)
	{
		fprintf(stderr, "The memory is full\n");
		exit(1);
	}
	temp->item = item;

	temp->llink = ptr;
	temp->rlink = ptr->rlink;
	ptr->rlink->llink = temp;
	ptr->rlink = temp;

	/*temp->llink = ptr->llink;
	temp->rlink = ptr;
	ptr->llink = temp;
	if (ptr->rlink == ptr)
		ptr->rlink = temp;
	else
		l_ptr->rlink = temp;*/

}

void deleteq(struct node* ptr)
{
	//struct node* delete_node = ptr->rlink;
	struct node* delete_node = ptr->llink;
	if (ptr->llink == ptr)
	{
		printf("No Data\n");
		return;
	}
	else
	{
		delete_node->llink->rlink = delete_node->rlink;
		delete_node->rlink->llink = delete_node->llink;


		/*ptr->rlink = delete_node->rlink;
		if (ptr->llink == delete_node)
			ptr->llink = ptr;
		else
			delete_node->rlink->llink = ptr;*/

	}

	printf("deleted data: %d\n", delete_node->item);
	delete_node->llink = NULL;
	delete_node->rlink = NULL;
	if (avail)
		delete_node->rlink = avail;
	else
		avail = delete_node;
}

void erase(struct node* head, struct node* avail)
{
	printf("실행");
	struct node* temp;
	while (head != (head->rlink))
		deleteq(head);

	while (avail != NULL)
	{
		temp = avail;
		avail = avail->rlink;
		free(avail);
	}

	free(head);

}

1. 원본 

// 중위표기법을 후위 표기법으로 변환
// 두 자리수 이상, 소수점 이하 까지 가능
// 음수 , sin , cos , tan 가능
#define _CRT_SECURE_NO_WARNINGS
#define PI 3.14159265358979323846
#define MAX 100
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<math.h>

// enum 안의 배열 값을 precedence로 치환 (struct)
typedef enum { lparen, rparen, plus, minus, times, divide, mod, eos, Sin, Cos, Tan, space, operand } precedence;

// isp = instack precedence, icp = incoming precedence
int isp[] = { 0, 19, 12, 12, 13, 13, 13, 0, 0, 0, 0 };  // 스택에 있는 값의 우선순위
int icp[] = { 20, 19, 12, 12, 13, 13, 13, 0, 20, 20, 20 }; // 스택에 들어가는 값의 우선순위 
 
double stack[MAX]; // 스택을 정의
int top;        // top포인터 정의



// 함수원형
void change_postfix(char*, char*); // 후위표현 변환 함수
precedence get_token(char*); // precedence의 형태의 값을 리턴하는 함수
char print_token(precedence); // precedence의값을 입력 받아서 문자를 리턴하는 함수
void init_stack(void); // stack을 초기화 하는 함수
void push(double); // push 하는 함수
double pop(void); // pop하는 함수
double eval(char* post); // 입력 값을 계산하는 함수
int sin_cos_tan(char* ptr); // sin, cos, tan 문자 판별 함수 



// Main 함수
void main()
{
    char infix[MAX] = "-10*-cos(--sin(--45--45)/2-sin(30))";
    char postfix[MAX] = { 0 };  //후위표기법을 저장하는 배열
    double result;
    int i;
    printf("수식을 입력하여주세요 : ");
    gets(infix); // 중위 표기법으로 입력

    change_postfix(infix, postfix); // 중위 표기법을 후위 표기법으로 바꾸는 함수 

    // 출력
    printf("중위표기법 : %s\n", infix);

    for (i = 0; postfix[i] != '\0'; i++)
    {
        if (postfix[i] == '$' || postfix[i] == '@' || postfix[i] == '#')
            printf(")");
        else
            printf("%c", postfix[i]);
    }
    printf("\n");

    result = eval(postfix); // result = 후위표기법으로 계산한 값
    printf("%s = %f\n", infix, result); // 좌변은 수식, 우변은 결과값
}



// 후위 표기법으로 변환된 수식을 이용하여 값을 계산하는 함수//////
double eval(char* post)
{
    char t[MAX];
    precedence token;
    double temp;
    int i = 0, j = 0, cnt_operand = 0, cnt_operator = 0;

    init_stack();  // 스택 초기화
    while ((token = get_token(post)) != eos)
    {
        if (token == space && i > 0) // 공백을 만나면 token을 실수형으로 변환
        {
            t[i] = '\0';
            temp = atof(t);
            push(temp);
            cnt_operand++;
            i = 0;
        }
        // 문자가 아니고 operand이거나 '-'이면서 다음에 operand이면 실행
        else if ((!isalpha(*post) && operand == token) || (token == minus && get_token(post + 1) == operand))
            t[i++] = *post;

        else   // operator이면 switch문 실행
        {
            if (!(token >= Sin && token <= space) && !isalpha(*post) && token != lparen)
                cnt_operator++;
            switch (token)
            {
            case Sin: push(sin(pop() * PI / 180));
                break;
            case Cos: push(cos(pop() * PI / 180));
                break;
            case Tan: push(tan(pop() * PI / 180));
                break;
            case plus: push(pop() + pop());
                break;
            case minus: temp = pop();
                push(pop() - temp);
                break;
            case times: push(pop() * pop());
                break;
            case divide: if ((temp = pop()) != 0);
                push(pop() / temp);
                break;
            case mod: temp = pop();
                push((int)pop() % (int)temp);
                break;
            }
        }
        post++;
    }

    if (cnt_operand - cnt_operator != 1)
    {
        puts("에러!!!!!!!!!!.   수식이 맞지 않습니다.");
        exit(1);
    }
    return pop();
}


// 중위표기법을 후위표기법으로 변환 시키는 함수
void change_postfix(char* str, char* postfix)
{
    int i = 0, j = 0, flag = 0, count = 0, s_c_t;
    precedence token;

    init_stack(); // 스택 초기화
    push(eos);    // 우선순위가 가장 낮은 '\0'를 삽입
    while ((token = get_token(str + i)) != eos) // str이 널값이면 변환 중지
    {
        if (token == operand) // operand이면 postfix에 바로 삽입
        {
            if (s_c_t = sin_cos_tan(str + i))
            {
                if (count % 2)  // -1 = (0-1) 이기때문에 ==>  0 1 - 로 표현
                {
                    strncat(postfix + j, "0 ", 2);  // operand 뒤에 공백 삽입
                    j += 2;
                    push(minus);
                    // push(token);
                    count = 0;
                }
                strncat(postfix + j, s_c_t == Sin ? "sin" : s_c_t == Cos ? "cos" : "tan", 3);
                push(s_c_t);
                if (lparen == get_token(str + i + 3))
                {
                    strncat(postfix + j, "( ", 2);
                    i++;
                    j += 2;
                }
                j += 3;
                i += 3;
                continue;
            }
            else if (count && count % 2)
            {
                *(postfix + j++) = '-';
                count = 0;
            }
            *(postfix + j++) = *(str + i);
            flag = 1;     // operand가 실행 되었다는것을 표시
        }
        else if (token == lparen && count % 2)

        {
            strncat(postfix + j, "0 ", 2);  // operand 뒤에 공백 삽입
            j += 2;
            push(minus);
            push(token);
            count = 0;
        }

        // 음수 판별 조건 : token은 '-' 이고, operand 또는(or)     ')' 바로 뒤에 '-'는 뺄셈 부호임
        // 따라서 operand가 선행 안되면서(and),   ')'가 이전에 없으면 '-'는 부호 표시 기호이다.
        else if (token == minus && !flag && get_token(str + i - 1) != rparen)
            count++;
        else
        {
            if (flag) // operand와 구분 시켜 주기위해 공백 삽입, flag가 1이면 operand가 삽입 되었단 말임
            {
                *(postfix + j++) = ' ';
                flag = 0;
            }
            if (token == rparen) // token이 ')'이면 '('이 나올때까지 postfix에 삽입
            {
                while ((token = (int)pop()) != lparen && !(token >= Sin && token <= Tan))
                {
                    *(postfix + j++) = ' ';
                    *(postfix + j++) = print_token(token);
                    *(postfix + j++) = ' ';
                }
                if (token != lparen)  // sin => $ , cos => @ , tan => # 기호 삽입
                {
                    *(postfix + j++) = print_token(token);
                    *(postfix + j++) = ' ';
                }
            }

            else
            {   // token값이 stack[top]값보다 우선순위가 높을때까지 postfix에 삽입
                while (icp[token] <= isp[(int)stack[top]])
                {
                    *(postfix + j++) = ' ';
                    *(postfix + j++) = print_token((int)pop());
                    *(postfix + j++) = ' ';
                }
                push(token); // 마지막에 token값을 푸쉬
            }
        }
        i++;
    }

    *(postfix + j++) = ' ';  // operand와 구분 시켜 주기위해 공백 삽입 

    while ((token = (int)pop()) != eos)   // 스택에 남은 값들을 postfix에 삽입
        *(postfix + j++) = print_token(token);
    *(postfix + j) = '\0'; // postfix 맨마지막에 null 삽입
}


// sin, cos, tan 문자 판별 함수
precedence sin_cos_tan(char* ptr)
{
    if (!strncmp(ptr, "sin", 3))
        return Sin;
    if (!strncmp(ptr, "cos", 3))
        return Cos;
    if (!strncmp(ptr, "tan", 3))
        return Tan;
    return 0;
}



// precedence의 형태의 값을 리턴하는 함수
precedence get_token(char* symbol)
{
    switch (*symbol)
    {
    case '(': return lparen;
    case ')': return rparen;
    case '+': return plus;
    case '-': return minus;
    case '*': return times;
    case '/': return divide;
    case '%': return mod;
    case '\0': return eos;
    case ' ': return space;
    case '$': return Sin;
    case '@': return Cos;
    case '#': return Tan;
    default: return operand;
    }
}



// precedence의값을 입력 받아서 문자를 리턴하는 함수
char print_token(precedence token)
{
    switch (token)
    {
    case plus: return '+';
    case minus: return '-';
    case times: return '*';
    case divide: return '/';
    case mod: return '%';
    case Sin: return '$';
    case Cos: return '@';
    case Tan: return '#';
    default: return '\0';
    }
}



// 스택 초기화 함수
void init_stack(void)
{
    top = -1;
}



//스택에 푸쉬 하는 함수

void push(double in)
{
    if (top >= MAX - 1)
    {
        puts("Stack is Full !!!!!!!!!!!");
        exit(1);
    }
    stack[++top] = in;
}



// 스택에서 팝하는 함수
double pop(void)
{
    if (top < 0)
    {
        puts("Stack is Empty !!!!!!!!!!!");
        exit(1);
    }
    return stack[top--];
}

결과 값

2. 변형 (sin,cos,tan 빼고 pi등 뺀 것.) (두 자리 이상과 마이너스만 살림)

#define _CRT_SECURE_NO_WARNINGS
#define MAX 100
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>

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

static int icp[] = { 20, 19, 12, 12, 13, 13, 13, 0 };
static int isp[] = { 0, 19, 12, 12, 13, 13, 13, 0 };

double stack[MAX];
int top;

// 함수 원형
void change_postfix(char*, char*);
precedence get_token(char*);
char print_token(precedence);
void init_stack(void);
void push(double);
double pop(void);
double eval(char* post);


void main()
{
    char infix[MAX] = { 0 };
    char postfix[MAX] = { 0 };
    double result;
    int i;
    printf("수식을 입력하여 주세요 : ");
    gets(infix);

    change_postfix(infix, postfix);

    printf("중위표기법 : %s\n", infix);

    for (i = 0; postfix[i] != '\0'; i++)
    {
        printf("%c", postfix[i]);
    }
    printf("\n");

    result = eval(postfix);
    printf("%s = %f\n", infix, result);
}
double eval(char* post)
{
    char t[MAX];
    precedence token;
    double temp;
    int i = 0, j = 0, cnt_operand = 0, cnt_operator = 0;

    init_stack();  // 스택 초기화
    while ((token = get_token(post)) != eos)
    {
        if (token == space && i > 0) // 공백을 만나면 token을 실수형으로 변환
        {
            t[i] = '\0';
            temp = atof(t);
            push(temp);
            cnt_operand++;
            i = 0;
        }
        // 문자가 아니고 operand이거나 '-'이면서 다음에 operand이면 실행
        else if ((!isalpha(*post) && operand == token) || (token == minus && get_token(post + 1) == operand))
            t[i++] = *post;

        else   // operator이면 switch문 실행
        {
            if (token <= space && !isalpha(*post) && token != lparen)
            {
                cnt_operator++;
                switch (token)
                {
                case plus: push(pop() + pop());
                    break;
                case minus: temp = pop();
                    push(pop() - temp);
                    break;
                case times: push(pop() * pop());
                    break;
                case divide: if ((temp = pop()) != 0);
                    push(pop() / temp);
                    break;
                case mod: temp = pop();
                    push((int)pop() % (int)temp);
                    break;
                }
            }
        }
        post++;
    }

    return pop();
}


void change_postfix(char* str, char* postfix)
{
    int i = 0, j = 0, flag = 0, count = 0;
    precedence token;

    init_stack();
    push(eos);
    while ((token = get_token(str + i)) != eos)
    {
        if (token == operand)
        {
            if (count && count % 2)
            {
                *(postfix + j++) = '-';
                count = 0;
            }
            *(postfix + j++) = *(str + i);
            flag = 1;
        }
        else if (token == lparen && count % 2)
        {
            strncat(postfix + j, "0", 2);
            j += 2;
            push(minus);
            push(token);
            count = 0;
        }
        else if (token == minus && !flag && get_token(str + i - 1) != rparen)
            count++;
        else
        {
            if (flag)
            {
                *(postfix + j++) = ' ';
                flag = 0;
            }
            if (token == rparen)
            {
                while ((token = (int)pop()) != lparen)
                {
                    *(postfix + j++) = ' ';
                    *(postfix + j++) = print_token(token);
                    *(postfix + j++) = ' ';
                }
                if (token != lparen)
                {
                    *(postfix + j++) = print_token(token);
                    *(postfix + j++) = ' ';
                }
            }
            else
            {
                while (icp[token] <= isp[(int)stack[top]])
                {
                    *(postfix + j++) = ' ';
                    *(postfix + j++) = print_token((int)pop());
                    *(postfix + j++) = ' ';
                }
                push(token);
            }
        }
        i++;
    }
    *(postfix + j++) = ' ';

    while ((token = (int)pop()) != eos)
        *(postfix + j++) = print_token(token);
    *(postfix + j) = '\0';
}

precedence get_token(char* symbol)
{
    switch (*symbol)
    {
    case '(': return lparen;
    case ')': return rparen;
    case '+': return plus;
    case '-': return minus;
    case '*': return times;
    case '/': return divide;
    case '%': return mod;
    case '\0': return eos;
    case ' ': return space;
    default: return operand;
    }
}

char print_token(precedence token)
{
    switch (token)
    {
    case plus: return '+';
    case minus: return '-';
    case times: return '*';
    case divide: return '/';
    case mod: return '%';
    default: return '\0';
    }
}

void init_stack(void)
{
    top = -1;
}

void push(double in)
{
    if (top >= MAX - 1)
    {
        puts("Stack is Full!!!");
        exit(1);
    }
    stack[++top] = in;
}

double pop(void)
{
    if (top < 0)
    {
        puts("Stack is Empty!!!!");
        exit(1);
    }
    return stack[top--];
}

-10*-(-10*(-10--20)) = -1000

다른거는 되는데 , 위에거 안됨

*- 붙어있는 걸 처리 못하는 듯.

 이것처럼 되어야 하는데..

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>

#define NUM 1
#define CHARCT 2


int numcmp(const char*, const char*); // 함수 numcmp 선언
void fcmp(int(**p)(const char *, const char *), char*, char*);// 함수 fcmp 선언

int main()
{
    char s[80], t[80];
    int (*ptr)(const char*, const char*);    // 변수 ptr 선언

    scanf_s("%s %s", s, t);
    fcmp(&ptr, s, t);   // 함수 fcmp 콜
        printf("%d\n", ptr(s, t));
    return 0;
}

//--------------- 함수 numcmp 정의 ---------------------
int numcmp(const char* ps, const char* pt)
{
    float a, b;

    a = atof(ps);
    b = atof(pt);

    if (a > b)
        return 1;
    else if (a < b)
        return -1;
    else
        return 0;
}


// --------------- 함수 fcmp 정의 ---------------------
void fcmp(int(**p)(const char*, const char*), char* ps, char* pt)
{
    int cond;

    cond = NUM;

    if (*ps == '-')
        ps++;
    while (cond == NUM && *ps != NULL)
        if (isdigit(*ps) || *ps == '.')
            ps++;
        else
            cond = CHARCT;

    if (*pt == '-')
        pt++;
    while (cond == NUM && *pt != NULL)
        if (isdigit(*pt) || *pt == '.')
            pt++;
        else
            cond = CHARCT;

    if (cond == NUM)
        *p = numcmp;
    else
        *p = strcmp;
}

유의사항 

1 . scanf_s 는 visual studio 전용 코드이므로 웬만하면 scanf를 사용할 것.

2. scanf를 사용할 때는  #include 보다 위에 #define _CRT_SECURE_NO_WARNINGS 넣어서 사용할 것.

3. 이번 코드에는 중괄호 {}가 생략 되었는데, 아주 끔찍한 코드라고함...(개발자커뮤니티에서)

앞으로는 { } 꼬박꼬박 넣으며 작성할 것.

+ Recent posts