-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path2.7.c
More file actions
108 lines (99 loc) · 2.93 KB
/
2.7.c
File metadata and controls
108 lines (99 loc) · 2.93 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>
#include <ctype.h>
jmp_buf begin; // точка начала диалога с пользователем
char curlex; // текущий символ
char *input; // указатель на строку ввода
int pos; // текущая позиция в строке
// функции разбора
void getlex(void);
int expr(void); // сложение и вычитание
int add(void); // умножение и деление
int mult(void); // возведение в степень
int atom(void); // цифра или скобки
void error(void);
// получение следующего символа
void getlex() {
while (input[pos] == ' ' || input[pos] == '\t') pos++; // пропуск пробелов
curlex = input[pos]; // текущий символ
}
// ошибка
void error(void) {
printf("\nОШИБКА!\n");
longjmp(begin, 1);
}
// expr: сложение и вычитание (левоассоциативно)
int expr() {
int e = add();
while (curlex == '+' || curlex == '-') {
char op = curlex;
pos++;
getlex();
int right = add();
if (op == '+') e += right;
else e -= right;
}
return e;
}
// add: умножение и деление (левоассоциативно)
int add() {
int a = mult();
while (curlex == '*' || curlex == '/') {
char op = curlex;
pos++;
getlex();
int right = mult();
if (op == '*') a *= right;
else {
if (right == 0) error(); // деление на ноль
a /= right;
}
}
return a;
}
// mult: возведение в степень (правоассоциативно)
int mult() {
int val = atom();
if (curlex == '^') {
pos++;
getlex();
int exp = mult(); // рекурсивный вызов для праваассоциативности
if (exp < 0) error(); // отрицательная степень
int base = val;
val = 1;
for (int i = 0; i < exp; i++) val *= base;
}
return val;
}
// atom: цифра или '(' expr ')'
int atom() {
int val = 0;
if (curlex >= '0' && curlex <= '9') {
val = curlex - '0';
pos++;
getlex();
} else if (curlex == '(') {
pos++;
getlex();
val = expr();
if (curlex != ')') error();
pos++;
getlex();
} else error();
return val;
}
// главный цикл программы
int main() {
char buf[256];
while (fgets(buf, sizeof(buf), stdin)) {
input = buf;
pos = 0;
if (setjmp(begin)) continue; // при ошибке возвращаемся сюда
getlex();
int result = expr();
if (curlex != '\n' && curlex != '\0') error();
printf("%d\n", result);
}
return 0;
}