Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.67/9: Рейтинг темы: голосов - 9, средняя оценка - 4.67
2712 / 1879 / 556
Регистрация: 05.06.2014
Сообщений: 5,455
1

Работа с регулярными выражениями и исключения

14.02.2017, 11:50. Просмотров 1758. Ответов 31
Метки нет (Все метки)


Очень простой вопрос - какую взять библиотеку для работы с регулярными выражениями, удовлетворяющую одному из следующих условий:
1) Напоровшись на некорректное выражение, парсер не плюется исключениями, а возвращает false.
2) Парсер все же кидает исключение, но это исключение гарантированно содержит описание ошибки. Очень желательно, в utf-16.

Предупреждая вопрос "нафиг надо" - метод assign стандартного std::regex, плюется исключением с невероятно информативной строчкой "regex_error". Поэтому, мне надо прям на месте это исключение ловить и менять на более информативное. И я как-то не понимаю чем такой дизайн лучше дедовской проверки кодов возврата.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.02.2017, 11:50
Ответы с готовыми решениями:

Работа с регулярными выражениями С++
Опишите функцию анализа номера, обработайте ошибку указания номера у недопустимом формате...

Работа с регулярными выражениями (парсинг txt-файла)
подскажите пожалуйста. хочу сделать парсер по файлу тхт написал вот такой код с регулярными...

Как пользоваться регулярными выражениями
Имеется текстовый файл с подобным содержанием: ////////////////////////////// Файл 12/1.19...

Не получается работать с регулярными выражениями
Добрый день, коллеги! Обращаюсь с вопросом, потому что новичок. Мне необходимо, используя...

__________________
Помогаю в написании курсовых работ и дипломов здесь.
Записывайтесь на профессиональные курсы C++ разработчиков
31
749 / 352 / 72
Регистрация: 10.06.2014
Сообщений: 2,369
14.02.2017, 12:12 2
Цитата Сообщение от Renji Посмотреть сообщение
апоровшись на некорректное выражение, парсер не плюется исключениями, а возвращает false.
Что вы подразумеваете под некорректным выражением? Если отсутствие совпадений по выражению то можно так:
C++
1
2
3
std::regex txt_regex("[a-z]+\\.txt");
std::cout << std::regex_match("foo.txt", txt_regex) << '\n';//1
std::cout << std::regex_match("bar.bin", txt_regex) << '\n';//0
Цитата Сообщение от Renji Посмотреть сообщение
Очень желательно, в utf-16.
Символы ведь это набор байт. Получаете текст и конвертируете в нужное представление (кодировку) - этим уже занимается принимающая сообщение сторона, тобишь вы.

Добавлено через 3 минуты
Если же вы говорите о синтаксических ошибках в самом регулярном выражении - то я видал 3 языка с поддержкой регекспов и ни один из них не выдавал нормальную информацию о том что не так с выражением.
Тут просто надо знать хорошо эти выражения и получив "регекс эррор" уже смотреть выражение и исправлять
0
2712 / 1879 / 556
Регистрация: 05.06.2014
Сообщений: 5,455
14.02.2017, 12:19  [ТС] 3
Цитата Сообщение от sys_beginner Посмотреть сообщение
Что вы подразумеваете под некорректным выражением?
Ровно то что написано - синтаксически некорректное выражение.
C++
1
std regex test("(");//опс... А скобочку то закрыть забыли
Цитата Сообщение от sys_beginner Посмотреть сообщение
Символы ведь это набор байт. Получаете текст и конвертируете в нужное представление (кодировку) - этим уже занимается принимающая сообщение сторона, тобишь вы.
Ну да, при броске исключения конвертируй из utf-16 в utf-8, в обработчике исключений конвертируй обратно. Я как раз и хочу уйти от этой бессмысленной конвертации текста туда-сюда. Если уж программа работает в utf-16, пусть везде будет utf-16.

Добавлено через 1 минуту
Цитата Сообщение от sys_beginner Посмотреть сообщение
Тут просто надо знать хорошо эти выражения и получив "регекс эррор" уже смотреть выражение и исправлять
Как смотреть? К моменту когда исключение поймали, информация о точке его возникновения давно потеряна. Плюс, я этот регексп из файла читаю. А файл большой.
0
Любитель чаепитий
3536 / 1647 / 507
Регистрация: 24.08.2014
Сообщений: 5,601
Записей в блоге: 1
14.02.2017, 12:20 4
Цитата Сообщение от sys_beginner Посмотреть сообщение
Что вы подразумеваете под некорректным выражением?
http://rextester.com/YSUU77183
C++
1
2
3
4
5
6
#include <regex>
 
int main()
{
    std::regex re("[a-b][a");
}
Цитата Сообщение от Renji Посмотреть сообщение
1) Напоровшись на некорректное выражение, парсер не плюется исключениями, а возвращает false.
std::regex_match и std::regex_search не плюются исключениями.
А перехват исключений при создании регекспа можно и так сделать.
Цитата Сообщение от Renji Посмотреть сообщение
плюется исключением с невероятно информативной строчкой "regex_error".
Есть http://en.cppreference.com/w/cpp/regex/error_type.
Цитата Сообщение от Renji Посмотреть сообщение
И я как-то не понимаю чем такой дизайн лучше дедовской проверки кодов возврата.
Из конструктора не вернешь значение.
2
749 / 352 / 72
Регистрация: 10.06.2014
Сообщений: 2,369
14.02.2017, 12:20 5
Цитата Сообщение от Renji Посмотреть сообщение
//опс... А скобочку то закрыть забыли
Если это нужно внутри программы тогда сказать нечего. Но если чисто для себя отлаживать... то можете вставить выражение например сюда
https://regex101.com/
Допустим для такого шаблона %[+$ пишет ответ Character class missing closing bracket
Хоть какая то информация
0
Любитель чаепитий
3536 / 1647 / 507
Регистрация: 24.08.2014
Сообщений: 5,601
Записей в блоге: 1
14.02.2017, 12:21 6
Цитата Сообщение от Renji Посмотреть сообщение
Если уж программа работает в utf-16, пусть везде будет utf-16.
На счёт экзепшонов не в курсе, но вообще есть такая штука. Опять же, не факт, что исключения будут бросаться в utf-16.
http://en.cppreference.com/w/c... gex_traits
0
749 / 352 / 72
Регистрация: 10.06.2014
Сообщений: 2,369
14.02.2017, 12:29 7
GbaLog-,
А что... Ваш вариант очень даже не плохой
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <regex>
#include <iostream>
 
int main()
{
    try {
        std::regex re("[a-b][a");
    } 
 
    catch (const std::regex_error& e) {
        std::cout << "regex_error caught: " << e.what() << '\n';
        if (e.code() == std::regex_constants::error_brack) {
            std::cout << "The code was error_brack\n";
        }
    }
}
Но наверное тут придется в зависимости от констант самому формировать более понятные сообщения...

Добавлено через 3 минуты
Цитата Сообщение от GbaLog- Посмотреть сообщение
std::regex_match и std::regex_search не плюются исключениями.
За то плюсется сам std::regex если выражение не валидно а без него regex_match вроде как и не работает
0
2712 / 1879 / 556
Регистрация: 05.06.2014
Сообщений: 5,455
14.02.2017, 12:32  [ТС] 8
Цитата Сообщение от GbaLog- Посмотреть сообщение
А перехват исключений при создании регекспа можно и так сделать.
Можно, но очень длинно.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
//Можно так
try
{
    regex.assign(str);
}
catch(...)
{
    cout<<"Error in "<<str;
}
 
//но хочу вот так
if(!regex.assign(str))
   cout<<"Error in "<<str;
Цитата Сообщение от GbaLog- Посмотреть сообщение
Спасибо, не знал. Но это не то. Чтоб этот код ошибки распечатать, надо ловить конкретно std::regex_error. То есть, делать дополнительную catch секцию, в дополнение к общей catch(const std::exception&error). Плюс, информация о сбойнувшем выражении все равно теряется. Ну вот вижу я что произошло "error_escape", как мне из этого понять какое выражение сбойнуло и откуда взялось?
Цитата Сообщение от sys_beginner Посмотреть сообщение
Если это нужно внутри программы тогда сказать нечего.
Нужно именно внутри программы прочитавшей регулярку из конфига. Мне потом в этот конфиг лезть и разбираться где я там опечатался. Так что нужен хотя-бы вызвавший сбой текст, а лучше - номер строки.
0
Любитель чаепитий
3536 / 1647 / 507
Регистрация: 24.08.2014
Сообщений: 5,601
Записей в блоге: 1
14.02.2017, 12:40 9
Цитата Сообщение от Renji Посмотреть сообщение
Так что нужен хотя-бы вызвавший сбой текст
Если вы перехватываете исключение, то:
C++
1
2
3
4
5
6
7
8
9
10
11
std::ifstream fileIn("regexps.txt");
std::string regexp;
fileIn >> regexp;
try
{
  std::regex re(regexp);
}
catch(...)
{
  std::cerr << "error in string: " << regexp << '\n';
}
Ну или если assign:
C++
1
2
3
4
5
6
7
8
try
{
  re.assign(str);
}
catch(...)
{
  std::cerr << "Error while assign: " << str << '\n';
}
0
749 / 352 / 72
Регистрация: 10.06.2014
Сообщений: 2,369
14.02.2017, 12:41 10
Цитата Сообщение от Renji Посмотреть сообщение
Так что нужен хотя-бы вызвавший сбой текст, а лучше - номер строки.
Ну в regex_error такой информации нет... А нельзя ли создать объект типа regex_error_info(самому описать класс) и до каждой строчки регекспа записывать туда информацию об использованном шаблоне и номер строки... А если будет поймано исключение - теребить этот объект и получить нужную инфу. В этом же классе на основе констант-ошибок написать понятные вам тексты. То есть и номер строки будет и текст.
0
Любитель чаепитий
3536 / 1647 / 507
Регистрация: 24.08.2014
Сообщений: 5,601
Записей в блоге: 1
14.02.2017, 12:41 11
Цитата Сообщение от sys_beginner Посмотреть сообщение
За то плюсется сам std::regex если выражение не валидно
...
Цитата Сообщение от GbaLog- Посмотреть сообщение
А перехват исключений при создании регекспа можно и так сделать.
0
2712 / 1879 / 556
Регистрация: 05.06.2014
Сообщений: 5,455
14.02.2017, 12:50  [ТС] 12
Цитата Сообщение от sys_beginner Посмотреть сообщение
Ну в regex_error такой информации нет... А нельзя ли создать объект типа regex_error_info(самому описать класс) и до каждой строчки регекспа записывать туда информацию об использованном шаблоне и номер строки...
Так это и будет "поймать regex_error на месте и заменить более информативным исключением".
C++
1
2
3
4
catch(const std::regex_error&)
{
    throw std::runtime_error("Error in "+str+" excpression");//нужный текст уехал в what() std::exception
}
0
749 / 352 / 72
Регистрация: 10.06.2014
Сообщений: 2,369
14.02.2017, 12:59 13
Renji,
А так не вариант?
C++
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
#include <iostream>
#include <regex>
 
class my_regex
{
    std::string message;
    std::regex r;
 
    public:
        std::string getMessage()
        {
            return message;
        }
        
        std::regex getRegex()
        {
            return r;
        }
        
       bool from_pattern(std::string pattern)
       {
            bool result = true;
            try {
                r = std::regex(pattern);
            } catch (const std::regex_error& e) {
                if (e.code() == std::regex_constants::error_brack) {
                    message = "The code was error_brack\n";
                }
                result = false;
            };
            return result;
       }
};
 
int main()
{
    my_regex r;
    if (!r.from_pattern("[a-b][a")) {
        std::cout << r.getMessage();
    }
    
}
Вроде похоже на то что вам нужно
1
2712 / 1879 / 556
Регистрация: 05.06.2014
Сообщений: 5,455
14.02.2017, 13:14  [ТС] 14
Цитата Сообщение от sys_beginner Посмотреть сообщение
А так не вариант?
Ну, в принципе да. Но я надеялся что можно обойтись готовым решением, а не пилить ту или иную форму костыля. Собственно, я даже видел библиотеку разбирающую регулярки именно так как мне нужно - SLRE называется. Произошла ошибка разбора - получите код ошибки и дальше сами текст ошибки формируйте. Но она не умеет делать replace. То есть, если брать ее, все равно придется с напильником возиться.
0
Игогошка!
1800 / 707 / 44
Регистрация: 19.08.2012
Сообщений: 1,367
14.02.2017, 13:52 15
Лучший ответ Сообщение было отмечено Renji как решение

Решение

Цитата Сообщение от Renji Посмотреть сообщение
std::regex
%s/std/boost

http://www.boost.org/doc/libs/... ssion.html
1
2712 / 1879 / 556
Регистрация: 05.06.2014
Сообщений: 5,455
14.02.2017, 13:57  [ТС] 16
Цитата Сообщение от ct0r Посмотреть сообщение
%s/std/boost
О, точно, у него есть флаг no_except. То что надо, спасибо.
0
Форумчанин
Эксперт CЭксперт С++
8164 / 5012 / 1436
Регистрация: 29.11.2010
Сообщений: 13,455
14.02.2017, 15:11 17
Цитата Сообщение от Renji Посмотреть сообщение
И я как-то не понимаю чем такой дизайн лучше дедовской проверки кодов возврата.
Что мешает сделать класс-дескриптор?
C++
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
#include <iostream>
#include <regex>
 
class Reg
{
public:
    Reg() : m_data(), m_msg() {}
    Reg(const char *str)
    {
        try
        {
            m_data = str;
        }
        catch (std::regex_error &e)
        {
            m_msg = e.what();
        }
    }
    explicit operator bool() const noexcept { return m_msg.empty(); }
    std::string msg() const noexcept { return m_msg; }
 
protected:
    std::regex m_data;
    std::string m_msg;
};
 
int main()
{
    Reg reg("[a-b][a");
    if (!reg)
        std::cout << reg.msg() << std::endl;
}
1
749 / 352 / 72
Регистрация: 10.06.2014
Сообщений: 2,369
14.02.2017, 16:10 18
Цитата Сообщение от MrGluck Посмотреть сообщение
explicit operator bool() const noexcept { return m_msg.empty(); }
Это типа срабатывает когда на if проверяется объект?

Добавлено через 1 минуту
Точнее когда объект принимает участие в bool выражении, так?

Добавлено через 1 минуту
Или это определяется наличием explicit? Если он есть то только в if, если нет тогда и в выражениях типа а==б срабатывает?
0
Форумчанин
Эксперт CЭксперт С++
8164 / 5012 / 1436
Регистрация: 29.11.2010
Сообщений: 13,455
14.02.2017, 16:20 19
sys_beginner, обычный оператор приведения типа с explicit.
explicit тут играет ту же роль что и при объявлении в конструкторе.

Добавлено через 1 минуту
То есть защищает от неявных преобразований.
Использование приведение к bool объекта в if условиях не считается неявным преобразованием.
1
Эксперт С++
8411 / 3946 / 864
Регистрация: 15.11.2014
Сообщений: 8,894
14.02.2017, 16:24 20
Цитата Сообщение от Renji Посмотреть сообщение
с невероятно информативной строчкой "regex_error".
http://ideone.com/zlcpkO
C++
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
#include<iostream>
#include <regex>
 
void DescriptionRegexError(const std::regex_error& e);
 
int main(int argc, char **argv)
{
  (void)argc; (void)argv;
 
 
  try {
      std::regex nameRegex("^[a-zA-Z][[:word:]]+");
      try {
        const auto r = std::regex_match("someDefaultName", nameRegex);
      }
      catch (const std::regex_error& e) {
        std::cout<<"invalid: const auto r = std::regex_match("someDefaultName", nameRegex);\n";
        DescriptionRegexError(e);
  }
 
  } 
  catch (const std::regex_error& e) {
    std::cout<<"invalid: std::regex nameRegex("^[a-zA-Z][[:word:]]+");\n";
    DescriptionRegexError(e);
  }
 
  std::cout<<"-----------------------\n";
}
 
void DescriptionRegexError(const std::regex_error& e)
{
      //std::cout << "regex_error caught: " << e.what() << '\n';
      //std::cout<< e.code() << '\n';
 
          if(e.code()==std::regex_constants::error_collate)
             std::cout << "the expression contains an invalid collating element name\n";   
          else if(e.code()==std::regex_constants::error_ctype)
             std::cout << "the expression contains an invalid character class name\n";
          else if(e.code()==std::regex_constants::error_escape)
             std::cout << "the expression contains an invalid escaped character or a trailing escape\n";
          else if(e.code()==std::regex_constants::error_backref)
             std::cout << "the expression contains an invalid back reference\n";
          else if(e.code()==std::regex_constants::error_brack)
             std::cout << "the expression contains mismatched square brackets ('[' and ']')\n";
          else if(e.code()==std::regex_constants::error_paren)
             std::cout << "the expression contains mismatched parentheses ('(' and ')')\n";
          else if(e.code()==std::regex_constants::error_brace)
             std::cout << "the expression contains mismatched curly braces ('{' and '}')\n";
          else if(e.code()==std::regex_constants::error_badbrace)
             std::cout << "the expression contains an invalid range in a {} expression\n";
          else if(e.code()==std::regex_constants::error_space)
             std::cout << "there was not enough memory to convert the expression into a finite state machine\n";
          else if(e.code()==std::regex_constants::error_badrepeat)
             std::cout << "one of *?+{ was not preceded by a valid regular expression\n";
          else if(e.code()==std::regex_constants::error_complexity)
             std::cout << "the complexity of an attempted match exceeded a predefined level\n";
          else if(e.code()==std::regex_constants::error_stack)
             std::cout << "there was not enough memory to perform a match\n";
 
#ifdef _MSC_VER  //microsoft specific
          else if(e.code()==std::regex_constants::error_parse)
             std::cout << "error_parse\n";
          else if(e.code()==std::regex_constants::error_syntax)
             std::cout << "error_syntax\n";
#endif
}
Добавлено через 1 минуту
Цитата Сообщение от MrGluck Посмотреть сообщение
std::string msg() const noexcept { return m_msg; }
бумс!

Кликните здесь для просмотра всего текста
std::string msg() const
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.02.2017, 16:24

Заказываю контрольные, курсовые, дипломные работы и диссертации здесь или здесь.

Проверка на наличие подстроки регулярными выражениями
Здравствуйте. С помощью регулярных выражений я пытаюсь проверить наличие подстроки. Для этого пишу...

Выбрать различные цифры из однотипных строк регулярными выражениями
есть много таких строк: &lt;AddOrder price=&quot;100.20&quot; orderId=&quot;199&quot; operation=&quot;BUY&quot; /&gt; &lt;DeleteOrder...

Обработка файов регулярными выражениями.
Задайте верное направление. Исходная задача. Необходимо обработать текстовый файл &quot;умным...

Работа с регулярными выражениями
Всем привет! У меня огромный код, который я хочу раскодировать регулярными выражениями. Подскажите...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.