c_programming_language/exercices/functions/par_4_3.c
2026-02-09 23:19:28 +03:00

132 lines
3.3 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#define MAXOP 100 // Максимальный размер операдна (цифры) или оператора
#define MAXVAL 100 // Максимальный размер стека (глубина)
#define NUMBER '0' // Признак числа
#define BUFSIZE 100
int getop(char[]);
void push(double);
double pop(void);
int getch(void);
void ungetch(int);
int sp = 0; /* Следующая свободная позиция в стеке */
int bufp = 0; /* след, свободная позиция в буфере */
double val[MAXVAL]; /* stack */
char buf[BUFSIZE]; /* буфер для ungetch */
int getch(void) /* взять (возможно возвращенный) символ */
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int с) /* вернуть символ на ввод */
{
if (bufp >= BUFSIZE)
printf("ungetch: слишком много символов\n");
else
buf[bufp++] = с;
}
void push(double f) {
if (sp < MAXVAL) {
val[++sp] = f;
}
else {
printf("Stack maximum depth reached: %c", MAXVAL);
}
}
double pop(void) {
if (sp > 0) {
return val[--sp];
} else {
printf("Stack is empty. Returning 0.0");
return 0.0;
}
}
/**
* @brief Функция получения следующего оператора или операнда
*
* @param s массив символов для оценки
*/
int getop(char s[]) {
int i, c;
while ((s[0] = c = getch()) == ' ' || c == '\t')
;
s[1] = '\0';
if (!isdigit(c) && c != '.')
return c;
i = 0;
/* Накапливаем целую часть */
if (isdigit(c))
while (isdigit(s[++i] = c = getch()))
;
/* Накапливаем дробную часть */
if (c == '.')
while (isdigit(s[++i] = c = getch()))
s[i] = '\0';
if (c != EOF)
ungetch(c);
return NUMBER;
}
int main() {
int type;
double pop2;
char s[MAXOP];
while ((type = getop(s)) != EOF) {
switch (type) {
case NUMBER:
push(atof(s));
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
/*
* Тут сначала извлекаем верхний операнд, из которого надо
* вычитать. В отличии от `+`, `*` для `-` и `/` порядок операндов
* важен.
*
* ----------
* -
* 10
* 20
* ...
* ----------
*
* Чтобы сделать вычитание - надо из 20 вычесть 10 - получается
* излекам со стека 10, затем 20 и делаем вычитание
*/
pop2 = pop();
push(pop() - pop2);
break;
case '/':
/*
* Тут примерно то-же самое, только еще надо сделать проверку
* на ноль
*/
pop2 = pop();
if (pop2 != 0.0)
push(pop() / pop2);
else
printf("Error: Division by zero\n");
break;
case '\n':
printf("\t%.g\n", pop());
break;
default:
printf("Error: Unknown operation %s\n", s);
break;
}
}
}