Загрузка данных


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

// ======================== СТЕК (односвязный список) ========================

// Стек для операторов (char)
typedef struct Node {
    char data;
    struct Node* next;
} Node;

Node* topOp = NULL;

void pushOp(char x) {
    Node* n = (Node*)malloc(sizeof(Node));
    n->data = x;
    n->next = topOp;
    topOp = n;
}

char popOp() {
    if (!topOp) return '\0';
    Node* t = topOp;
    char val = t->data;
    topOp = topOp->next;
    free(t);
    return val;
}

char peekOp() {
    return topOp ? topOp->data : '\0';
}

// Стек для чисел (double)
typedef struct DNode {
    double data;
    struct DNode* next;
} DNode;

DNode* topNum = NULL;

void pushNum(double x) {
    DNode* n = (DNode*)malloc(sizeof(DNode));
    n->data = x;
    n->next = topNum;
    topNum = n;
}

double popNum() {
    if (!topNum) return 0;
    DNode* t = topNum;
    double val = t->data;
    topNum = topNum->next;
    free(t);
    return val;
}

void printStack() {                 // пошаговый вывод
    DNode* p = topNum;
    printf("[ ");
    while (p) {
        printf("%.2f ", p->data);
        p = p->next;
    }
    printf("]\n");
}

// Приоритет
int prio(char op) {
    if (op == '+' || op == '-') return 1;
    if (op == '*' || op == '/') return 2;
    return 0;
}

// ======================== ИНФИКС → ОПЗ ========================
void infixToPostfix(char* infix, char* postfix) {
    int i = 0, j = 0;
    postfix[0] = '\0';

    while (infix[i]) {
        if (isspace(infix[i])) { i++; continue; }

        if (isdigit(infix[i])) {
            while (isdigit(infix[i]))
                postfix[j++] = infix[i++];
            postfix[j++] = ' ';
            continue;
        }

        if (infix[i] == '(') {
            pushOp('(');
        }
        else if (infix[i] == ')') {
            while (peekOp() != '(' && peekOp() != '\0') {
                postfix[j++] = popOp();
                postfix[j++] = ' ';
            }
            popOp(); // убираем '('
        }
        else if (strchr("+-*/", infix[i])) {
            while (prio(peekOp()) >= prio(infix[i]) && peekOp() != '(') {
                postfix[j++] = popOp();
                postfix[j++] = ' ';
            }
            pushOp(infix[i]);
        }
        i++;
    }

    while (peekOp() != '\0') {
        postfix[j++] = popOp();
        postfix[j++] = ' ';
    }
    postfix[j] = '\0';
}

// ======================== ВЫЧИСЛЕНИЕ ОПЗ ========================
double evaluatePostfix(char* postfix) {
    char* token = strtok(postfix, " ");
    
    printf("Пошаговое вычисление:\n");
    
    while (token) {
        if (isdigit(token[0])) {
            pushNum(atof(token));
            printf("push %.2f → ", atof(token));
            printStack();
        }
        else {
            double b = popNum();
            double a = popNum();
            double res = 0;
            
            switch(token[0]) {
                case '+': res = a + b; break;
                case '-': res = a - b; break;
                case '*': res = a * b; break;
                case '/': 
                    if (b == 0) { printf("Деление на ноль!\n"); return 0; }
                    res = a / b; 
                    break;
            }
            pushNum(res);
            printf("%c → ", token[0]);
            printStack();
        }
        token = strtok(NULL, " ");
    }
    return popNum();
}

// ======================== MAIN ========================
int main() {
    char expr[256];
    char postfix[512];
    
    printf("Введите выражение: ");
    fgets(expr, sizeof(expr), stdin);
    
    infixToPostfix(expr, postfix);
    
    printf("\nИсходное: %s", expr);
    printf("ОПЗ: %s\n", postfix);
    
    double result = evaluatePostfix(postfix);
    
    printf("Результат = %.2f\n", result);
    
    return 0;
}