Имя: Пароль:
1C
 
Задача со скобкаим
,
0 Sv4org
 
20.12.16
21:24
Составить обработку, которая проверяет корректность баланса скобок в арифметическом выражении, т.е. что скобки установлены верно и правильно их вхождение, то есть если скобки так расположены [({})] , то это правильное вхождение, а вот [([) - неверное.
Входной параметр - Строка - арифметическое выражение;
Выходной параметр - "Верно"\"Не верно".
Использовать метод "Вычислить" нельзя.
1 Sv4org
 
20.12.16
21:24
Подскажите пожалуйста как это решить
2 Мимохожий Однако
 
20.12.16
21:30
Перебирай последовательно и считай скобки.
3 butterbean
 
20.12.16
21:31
Перебирай посимвольно и запоминай в массив открытые скобки, и убирай их оттуда по мере того, как попадутся закрытые
4 Fragster
 
гуру
20.12.16
21:33
2000 рублей
5 Garykom
 
гуру
20.12.16
21:35
(0) Задача имеет много решений, правильные это нечто вроде https://ru.wikipedia.org/wiki/Синтаксический_анализ можно восходящий.

А тупое это

Стр = [({})];
Пока СтрДлина()>0 Цикл
   НовСтр = СтрЗаменит(Стр, "{}", "");
   НовСтр = СтрЗаменит(Стр, "()", "");
   НовСтр = СтрЗаменит(Стр, "[]", "");
   Если СтрДлина(НовСтр)=СтрДлина(Стр) Тогда
      Сообщить("Неверные скобки!");
      Прервать();
   КонецЕсли;
   Стр = НовСтр;
КонецЦикла;
Если СтрДлина(Стр)=0 Тогда
   Сообщить("Верные скобки!");
КонецЕсли;
6 Garykom
 
гуру
20.12.16
21:37
(5)+ сорри за очепятки
7 Garykom
 
гуру
20.12.16
21:38
Гы кто ответит не запуская сколько у меня всего ошибок в (5) и сколько разных видов ошибок?
8 Sv4org
 
20.12.16
21:50
Ну суть примерно понял, вот что получилось, не знаю правильно или нет


Процедура КнопкаВыполнитьНажатие(Кнопка)
    
    Верно = Истина;
    
    //  ([{}])
    
    // создаем таблицу значений скобок, какие есть скобки и в поле "Параметр" их группируем
    лСтрока = СокрЛП("Строка");
    
    ТЗСкобки = Новый ТаблицаЗначений;
    
    ТЗСкобки.Колонки.Добавить("Параметр");
    ТЗСкобки.Колонки.Добавить("СимволСкобки");
    ТЗСкобки.Колонки.Добавить("КакаяСкобка");
    
    Стр = ТЗСкобки.Добавить();
    Стр.Параметр         = 1;
    Стр.СимволСкобки     = "(";
    Стр.КакаяСкобка     = "Открывающая";
    
    Стр = ТЗСкобки.Добавить();
    Стр.Параметр         = 1;
    Стр.СимволСкобки     = ")";
    Стр.КакаяСкобка     = "Закрывающая";
    
    Стр = ТЗСкобки.Добавить();
    Стр.Параметр         = 2;
    Стр.СимволСкобки     = "[";
    Стр.КакаяСкобка     = "Открывающая";
    
    Стр = ТЗСкобки.Добавить();
    Стр.Параметр         = 2;
    Стр.СимволСкобки     = "]";
    Стр.КакаяСкобка     = "Закрывающая";
    
    Стр = ТЗСкобки.Добавить();
    Стр.Параметр         = 3;
    Стр.СимволСкобки     = "{";
    Стр.КакаяСкобка     = "Открывающая";
    
    Стр = ТЗСкобки.Добавить();
    Стр.Параметр         = 3;
    Стр.СимволСкобки     = "}";
    Стр.КакаяСкобка     = "Закрывающая";
    
    КолОткрывающихСкобок = 0;
    
    КолСимволовВСтроке = СтрДлина(лСтрока);
    
    // если количество символов (скобок) не четное то что-то не правильно
    Если КолСимволовВСтроке/2 > Цел(КолСимволовВСтроке/2) Тогда
        Сообщить("Не верно!");    
        Верно = Ложь;
    Иначе
        КолСимволов = 1;
        
        // список значений - это список уже прочитаных и не закрытых скобок
        СписокСкобок = Новый СписокЗначений;
        
        Пока КолСимволов <> КолСимволовВСтроке Цикл
            
            л = Сред(лСтрока, КолСимволов, 1); // берем символ
            
            НайденоЗнач = ТЗСкобки.Найти(л);
            
            Если НайденоЗнач = Неопределено Тогда
                Сообщить("Не верно! В строке содержаться не только скобки!");
                Верно = Ложь;
                Прервать;    
            КонецЕсли;
            
            Если НайденоЗнач.КакаяСкобка = "Закрывающая" и КолОткрывающихСкобок = 0 Тогда
                Сообщить("Не верно!");    
                Верно = Ложь;
                Прервать;
            КонецЕсли;
            
            Если НайденоЗнач.КакаяСкобка = "Открывающая" Тогда
                КолОткрывающихСкобок = КолОткрывающихСкобок + 1;
            КонецЕсли;
            
            Если  КолОткрывающихСкобок > КолСимволовВСтроке/2 Тогда
                Сообщить("Не верно! В строке больше открывающих строк!");
                Верно = Ложь;
                Прервать;    
            КонецЕсли;
            
            
            Если  НайденоЗнач.КакаяСкобка = "Закрывающая" Тогда
                ПоследняяСкобка = СписокСкобок[СписокСкобок.Количество()-1];
                
                // проверяем по параметрам () {} []
                Если ПоследняяСкобка.Значение.Параметр <> НайденоЗнач.Параметр Тогда
                    Сообщить("Не верно!");
                    Верно = Ложь;
                Иначе
                    // удаляем открывающую скобку и закрывающую скобку не записываем
                    СписокСкобок.Удалить(СписокСкобок[СписокСкобок.Количество()-1]);
                КонецЕсли;
            Иначе
                СписокСкобок.Добавить(НайденоЗнач);
            КонецЕсли;
            
            КолСимволов = КолСимволов + 1;
        КонецЦикла;
        
        Если Верно Тогда
            Сообщить("Верно!");
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры


Подскажите только как сделать это в обработке?
какие реквизиты нужны или ТЧ?
Как это вообще должно работать?
9 НП
 
20.12.16
22:10
(0) Строгое решение состоит в преобразовании в польскую (постфиксную) запись. Все это широко обсуждалось лет 50 тому назад.
В книге Генератор компиляторов  У Маккимана и др. на стр. 52 в разделе "Деревья, стеки и польская запись приводится" теоретической обоснование компиляции арифметического выражения.
10 NorthWind
 
20.12.16
22:29
(0) рекурсия. Сканируем строку слева направо. Когда обнаруживается открывающаяся скобка - вызываем себя же, передавая номер следующего после открывающейся скобки символа и тип этой скобки (квадратная, круглая и т.д.). Соответственно сканируем уже начиная с этого символа и т.д. Выход из процедуры на уровень выше происходит, когда встретится закрывающая скобка такого же типа, как была передана, или когда строка окончится.
.
Еще должна быть глобальная по отношению к процедуре переменная типа "счетчика ссылок". Изначально она инициализируется нулем. Встретили открывающую скобку - увеличиваем на 1, закрывающую - уменьшили на 1.
.
Если выражение корректно, то по окончании сканирования значение этой переменной будет 0. Если скобки расположены криво или их количество не соответствует действительности, то значение будет ненулевое.
11 NorthWind
 
20.12.16
22:32
(9) польскую запись есть смысл мутить, если нужно делать полноценный разбор выражений с арифметическими и прочими действиями. Если просто посчитать скобки и корректность их открытия-закрытия - то достаточно (10).
12 Fragster
 
гуру
20.12.16
22:34
Зачем рекурсия? Цикл и стек из массива.
13 NorthWind
 
20.12.16
22:39
(12) Если бояться переполнения стека, то таки да :)
14 NorthWind
 
20.12.16
22:40
хотя можно просто поставить ограничение на количество вложений скобок
Основная теорема систематики: Новые системы плодят новые проблемы.