Форум программистов, компьютерный форум CyberForum.ru

Делаем регулярные выражения - C++

Восстановить пароль Регистрация
 
Labus
0 / 0 / 0
Регистрация: 28.08.2012
Сообщений: 3
28.08.2012, 02:12     Делаем регулярные выражения #1
Приветствую.

Свою молодость провел бурно, на программирование времени не осталось. Печально. Прошу помощи:

Есть текстовый файл с записями вида:

901 1800000 1899999
901 7000000 7299999

Скрывать не буду - это телефонные коды, разбитые по регионам и принадлежащие тому или иному оператору связи. Есть задача - привести все это к виду "регулярного выражения" (надеюсь все знают что это такое?). Т.е. программка читает файлик, сравнивает 2 и 3 столбцы и на выходе выдает что-то вроде этого (комментарии как пояснение):

901 1800000 1899999 ^90118\d{5}$ //первые 5 цифр статичные, остальные 5 - любые (\d{5}).
901 7000000 7299999 ^9017[0-2]\d{5}$ //4 начальных цифры статичные, 5 цифра - 0 или 1 или 2, остальные 5 цифр - любые(\d{5}).

Думаю задача довольно интересная для тех кто учится писать на C, C++ и т.п. (в памяти всплывают слова лектора о том, что работа со строками и подстроками - важный аспект программирования).
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
28.08.2012, 02:12     Делаем регулярные выражения
Посмотрите здесь:

C++ регулярные выражения
[C++] Регулярные выражения C++
Регулярные выражения C++
С++ и регулярные выражения C++
C++ Регулярные выражения
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
ForEveR
Модератор
Эксперт C++
 Аватар для ForEveR
7927 / 4709 / 318
Регистрация: 24.06.2010
Сообщений: 10,524
Завершенные тесты: 3
28.08.2012, 03:12     Делаем регулярные выражения #2
Labus, Ну если простые регексы - то легко. А если сложные... Ну как бэ каждое выражение можно выразить разными регексами по большому счету. А чего самому-то не сделать?
Avazart
 Аватар для Avazart
6904 / 5144 / 253
Регистрация: 10.12.2010
Сообщений: 22,629
Записей в блоге: 17
28.08.2012, 03:45     Делаем регулярные выражения #3
Нифига не понял, программа должна составлять регулярное выражение на основе файла с номерами?
Или просто делать выборку согласно заданной регулярки?
Labus
0 / 0 / 0
Регистрация: 28.08.2012
Сообщений: 3
28.08.2012, 12:38  [ТС]     Делаем регулярные выражения #4
Цитата Сообщение от Avazart Посмотреть сообщение
Нифига не понял, программа должна составлять регулярное выражение на основе файла с номерами?
Или просто делать выборку согласно заданной регулярки?

программа должна составлять регулярное выражение на основе файла с номерами:

Т.е. из записи вида 901 1800000 1899999 должна получать на выходе ^90118\d{5}$

^ - начало строки
$ - конец строки
\d{n} - любые n целых цифр ( \d{5} = последовательность из 5 любых целых от 0 до 9 цифр).
[0-2] - любая цифра из набора 0 1 2.
igorrr37
 Аватар для igorrr37
1593 / 1221 / 118
Регистрация: 21.12.2010
Сообщений: 1,868
Записей в блоге: 7
28.08.2012, 12:54     Делаем регулярные выражения #5
префикс 901 у обоих номеров одинаковый?
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
67
68
69
70
71
72
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
//#include <boost/regex.hpp>
 
/*
    901 1800000 1899999      ^90118\d{5}$
    901 7000000 7299999      ^9017[0-2]\d{5}$
*/
 
int main()
{
    std::fstream ifs("in.txt", std::ios::in);
    if(ifs.is_open())
    {
        std::string s1, s2, res;
        while(std::getline(ifs, s1))
        {
            //if(boost::regex_match(s1, boost::regex(" *\\d{3} +\\d{7} +\\d{7} *"))) // проверка строки на валидность
            //{
                std::stringstream ss(s1);
                ss >> s1;
                res += ("^" + s1);
                ss >> s1 >> s2;
                ss.clear();
                ss.str("");
                std::string::const_iterator cits1(s1.begin()), cits1End(s1.cend()), cits2(s2.begin());
                for(; cits1 != cits1End; ++cits1, ++cits2)
                {
                    if(*cits1 == *cits2)
                    {
                        res += *cits1;
                    }
                    else if(*cits1 != '0' || *cits2 != '9')
                    {
                        ss << '[' << *cits1 << '-' << *cits2 << ']';
                        res += ss.str();
                        ss.str("");
                    }
                    else
                    {
                        res += "\\d";
 
                    }
                }
                res += '$';
                std::size_t cntr;
                std::string::size_type ind, ind1;
                for(ind = 0; (ind = res.find("\\d", ind)) != std::string::npos; ind += 2) // заменяем последовательность из нескольких \d на \d{n}
                {
                    for(ind1 = ind + 2, cntr = 1; res.find("\\d", ind1) == ind1; ind1 += 2, ++cntr)
                        ;
                    if(ind1 != ind + 2)
                    {
                        ss << "\\d{" << ((ind1 - ind) / 2) << '}';
                        res.replace(ind, ind1 - ind, ss.str());
                        ss.str("");
                    }
                }
                std::cout << res << std::endl;
                res.clear();
            //}
            //else
                //std::cerr << "String:\n" << s1 << "\nis invalid" << std::endl;
        }
        ifs.close();
    }
    else
        std::cerr << "Unable to open file" << std::endl;
    return 0;
}
OhMyGodSoLong
~ Эврика! ~
 Аватар для OhMyGodSoLong
1234 / 983 / 42
Регистрация: 24.07.2012
Сообщений: 2,002
28.08.2012, 13:56     Делаем регулярные выражения #6
Окей, контрпример:
номера, начинающиеся на 901 700, могут дальше состоять только из чисел до 120000;
начинающиеся на 901 701 — до 140000;
и т. п.

Простыми регэкспами все случаи не покроешь.
Avazart
 Аватар для Avazart
6904 / 5144 / 253
Регистрация: 10.12.2010
Сообщений: 22,629
Записей в блоге: 17
28.08.2012, 14:41     Делаем регулярные выражения #7
Цитата Сообщение от Labus Посмотреть сообщение
программа должна составлять регулярное выражение на основе файла с номерами:
Т.е. из записи вида 901 1800000 1899999 должна получать на выходе ^90118\d{5}$
^ - начало строки
$ - конец строки
\d{n} - любые n целых цифр ( \d{5} = последовательность из 5 любых целых от 0 до 9 цифр).
[0-2] - любая цифра из набора 0 1 2.
Т.е. один один одно выражение ?
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.08.2012, 18:07     Делаем регулярные выражения
Еще ссылки по теме:

C++ Регулярные выражения с++
Регулярные выражения C++
C++ Регулярные выражения

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

Или воспользуйтесь поиском по форуму:
Labus
0 / 0 / 0
Регистрация: 28.08.2012
Сообщений: 3
28.08.2012, 18:07  [ТС]     Делаем регулярные выражения #8
Цитата Сообщение от ~OhMyGodSoLong~ Посмотреть сообщение
Окей, контрпример:
номера, начинающиеся на 901 700, могут дальше состоять только из чисел до 120000;
начинающиеся на 901 701 — до 140000;
и т. п.

Простыми регэкспами все случаи не покроешь.

Я нигде не указывал ограничения в использовании регэкспов. Все что было выше - всего лишь пример.

Строки всегда одинаковой длины.

901 1800000 1899999
901 7000000 7299999

Что мешает сравнивать посимвольно и делать регэкспы для каждой цифры номера? Например если сравнить в 1 строке последние 5 цифр 2 и 3 столбца - видно, что это могут быть любые цифры в промежутке от 0 до 9 и их можно заменить на \d{5}, а во 2 строке 70 и 72 отличаются только 2 цифрой. Такие вещи заменять [0-2], оставшиеся 5 заменяем на \d{5}...


Хотя, наверное это все-таки сложно.
Yandex
Объявления
28.08.2012, 18:07     Делаем регулярные выражения
Ответ Создать тему
Опции темы

Текущее время: 11:01. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru