Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
1 / 1 / 0
Регистрация: 18.02.2016
Сообщений: 71

Как разобрать арифметическое выражение?

09.10.2018, 17:52. Показов 1182. Ответов 9
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Мне сначала надо найти знак равенства, потом пройтись по левой и правой части.
C#
1
List<string> list = new List<string>() { "test1", "=", "test3", "+", "test5",  "*",  "test7", "-", "test8"  "*"  "test9" };
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
09.10.2018, 17:52
Ответы с готовыми решениями:

Добавить числа в скобочное выражение, чтобы получилось правильное арифметическое выражение
1.Дана последовательность из N круглых, квадратных и фигурных скобок. Выяснить, можно ли добавить в неё цифры и знаки арифметических...

Разобрать в ПОЛИЗ логическое выражение
Предположим у нас есть логическое выражение типа Con(A \bigcup B)\bigcap Dil(!A). И его надо решить. Для решения я выбрал разбор...

Разобрать логическое выражение и составить таблицу истинности
Собственно начался новый учебный год а с ним и новые трудности; Вчера с фразой &quot;Так как по идее вы должны уже идеально знать 2...

9
 Аватар для PoPsa85
814 / 561 / 240
Регистрация: 01.07.2018
Сообщений: 1,818
09.10.2018, 18:01
ivret, А причем тут этот лист ?
0
1 / 1 / 0
Регистрация: 18.02.2016
Сообщений: 71
09.10.2018, 18:11  [ТС]
Цитата Сообщение от PoPsa85 Посмотреть сообщение
ivret, А причем тут этот лист ?
Таблица лексем.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,111
Записей в блоге: 2
09.10.2018, 18:28
Цитата Сообщение от ivret Посмотреть сообщение
Мне сначала надо найти знак равенства, потом пройтись по левой и правой части.
Для начала маленький совет. Объявляйте массив лексем в порядке приоритета таким образом:
C#
1
2
3
4
5
6
7
8
        public List<string> list  = @"
=
( )
* /
- +
sin cos
"           .Split(new char[] { '\r', '\n', ' '}, StringSplitOptions.RemoveEmptyEntries)
            .ToList();
Нагляднее. Меньше путаницы будет.

Второе, собственно разбор у Вас состоит из деления на две части выражение по знаку равенства. Здесь надо проверять на корректность: знак должен быть только один.
И потом обе стороны разбирать.

Здесь уже надо более определённо. А что за разбор? Для чего? По каким правилам? И т.д и т.п.
1
1 / 1 / 0
Регистрация: 18.02.2016
Сообщений: 71
09.10.2018, 18:46  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Здесь уже надо более определённо. А что за разбор? Для чего? По каким правилам? И т.д и т.п.
Задание у меня такое.

На вход программы подается текстовый файл (с именем INPUT.TXT), содержащий единственную строку сим- волов. Данная строка задает присваивание переменной значения арифметического выражения в виде
ПЕРЕМЕННАЯ = ВЫРАЖЕНИЕ. Выражение может включать:
– знаки сложения и умножения («+» и «*»);
– круглые скобки («(» и «)»);
8
– константы (например, 5; 3.8; 1e+18, 8.41E-10);
– имена переменных.
Имя переменной — это последовательность букв и цифр,
начинающаяся с буквы. Входное выражение считать правильным. Программа должна с помощью регулярного выражения построить дерево, соответствующее заданному во входном файле выражению, и выдать (в текстовый файл OUTPUT.TXT) для дан-
ного выражения:
1) таблицу имен;
2) неоптимизированный код; 3) оптимизированный код.

В методичке сказано.

Рекурсивный алгоритм построения дерева:
1. На входе алгоритма имеем некоторый узел дерева node и
строку с частью математического выражения expr.
2. Ищем в строке знаки операций, не заключенные в скобки, в порядке приоритета. Наименьший приоритет у присваи- вания («=»), средний у сложения («+»), наивысший —
у умножения («*»).
3. Если знак операции найден в позиции pos строки expr,
то записываем его в поле oper узла дерева node. Далее два раза вызываем рекурсивно данный алгоритм — сна- чала для левого поддерева node.left и для подстроки строки expr, расположенной слева от позиции pos, и за- тем для правого поддерева node.right и для подстроки строки expr, расположенной справа от позиции pos.
4. Если знак не найден, то:
4.1. Если при этом первым символом строки expr явля- ется открывающая скобка «(», а последним — закрываю- щая «)», то удалить их и вернуться на шаг 2.
4.2. В противном случае имеем лист дерева. Записываем в поле oper узла дерева node все выражение expr — оно содержит либо идентификатор, либо константу. Указате- ли node.left и node.right обнулить.
Для начала работы алгоритма запускаем его, передавая на вход указатель root и строку, содержащую исходное выраже- ние. В качестве примера возьмем выражение
COST = (PRICE+TAX)*0.98.

Рекурсивный алгоритм построения дерева:
1. На входе алгоритма имеем некоторый узел дерева node и
строку с частью математического выражения expr.
2. Ищем в строке знаки операций, не заключенные в скобки, в порядке приоритета. Наименьший приоритет у присваи- вания («=»), средний у сложения («+»), наивысший —
у умножения («*»).
3. Если знак операции найден в позиции pos строки expr,
то записываем его в поле oper узла дерева node. Далее два раза вызываем рекурсивно данный алгоритм — сна- чала для левого поддерева node.left и для подстроки строки expr, расположенной слева от позиции pos, и за- тем для правого поддерева node.right и для подстроки строки expr, расположенной справа от позиции pos.
4. Если знак не найден, то:
4.1. Если при этом первым символом строки expr явля- ется открывающая скобка «(», а последним — закрываю- щая «)», то удалить их и вернуться на шаг 2.
4.2. В противном случае имеем лист дерева. Записываем в поле oper узла дерева node все выражение expr — оно содержит либо идентификатор, либо константу. Указате- ли node.left и node.right обнулить.
Для начала работы алгоритма запускаем его, передавая на вход указатель root и строку, содержащую исходное выраже- ние. В качестве примера возьмем выражение
COST = (PRICE+TAX)*0.98.


Есть пример на Паскале. Только сама рекурсивная функция построения дерева из строки.

Pascal
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
Program ex;
Type setChar=set of char; {тип «множество символов»}
str80=string[80]; 
рТор=^Top; {тип «строка длиной 80 символов»} {тип «указатель на вершину»}
Top=record 
operator1:string[5]; 
value:single; 
left,right:рТор; {тип «вершина»} {знак операции}{значение константы}{указатели на левое и правое поддерево}
end;
Var st:str80; Root:рТор;{строка - запись выражения} {корень дерева выражения}
кеу:boolean; {признак существования значения в заданной точке} 
x,xn,xe,dx,y:single; {начальное, конечное значения и шаг
аргумента, значение аргумента и функции} 
n,i:word; {количество точек и номер текущей точки}
 
{рекурсивная функция конструирования поддерева выражения с корнем г из строки st}
 
Procedure Constr_Tree(r:рТор;st:str80);
Var next:рТор; SetOp:setChar; c,po,code:integer; stl,stri:str80; с:single;
Function PosOp(st:str80;SetOp:setChar):byte; Var i,j,k,p:byte;
begin j:=0;k:=0;p:=0;i:=1;
while (7<= length(st)) and (p=0) do begin
if st[i]= '(' then inc(j) {считаем количество открывающихся скобок}
else if st[i]=')' then inc(k) {считаем количество закрывающихся скобок}
else if (j=k) and (st[i] in SetOp) then p:=i; inc(i);
end; PosOp:=p;
end;
{раздел операторов функции конструирования дерева выражения} 
Begin
po:=PosOp(st,['+','-']); {ищем разделительный знак операции + или -} 
if po=0 then po:=PosOp(st,['*']); {ищем разделительный знак
операции * или /} 
if po=0 then po:=PosOp(st,['^']);{ищем разделительный знак операции '^}
if po<>0 then 
begin
{разделяющий знак найден}
{записываем знак операции в вершину} {копируем подстроку первого операнда}
r^.operator1:=st[po];
stl:=copy(st,1,po-1);
if (stl[1]='(') and (PosOp(st,['*', '/', '+', '-', '^'])=0)
then
stl:=copy(stl,2,length(stl)-2); {убираем скобки} 
stri:=copy(st,po+1, length(st)-po);  {копируем подстроку второго опе*
ранда}
if(stri[1]= '(') and (PosOp(st,['*'])=0) then
stri:=copy(stri,2,length(stri)-po); {убираем скобки}
new(r^.left);
Constr_Tree(r^.left,stl);
new(r^.right);
Constr_Tree(r^.right,stri); {конструируем правый операнд}
end else
if st[1]= 'х' then {аргумент} 
begin
r^.operator1:= 'x\';
r^.left:=nil;
r^.right:=nil; 
end
else begin
val(st,c,code); if code=0 then
{пытаемся получить число} {константа}
begin 
r^.operator1:='0'; 
r^.left:=nil; 
r^.right:=nil;
r^.Value:=c;
end
else {функция}
begin po:=Pos('(', st);
r^.operator1:=copy(st,1,po-1); {выделяем имя функции} 
r^.right:=nil;
stl:=copy(st,po+1,length(st)-po-1); {вьШеляем подстроку}
new(r^.left);
Constr_Tree(r^.left,stl);
 end;
end; 
end;
Я пытаюсь применить его на своём примере. По таблице лексем ищу знак с наименьшим приоритетом это знак равно, потом тоже самое нужно сделать с левым и правыми частями таблицы.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,111
Записей в блоге: 2
09.10.2018, 19:28
Цитата Сообщение от ivret Посмотреть сообщение
строка задает присваивание переменной значения арифметического выражения в виде
ПЕРЕМЕННАЯ = ВЫРАЖЕНИЕ. Выражение может включать:
Ваше задание значительно отличается от начально-предоставленной Вами информации.

Надо сначала проверить полученное выражение на корректность. Сформировать из левой части имя переменной. А арифметический анализ проводить только правой части.

Есть множество тем, в том числе и на этом форуме, по разбору и вычислению выражений заданных в строке.

Посмотрите их, что-то сами сделаете. Что не получится - напишите.
0
1 / 1 / 0
Регистрация: 18.02.2016
Сообщений: 71
09.10.2018, 19:56  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Ваше задание значительно отличается от начально-предоставленной Вами информации.
В той теме я как раз и пытался сделать такую функцию.
Вот тут такой-же пример https://www.cyberforum.ru/post1443152.html
Он ищет знак и потом применяет ту же функцию к левой и правой части как и я, только у меня не получается выйти из рекурсивной функции.
Спасибо, буду дальше разбираться.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,111
Записей в блоге: 2
09.10.2018, 20:18
Цитата Сообщение от ivret Посмотреть сообщение
ищет знак и потом применяет ту же функцию к левой и правой части как и я, только у меня не получается выйти из рекурсивной функции.
Спасибо, буду дальше разбираться.
Вашу реализацию сюда скиньте. Только с нормальными операторами, а не этими "test1", "test3"....
0
1 / 1 / 0
Регистрация: 18.02.2016
Сообщений: 71
10.10.2018, 00:55  [ТС]
Цитата Сообщение от Элд Хасп Посмотреть сообщение
Вашу реализацию сюда скиньте. Только с нормальными операторами, а не этими "test1", "test3"....

Я сейчас пытаюсь сделать без использования foreach, возможно проблема в этом. Код в той теме и в примере на Паскале, который я привёл один и тот же только в Паскале используют while. Cейчас я попытаюсь попытаюсь сделать с оператором for.
0
Модератор
Эксперт .NET
 Аватар для Элд Хасп
16140 / 11264 / 2888
Регистрация: 21.04.2018
Сообщений: 33,111
Записей в блоге: 2
10.10.2018, 11:16
Цитата Сообщение от ivret Посмотреть сообщение
Я сейчас пытаюсь сделать без использования foreach, возможно проблема в этом. Код в той теме и в примере на Паскале, который я привёл один и тот же только в Паскале используют while. Cейчас я попытаюсь попытаюсь сделать с оператором for.
Оператор for имеет явно заданные границы, while - нет. Через while осуществить for всегда можно. Обратное - не всегда.

Добавлено через 3 минуты
Цитата Сообщение от ivret Посмотреть сообщение
Код в той теме и в примере на Паскале, который я привёл один и тот же только в Паскале используют while.
В любом случае скиньте свой код на C#. Увидев Паскаль в начале темы - многие даже читать дальше не будут.
Так как тема уже "старая", те кто её читал, возможно читать больше не будут. Сделайте какой можете код на C#. И проблемные участки этого кода, выкладывайте в в новой теме с описанием проблем. Так быстрее дождётесь помощи.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
10.10.2018, 11:16
Помогаю со студенческими работами здесь

Разобрать(парсить) арифметическое выражение
Нужно считать из файла арифметическое выражение, которое может включать &quot;+-/*&quot; и числа/переменные -----&gt; (сделано) Далее нужно...

Как вычислить арифметическое выражение?
Помогите пожалуйста решить задачу на экзамен! Вычисление арифметического выражения. Арифметическое выражение вводится в виде...

Как вычислить арифметическое выражение?
Как вычислить арифметическое выражение? Например дана строка '4+7-3' нужно получить результат(целое число)

Как записать арифметическое выражение?
sin((sqrt(x)^3) т.е. sin*кубический корень

Как записать арифметическое выражение
x-10sinx+|x4 - х5|


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Новые блоги и статьи
Отправка уведомления на почту при изменении наименования справочника
Maks 24.03.2026
Программная отправка письма электронной почты на примере изменения наименования типового справочника "Склады" в конфигурации БП3. Перед реализацией необходимо выполнить настройку системной учетной. . .
модель ЗдравоСохранения 5. Меньше увольнений- больше дохода!
anaschu 24.03.2026
Теперь система здравосохранения уменьшает количество увольнений. 9TO2GP2bpX4 a42b81fb172ffc12ca589c7898261ccb/ https:/ / rutube. ru/ video/ a42b81fb172ffc12ca589c7898261ccb/ Слева синяя линия -. . .
Midnight Chicago Blues
kumehtar 24.03.2026
Такой Midnight Chicago Blues, знаешь?. . Когда вечерние улицы становятся ночными, а ты не можешь уснуть. Ты идёшь в любимый старый бар, и бармен наливает тебе виски. Ты смотришь на пролетающие. . .
Контроль уникальности заводского номера - вариант №2
Maks 24.03.2026
В отличие от предыдущего варианта добавлено прерывание циклов, также добавлены новые переменные для сохранения контекста ошибки перед прерыванием цикла: Процедура ПередЗаписью(Отказ, РежимЗаписи,. . .
SDL3 для Desktop (MinGW): Вывод текста со шрифтом TTF с помощью библиотеки SDL3_ttf на Си и C++
8Observer8 24.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-text-sdl3-c. zip finish-text-sdl3-cpp. zip
Жизнь в неопределённости
kumehtar 23.03.2026
Жизнь — это постоянное существование в неопределённости. Например, даже если у тебя есть список дел, невозможно дойти до точки, где всё окончательно завершено и больше ничего не осталось. В принципе,. . .
Модель здравоСохранения: работники работают быстрее после её введения.
anaschu 23.03.2026
geJalZw1fLo Корпорация до введения программа здравоохранения имела много невыполненных работниками заданий, после введения программы количество заданий выросло. Но на выплатах по больничным это. . .
Контроль уникальности заводского номера - вариант №1
Maks 23.03.2026
Алгоритм контроля уникальности заводского (или серийного) номера на примере нетипового документа выдачи шин для спецтехники с табличной частью, разработанного в конфигурации КА2. Данные берутся из. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru