postfix_calc.c

Download
c 258 lines 6.7 KB
  1// postfix_calc.c
  2// μŠ€νƒμ„ μ΄μš©ν•œ ν›„μœ„ ν‘œκΈ°λ²•(Postfix) 계산기
  3// μ€‘μœ„: (3 + 4) * 5  β†’  ν›„μœ„: 3 4 + 5 *
  4
  5#include <stdio.h>
  6#include <stdlib.h>
  7#include <ctype.h>
  8#include <string.h>
  9#include <stdbool.h>
 10
 11#define MAX_SIZE 100
 12
 13// μ‹€μˆ˜ν˜• μŠ€νƒ (계산 κ²°κ³Όκ°€ μ‹€μˆ˜μΌ 수 있음)
 14typedef struct {
 15    double data[MAX_SIZE];
 16    int top;
 17} Stack;
 18
 19// μŠ€νƒ μ΄ˆκΈ°ν™”
 20void stack_init(Stack *s) {
 21    s->top = -1;
 22}
 23
 24// λΉ„μ–΄μžˆλŠ”μ§€ 확인
 25bool stack_isEmpty(Stack *s) {
 26    return s->top == -1;
 27}
 28
 29// Push
 30void stack_push(Stack *s, double v) {
 31    if (s->top < MAX_SIZE - 1) {
 32        s->data[++s->top] = v;
 33    }
 34}
 35
 36// Pop
 37double stack_pop(Stack *s) {
 38    if (!stack_isEmpty(s)) {
 39        return s->data[s->top--];
 40    }
 41    return 0.0;
 42}
 43
 44// Peek
 45double stack_peek(Stack *s) {
 46    if (!stack_isEmpty(s)) {
 47        return s->data[s->top];
 48    }
 49    return 0.0;
 50}
 51
 52// μ—°μ‚°μžμΈμ§€ 확인
 53bool isOperator(char c) {
 54    return c == '+' || c == '-' || c == '*' || c == '/' || c == '%';
 55}
 56
 57// μ—°μ‚° μˆ˜ν–‰
 58double applyOperator(double a, double b, char op) {
 59    switch (op) {
 60        case '+': return a + b;
 61        case '-': return a - b;
 62        case '*': return a * b;
 63        case '/':
 64            if (b == 0) {
 65                printf("였λ₯˜: 0으둜 λ‚˜λˆŒ 수 μ—†μŠ΅λ‹ˆλ‹€!\n");
 66                return 0;
 67            }
 68            return a / b;
 69        case '%':
 70            if (b == 0) {
 71                printf("였λ₯˜: 0으둜 λ‚˜λˆŒ 수 μ—†μŠ΅λ‹ˆλ‹€!\n");
 72                return 0;
 73            }
 74            return (int)a % (int)b;
 75        default:
 76            printf("μ•Œ 수 μ—†λŠ” μ—°μ‚°μž: %c\n", op);
 77            return 0;
 78    }
 79}
 80
 81// ν›„μœ„ ν‘œκΈ°λ²• 계산
 82// 곡백으둜 κ΅¬λΆ„λœ 토큰 ν˜•μ‹: "3 4 + 5 *"
 83double evaluatePostfix(const char *expr) {
 84    Stack s;
 85    stack_init(&s);
 86
 87    // μž…λ ₯ λ¬Έμžμ—΄ 볡사 (strtok이 원본을 μˆ˜μ •ν•˜λ―€λ‘œ)
 88    char *str = strdup(expr);
 89    char *token = strtok(str, " ");
 90
 91    printf("계산 κ³Όμ •:\n");
 92
 93    while (token) {
 94        // μˆ«μžμΈμ§€ 확인 (μŒμˆ˜λ„ 처리)
 95        if (isdigit(token[0]) || (token[0] == '-' && strlen(token) > 1)) {
 96            double num = atof(token);
 97            stack_push(&s, num);
 98            printf("  숫자 %gλ₯Ό μŠ€νƒμ— push\n", num);
 99        }
100        // μ—°μ‚°μž
101        else if (isOperator(token[0]) && strlen(token) == 1) {
102            if (s.top < 1) {
103                printf("였λ₯˜: μ—°μ‚°μž '%c'λ₯Ό μ μš©ν•  ν”Όμ—°μ‚°μžκ°€ λΆ€μ‘±ν•©λ‹ˆλ‹€!\n", token[0]);
104                free(str);
105                return 0;
106            }
107
108            double b = stack_pop(&s);
109            double a = stack_pop(&s);
110            double result = applyOperator(a, b, token[0]);
111
112            printf("  μ—°μ‚°: %g %c %g = %g\n", a, token[0], b, result);
113            stack_push(&s, result);
114        }
115        else {
116            printf("였λ₯˜: 잘λͺ»λœ 토큰 '%s'\n", token);
117            free(str);
118            return 0;
119        }
120
121        token = strtok(NULL, " ");
122    }
123
124    free(str);
125
126    // μŠ€νƒμ— μ •ν™•νžˆ ν•˜λ‚˜μ˜ 결과만 남아야 함
127    if (s.top != 0) {
128        printf("였λ₯˜: 잘λͺ»λœ ν‘œκΈ°λ²• (μŠ€νƒμ— %d개의 값이 λ‚¨μŒ)\n", s.top + 1);
129        return 0;
130    }
131
132    return stack_pop(&s);
133}
134
135// μ—°μ‚°μž μš°μ„ μˆœμœ„ λ°˜ν™˜
136int precedence(char op) {
137    if (op == '+' || op == '-') return 1;
138    if (op == '*' || op == '/' || op == '%') return 2;
139    return 0;
140}
141
142// μ€‘μœ„ ν‘œκΈ°λ²•μ„ ν›„μœ„ ν‘œκΈ°λ²•μœΌλ‘œ λ³€ν™˜ (심화)
143// κ°„λ‹¨ν•œ κ΅¬ν˜„: κ΄„ν˜Έμ™€ μ—°μ‚°μž μš°μ„ μˆœμœ„ 처리
144void infixToPostfix(const char *infix, char *postfix) {
145    Stack s;
146    stack_init(&s);
147    int j = 0;
148
149    for (int i = 0; infix[i]; i++) {
150        char c = infix[i];
151
152        // 곡백 λ¬΄μ‹œ
153        if (c == ' ') continue;
154
155        // ν”Όμ—°μ‚°μž (μˆ«μžλ‚˜ λ³€μˆ˜)
156        if (isalnum(c)) {
157            postfix[j++] = c;
158            postfix[j++] = ' ';
159        }
160        // μ—¬λŠ” κ΄„ν˜Έ
161        else if (c == '(') {
162            stack_push(&s, c);
163        }
164        // λ‹«λŠ” κ΄„ν˜Έ
165        else if (c == ')') {
166            while (!stack_isEmpty(&s) && (char)stack_peek(&s) != '(') {
167                postfix[j++] = (char)stack_pop(&s);
168                postfix[j++] = ' ';
169            }
170            stack_pop(&s);  // '(' 제거
171        }
172        // μ—°μ‚°μž
173        else if (isOperator(c)) {
174            while (!stack_isEmpty(&s) &&
175                   precedence((char)stack_peek(&s)) >= precedence(c)) {
176                postfix[j++] = (char)stack_pop(&s);
177                postfix[j++] = ' ';
178            }
179            stack_push(&s, c);
180        }
181    }
182
183    // μŠ€νƒμ— 남은 μ—°μ‚°μž λͺ¨λ‘ 좜λ ₯
184    while (!stack_isEmpty(&s)) {
185        postfix[j++] = (char)stack_pop(&s);
186        postfix[j++] = ' ';
187    }
188
189    postfix[j] = '\0';
190}
191
192// ν…ŒμŠ€νŠΈ μ½”λ“œ
193int main(void) {
194    printf("=== ν›„μœ„ ν‘œκΈ°λ²• 계산기 ===\n\n");
195
196    // ν›„μœ„ ν‘œκΈ°λ²• 계산 ν…ŒμŠ€νŠΈ
197    const char *postfixExpressions[] = {
198        "3 4 +",                  // 3 + 4 = 7
199        "3 4 + 5 *",              // (3 + 4) * 5 = 35
200        "10 2 / 3 +",             // 10 / 2 + 3 = 8
201        "5 1 2 + 4 * + 3 -",      // 5 + ((1 + 2) * 4) - 3 = 14
202        "15 7 1 1 + - / 3 * 2 1 1 + + -",  // λ³΅μž‘ν•œ 식
203        "8 2 /",                  // 8 / 2 = 4
204        "9 3 % 2 *"               // (9 % 3) * 2 = 0
205    };
206
207    int n = sizeof(postfixExpressions) / sizeof(postfixExpressions[0]);
208
209    printf("[ ν›„μœ„ ν‘œκΈ°λ²• 계산 ]\n");
210    for (int i = 0; i < n; i++) {
211        printf("\n%d. Expression: %s\n", i + 1, postfixExpressions[i]);
212        double result = evaluatePostfix(postfixExpressions[i]);
213        printf("   μ΅œμ’… κ²°κ³Ό: %.2f\n", result);
214    }
215
216    // μ€‘μœ„ β†’ ν›„μœ„ λ³€ν™˜ ν…ŒμŠ€νŠΈ
217    printf("\n\n[ μ€‘μœ„ ν‘œκΈ°λ²• β†’ ν›„μœ„ ν‘œκΈ°λ²• λ³€ν™˜ ]\n");
218
219    const char *infixExpressions[] = {
220        "(3 + 4) * 5",
221        "a + b * c",
222        "(a + b) * (c - d)",
223        "a + b - c",
224        "a * b + c / d"
225    };
226
227    int m = sizeof(infixExpressions) / sizeof(infixExpressions[0]);
228
229    for (int i = 0; i < m; i++) {
230        char postfix[MAX_SIZE];
231        infixToPostfix(infixExpressions[i], postfix);
232        printf("\nμ€‘μœ„: %s\n", infixExpressions[i]);
233        printf("ν›„μœ„: %s\n", postfix);
234    }
235
236    // λŒ€ν™”ν˜• 계산기
237    printf("\n\n[ λŒ€ν™”ν˜• ν›„μœ„ 계산기 ]\n");
238    printf("ν›„μœ„ ν‘œκΈ°λ²•μœΌλ‘œ μˆ˜μ‹μ„ μž…λ ₯ν•˜μ„Έμš” (예: 3 4 +)\n");
239    printf("μ’…λ£Œν•˜λ €λ©΄ 'q'λ₯Ό μž…λ ₯ν•˜μ„Έμš”.\n\n");
240
241    char input[MAX_SIZE];
242    while (1) {
243        printf("> ");
244        if (!fgets(input, MAX_SIZE, stdin)) break;
245
246        // κ°œν–‰ 문자 제거
247        input[strcspn(input, "\n")] = 0;
248
249        if (strcmp(input, "q") == 0) break;
250
251        double result = evaluatePostfix(input);
252        printf("κ²°κ³Ό: %.2f\n\n", result);
253    }
254
255    printf("ν”„λ‘œκ·Έλž¨μ„ μ’…λ£Œν•©λ‹ˆλ‹€.\n");
256    return 0;
257}