Вход | Регистрация
 

Как проверить корректность расстановки скобок в выражении?

Как проверить корректность расстановки скобок в выражении?
Я
   Владислав_startinpro
 
23.04.21 - 12:21
Проверить корректность расстановки скобок в арифметическом выражении.
Выражение задается как строковый входной параметр функции и может содержать произвольное количество круглых скобок.
Функция должна возвращать одну строчку: "правильно" или "неправильно".
   Mikeware
 
1 - 23.04.21 - 12:22
срочно скажи, что не получается.
   Mikeware
 
2 - 23.04.21 - 12:23
»
   Garykom
 
3 - 23.04.21 - 12:24
(0) Попытка ... Вычислить(...)
   Mikeware
 
4 - 23.04.21 - 12:25
(3) само выражение может быть бессмысленным. его только скобки интересуют.
ну обычная задачка школьная...
   d_monah
 
5 - 23.04.21 - 12:25
(0) А вы знаете,так можно,попробуйте.Если не получится ,сообщите,попробуем по другому
   mikecool
 
6 - 23.04.21 - 12:27
Функция ВернутьПравильноИлиНеправильно()
  Возврат "Правильно" Или "Неправильно";
КонецФункции
   fisher
 
7 - 23.04.21 - 12:27
Возврат СтрЧислоВхождений(ИсходнаяСтрока, "(") = СтрЧислоВхождений(ИсходнаяСтрока, ")");
   Mikeware
 
8 - 23.04.21 - 12:28
(7) это всего лишь необходимое условие
   mikecool
 
9 - 23.04.21 - 12:28
(7) результат возврата не тот )
   fisher
 
10 - 23.04.21 - 12:28
(8) Согласен
   Garykom
 
11 - 23.04.21 - 12:30
(4) заменить все кроме скобок на хрень но вычисляемую и Попытка Вычислить
   fisher
 
12 - 23.04.21 - 12:30
Придется посимвольным обходом с проверкой на отсутствие закрывающих скобок без открывающих
   Garykom
 
13 - 23.04.21 - 12:31
(7) Добавить что нет бессмысленных скобок типа "()" и пойдет
   Garykom
 
14 - 23.04.21 - 12:32
(13)+ а и еще что нет внешних скобок хотя и парных типа "..)..(.."
   Mikeware
 
15 - 23.04.21 - 12:33
(12) ну ,чтоб количество открытыъ подскобочных выражений всегда было неотрицательным.
интересно, а регулярками как такое сделать?
   Garykom
 
16 - 23.04.21 - 12:33
(14)+ Достаточно проверки что первая скобка слева "(" а справа последняя это ")"
   fisher
 
17 - 23.04.21 - 12:34
(15) Не хочу даже думать. От регулярок чаще больше зла, чем добра :)
   fisher
 
18 - 23.04.21 - 12:34
(16) Недостаточно
   RomanYS
 
19 - 23.04.21 - 12:35
(15) давайте усложним задачу, (0) надо решить в запросе)
   Mikeware
 
20 - 23.04.21 - 12:35
(17) но ведь один хрен это у нас конечный автомат получается?
   RomanYS
 
21 - 23.04.21 - 12:35
(16)
())(()
   Mikeware
 
22 - 23.04.21 - 12:36
(19) в запросе - это к ильдаровичу.
   Владислав_startinpro
 
23 - 23.04.21 - 12:37
ЛКруглаяСкобка = 0;
    ПКвадратнаяСкобка = 0;
    ЛКвадратнаяСкобка = 0;
    ПФигурнаяСкобка = 0;
    ЛФигурнаяСкобка = 0;
    ПУгловаяСкобка = 0;
    ЛУгловаяСкобка = 0;
    ТестоваяСтрока = "";
    ВвестиСтроку(ТестоваяСтрока, "Введите выражение");
    Для Буква = 1 По СтрДлина(ТестоваяСтрока) Цикл
    
    Если Буква = "(" Тогда
        ПКруглаяСкобка = ПКруглаяСкобка + 1;        
    
    ИначеЕсли Буква = ")" Тогда
        ЛКруглаяСкобка = ЛКруглаяСкобка + 1;
    
    ИначеЕсли Буква = "[" Тогда
        ПКвадратнаяСкобка = ПКвадратнаяСкобка + 1;
    ИначеЕсли Буква = "]" Тогда
        ЛКвадратнаяСкобка = ЛКвадратнаяСкобка + 1; 
    ИначеЕсли Буква = "{" Тогда
        ПФигурнаяСкобка = ПФигурнаяСкобка + 1;
    ИначеЕсли Буква = "}" Тогда
        ЛФигурнаяСкобка = ЛФигурнаяСкобка + 1;
    ИначеЕсли Буква = "<" Тогда
        ПУгловаяСкобка = ПУгловаяСкобка + 1;    
    Иначе Буква = ">" Тогда
        ЛУгловаяСкобка = ЛУгловаяСкобка + 1;
    
    КонецЕсли; 
Пока пытаюсь посчитать количество вхождений каждой скобки в строку
   fisher
 
24 - 23.04.21 - 12:37
(20) В случае с лобовой проверкой - простейшего вида. А в регулярке может жесть жестяная получиться на уровне исполнения.
   RomanYS
 
25 - 23.04.21 - 12:37
(22) Реально что ли забацать, что будет ТСу если он решение запросом сдаст)?
   RomanYS
 
26 - 23.04.21 - 12:38
(23) Ты задачу-то свою читал : "и может содержать произвольное количество круглых скобок"
   dmt
 
27 - 23.04.21 - 12:40
(0) если это тестовое какое-то, должно прокатить так:
Функция ПроверитьСкобки(Выражение)
    
    колОткрытых = 0;
    
    Для к=1 по СтрДлина(Выражение) Цикл
        Если Сред(Выражение, к, 1) = "(" Тогда
            колОткрытых = колОткрытых + 1;
        ИначеЕсли Сред(Выражение, к, 1) = ")" Тогда 
            колОткрытых = колОткрытых - 1;
        КонецЕсли; 
        
        Если колОткрытых < 0 Тогда
            Возврат Ложь;
        КонецЕсли; 
        
    КонецЦикла;
    
    Возврат колОткрытых = 0;
    
КонецФункции
   Mikeware
 
28 - 23.04.21 - 12:41
(24) с любой
   RomanYS
 
29 - 23.04.21 - 12:44
(27) Блин, такую ветку запорол))
   Garykom
 
30 - 23.04.21 - 12:46
(21) добавить проверку что в самой середине нет )( или )...(
Как была проверка на пустые ()
 
 Рекламное место пустует
   RomanYS
 
31 - 23.04.21 - 12:47
(30) любитель костылей))) их там будет много на твоем пути? Решение в (27)
   mikecool
 
32 - 23.04.21 - 12:49
(27) чего ты Сред вычисляешь постоянно?
   mikecool
 
33 - 23.04.21 - 12:49
+32 и ты тоже возвращаешь неверный результат
   fisher
 
34 - 23.04.21 - 12:50
(30) Зачем? Пустая подгруппа может считаться корректным выражением.
   fisher
 
35 - 23.04.21 - 12:51
(33) Для какого кейса?
   mikecool
 
36 - 23.04.21 - 12:52
(35) из задачи (0) "Функция должна возвращать одну строчку: "правильно" или "неправильно"."
чего вы все булево возвращаете?
   Mikeware
 
37 - 23.04.21 - 12:53
(36) профдеформация
   fisher
 
38 - 23.04.21 - 12:54
(36) Обернет в декоратор, делов-то :)
   vi0
 
39 - 23.04.21 - 12:55
(15) вроде бы что то подобное рассматривалось в книге Фрилда про регулярки
   vi0
 
40 - 23.04.21 - 12:56
(24) большое вопрос как будет оформлена эта регулярка и как прокомментирована
синтаксисы позволяют делать из многострочными, с отступами итд, т.е. читабельными
   vi0
 
41 - 23.04.21 - 12:56
*делать их
   fisher
 
42 - 23.04.21 - 12:59
(40) Речь не только про читабельность. Хотя "читабельность регулярок" - это оксюморон.
Речь про особенности исполнения. Элементарно можно схлопотать недетерменированную производительность.
   Fragster
 
43 - 23.04.21 - 13:00
простейшее тестовое задание, а автор его провалил
   Mikeware
 
44 - 23.04.21 - 13:01
   Владислав_startinpro
 
45 - 23.04.21 - 13:02
Ну раз оно такое простейшее, почему тут нет верного решения ...
   Mikeware
 
46 - 23.04.21 - 13:03
(45) так кто ж тебе его дастЬ? :-)
делай сам
   Garykom
 
47 - 23.04.21 - 13:06
(45) Потому что задание тупое и не детализированное

1. Если это арифметическое выражение то банально попробуй его вычислить, если не упало то считаем что скобки правильно расставлены
Если упало то хз конечно (вдруг там деление на 0 было) но считаем что не правильно
По уму надо ошибку проанализировать

2. Или да писать парсер - синтаксический разбор выражения

3. Вариант предполагается авторами: простейший проверка/парсер в меру способностей тестируемого что он сумеет накалякать
   Владислав_startinpro
 
48 - 23.04.21 - 13:07
Я понял, всем спасибо
   timurhv
 
49 - 23.04.21 - 13:10
Обходить все символы, если "(", то счетчик + 1, если ")", то счетчик -1. Если счетчик отрицательный, то ошибка?
Такой вариант правильный?
   timurhv
 
50 - 23.04.21 - 13:10
(49) ну и в конце дб равен 0
   Владислав_startinpro
 
51 - 23.04.21 - 13:18
Я столкнулся с ошибкой при обходе символов в строке, пишу:
Для каждого Буква из ТестоваяСтрока Цикл
.....(условие проверки),
подскажите, как сделать обход по каждому символу в строке
   Mikeware
 
52 - 23.04.21 - 13:21
(51) сред()
итератора для строки в 1с нет
   dmt
 
53 - 23.04.21 - 13:22
   Irbis
 
54 - 23.04.21 - 13:24
А выражение "(·)(·)" считается за ошибку или нет?
   fisher
 
55 - 23.04.21 - 13:26
(54) С каких это пор сиськи считаются ошибкой?
   Garykom
 
56 - 23.04.21 - 13:27
(54) Сисек может быть от 0 до X
   Mikeware
 
57 - 23.04.21 - 13:27
(55) был определенный период
   Mikeware
 
58 - 23.04.21 - 13:28
(56) ты про размер или про количество?
   Mikeware
 
59 - 23.04.21 - 13:29
(56) ну и"до X" они могут быть только в Тайланде...
   fisher
 
60 - 23.04.21 - 13:32
(59) Некоторые считают, что с хорошими сиськами и X не нужен, а некоторые перестраховываются.
 
 Рекламное место пустует
   Kassern
 
61 - 23.04.21 - 13:33
(52) зачем эти циклы и обходы посимвольные, когда можно:
    КоличествоСкобокВкл=СтрРазделить(Выражение,"(").Количество();
    КоличествоСкобокВыкл=СтрРазделить(Выражение,")").Количество();
    Сообщить(КоличествоСкобокВкл=КоличествоСкобокВыкл);
   RomanYS
 
62 - 23.04.21 - 13:35
(61)
)(
   Kassern
 
63 - 23.04.21 - 13:36
(62) точно, порядок же еще...
   fisher
 
64 - 23.04.21 - 13:36
(62) Тоже вполне достойное выражение.
   Arbuz
 
65 - 23.04.21 - 13:57
(()о()) устроили.
Простейшая алгоритмическая задача. Решается каждый раз при написании любого мало-мальски рабочего синтаксического разбора и, к тому же, находится место, где именно неправильная скобка. Почему никто про необходимость учёта корректности вложенности скобок не говорит? типа "())(()".
   Irbis
 
66 - 23.04.21 - 13:59
(65) это уже перетёрли, кури тему внематочнее
   Arbuz
 
67 - 23.04.21 - 14:01
(66) покажи где
   Kassern
 
68 - 23.04.21 - 14:02
(67) (61) (62)
   Irbis
 
69 - 23.04.21 - 14:02
(67) см (27) наприклад
   Mikeware
 
70 - 23.04.21 - 14:03
(67) в (15), например. даже в (27) решение
   Irbis
 
71 - 23.04.21 - 14:04
В (27) только пустые скобки останутся правильными.
   hhhh
 
72 - 23.04.21 - 15:19
(71) чего это? нормально там всё
   H A D G E H O G s
 
73 - 23.04.21 - 16:09
Пусть этим займется 1С
Попытка
Вычислить(ПроверяемоеВыражение);
Исключение
КонецПопытки

1С все равно сделает это лучше.
   Kassern
 
74 - 23.04.21 - 16:21
(73) проблема в том, что в тексте может быть все что угодно, а задача проверить только корректность скобочек. Следовательно из поста ТС, выражение "()" должно вернуть правильно, а ")(" - неправильно, если я все правильно понял
   Garykom
 
75 - 23.04.21 - 16:39
(74) "(что то есть)" должно вернуть правильно
() как бы не корректно
   Garykom
 
76 - 23.04.21 - 16:39
(73) см (3)
   fisher
 
77 - 23.04.21 - 16:46
(75) Это в 1С некорректно. А в другой среде вполне может быть корректно.
   Sserj
 
78 - 23.04.21 - 16:57
Функция ПроверитьСкобки(Выражение)
  результат = Неопределено;
  стек = Новый СписокЗначений;
  Для номерСимвола = 1 по СтрДлина(Выражение) Цикл
    токен = Сред(Выражение, номерСимвола, 1);
    Если не токен = ")" и не токен = "(" Тогда
      Продолжить;
    КонецЕсли;
    Если стек.Количество() = 0 Тогда
      Если токен = ")" Тогда
        результат = Ложь;
        Прервать;
      Иначе
        стек.Добавить(токен);
      КонецЕсли;
    ИначеЕсли токен = "(" Тогда
      стек.Добавить(токен);
    ИначеЕсли стек[стек.Количество() - 1].Значение = токен Тогда
      стек.Добавить(токен);
    Иначе 
      стек.Удалить(стек.Количество() - 1);
    КонецЕсли;
  КонецЦикла;
  
  Если результат = Неопределено Тогда
    результат = (стек.Количество() = 0);
  КонецЕсли;

  Возврат результат;
КонецФункции
   fisher
 
79 - 23.04.21 - 17:11
(78) Жесть какая. И чем это лучше (27), кроме того что хуже? Эхо алгоритма Дейкстры нахлобучило? :)
   acht
 
80 - 23.04.21 - 17:24
(78) > Если не токен = ")" и не токен = "(" Тогда

Офигенный пример к чему приводит выпендреж с использованием "не =" вместо "<>"

Что проще прочитать:
    Если не токен = ")" и не токен = "(" Тогда
или
    Если Токен <> ")" и Токен <> "(" Тогда

?
   Kassern
 
81 - 23.04.21 - 17:25
(80) я конструкцию НЕ использую обычно с функциями к примеру Если Не РаботаетИнтернет() Тогда
   Kassern
 
82 - 23.04.21 - 17:26
(80) хотя может это дело привычки восприятия... кому НЕ а кому <>
   программистище
 
83 - 23.04.21 - 17:26
(80) вкусовщина
   acht
 
84 - 23.04.21 - 17:26
(81) Ну там еще отрицание в идентификаторах давить надо. У некоторых получаются перлы типа
Если Не ИнтернетНеРаботает() Тогда
   acht
 
85 - 23.04.21 - 17:27
(83) Ты должен был спеть это и станцевать!
   Sserj
 
86 - 23.04.21 - 17:37
(79) Тем что (27) не учитывает порядок, он пропустит: )))((( или (()))(
(80) Мне проще прочитать с "не", знак равенства не оставляет в голове каких то других возможных вариантов, а БольшеИлиМеньше всегда цепляет взгляд на подумать а что больши или меньше.
   Вафель
 
87 - 23.04.21 - 17:39
Это же классическая задача в программировании.
   Вафель
 
88 - 23.04.21 - 17:41
Сдается что тс и задали такую задачу.
Универ?
   fisher
 
89 - 23.04.21 - 18:05
(86) Учитывает. Не пропустит.
   ДедМорроз
 
90 - 24.04.21 - 17:36
В тексте могут быть литералы (читай числа),имена переменных или функций(по условию задачи не понятно).
А также операторы,бинарные и угарные (такие как НЕ или минус).
Просто,построить дерево вычисления,в процессе построения будет понятно,правильное выражение или нет.
   spectre1978
 
91 - 24.04.21 - 21:22
По классике рекурсией делается. Открытая скобка, читаем выражение до закрытой. Если вновь открытая, то рекурсивный вызов себя же.  Если не встретилась закрывающая, то косяк "неправильно", если везде встретилась, то "правильно".
   Garykom
 
92 - 24.04.21 - 21:38
(91) и (10)()(-17) ?
   fisher
 
93 - 26.04.21 - 12:54
(91) На рекурсию ложится, но тут даже рекурсия не нужна. Рекурсия ведь не бесплатна.
(92) Если нужна еще и проверка корректности выражений внутри скобок - тогда это полный разбор надо делать. Но он тоже несложный. Есть классический алгоритм Дейкстры для преобразования выражений со скобками и приоритетом операций в обратную польскую нотацию (со стеком операций и очередью вывода): https://ru.wikipedia.org/wiki/Алгоритм_сортировочной_станции
Но мне нравится другая его модификация на двух стеках, которая производит вычисления по ходу разбора выражения. Навскидку вроде вот на хабре нашлось: https://habr.com/ru/post/50196/
   Volodja
 
94 - 26.04.21 - 13:30
(75) Очень даже может быть корректно и в 1С, если в выражении функция
(4*ЧислоПИ())


Список тем форума
Рекламное место пустует  Рекламное место пустует
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.