Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.91/11: Рейтинг темы: голосов - 11, средняя оценка - 4.91
3 / 3 / 4
Регистрация: 18.11.2013
Сообщений: 172

Регулярные выражения или традиционные методы

17.02.2017, 12:36. Показов 2340. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Допустим имеется строка:

C++
1
string content = "another word?name:Вася:end*anoher_word.name:Петя:end\\:'name:Кирилл:end";
Как можно вытащить из нее нужные мне участи, то есть Вася, Петя, Кирилл.

Использовать регулярные выражения или есть традиционные методы?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
17.02.2017, 12:36
Ответы с готовыми решениями:

Регулярные выражения. Методы matches и find()
Начал изучать регулярные выражения и накопилось несколько вопросов: 1. Написал такую вот программу. При вводе: 123.02 345.6 +45.4...

ЧПУ. Замена строк, регулярные выражения. Как правильно использовать переменную в регулярные выражения ?
Здравствуйте! Решил реализовать ЧПУ на своем сайте. Первый этап это замена всех реальных ссылок на чпу ссылки. Так вот при замене я...

Регулярные выражения в MySQL? или
В таблице есть поле Phone. Телефон в нем может храниться ну как душе угодно, например: 8(928)000-11-22 8 (928) 000-11-22 89280001122 ...

21
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
17.02.2017, 13:41
Лучший ответ Сообщение было отмечено b00006 как решение

Решение

То есть забрать содержимое между
name: и :end?
Можно, конечно, и стандартными методами, но регулярками это выглядит проще. Думаю, тут дело вкуса.

Добавлено через 8 минут
Стандартный способ:
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <string>
 
int main()
{
    setlocale(LC_ALL, "");
    const std::string content = "another word?name:Вася:end*anoher_word.name:Петя:end\\:'name:Кирилл:end", beg = "name:", end = ":end";
    for (size_t pos1 = content.find(beg), pos2 = content.find(end, pos1 + beg.length());
         pos1 != std::string::npos && pos2 != std::string::npos;
         pos1 = content.find(beg, pos2+end.length()), pos2 = content.find(end, pos1 + beg.length()))
        std::cout << content.substr(pos1 + beg.length(), pos2 - pos1 - beg.length()) << std::endl;
}
Добавлено через 2 минуты
На регулярках:
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <regex>
#include <string>
 
int main()
{
    setlocale(LC_ALL, "");
    const std::string content = "another word?name:Вася:end*anoher_word.name:Петя:end\\:'name:Кирилл:end";
    std::regex reg("name:(.*?):end");
    for (auto it = std::sregex_iterator(content.begin(), content.end(), reg); it != std::sregex_iterator(); ++it)
        std::cout << it->str(1) << std::endl;
}
2
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
17.02.2017, 13:49
Цитата Сообщение от b00006 Посмотреть сообщение
Использовать регулярные выражения или есть традиционные методы?
С таким простым форматом строки, я бы советовал посмотреть в сторону sscanf (именно с двумя "s" в начале). Впрочем, это те же самые регулярки, только с более урезанным функционалом.

Но, вообще, у регулярок под капотом виртуальная машина, которая традиционные методы и крутит. Так что всегда можно скомпилировать выражение в уме и настучать от руки то самое, что в виртуальной машине. Код, конечно, будет быстрей, но длиннее.
1
Эксперт CЭксперт С++
 Аватар для liv
5120 / 4573 / 855
Регистрация: 07.10.2015
Сообщений: 9,462
17.02.2017, 14:14
Еще вариант: На С с помощью токенов.
Имейте в виду, строка портится. Поэтому исходную строку надо скопировать в буфер.
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
#include <string.h>
#include <stdio.h>
 
char * content = "another word?name:Вася:end*anoher_word.name:Петя:end\\:'name:Кирилл:end";
 
int main()
{
    char* pStr;
    char* pSep = " ?:*.\'";
    char* pName = "name";
    char str[256];
 
    strcpy(str, content);
 
    pStr = strtok(str, pSep);
    while(pStr)
    {
        if (!strcmp(pStr, pName))
        {
            pStr = strtok(NULL, pSep);
            if (pStr)
                printf("name = %s\n", pStr);
            else
                break;
        }
        pStr = strtok(NULL, pSep);
    }
    return 0;
}
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
17.02.2017, 14:34
Лучший ответ Сообщение было отмечено b00006 как решение

Решение

Вот еще один вариант на регулярках
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include<iostream>
#include<string>
#include<regex>
 
int main()
{
    std::string input = "another word?name:Вася:end*anoher_word.name:Петя:end\\:'name:Кирилл:end";
    std::regex r("name:(.*?):end");
    std::smatch sm;
 
    while(std::regex_search(input, sm, r))
    {
        std::cout << sm[1] << '\n';
        input = sm.suffix();
    }
}
Цитата Сообщение от b00006 Посмотреть сообщение
Использовать регулярные выражения или есть традиционные методы?
Думаю с регулярками код чище и понятнее будет...
1
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
17.02.2017, 15:11
Цитата Сообщение от sys_beginner Посмотреть сообщение
C++
1
input = sm.suffix();
И на каждой итерации мы генерируем новую строку с этим самым суффиксом. За время пропорциональное размеру строки, то есть за время пропорциональное размеру еще не просмотренного регуляркой текста. Да здравствует квадратичная сложность алгоритма, помноженная на постоянные обращения к динамической памяти. Руки бы поотрывать тому, кто такие строчки на http://en.cppreference.com и http://www.cplusplus.com добавлял.
А использовать в таких циклах надо std::regex_iterator.
2
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
17.02.2017, 15:15
Renji,
Учту, спасибо
1
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
17.02.2017, 15:17
Цитата Сообщение от Renji Посмотреть сообщение
Руки бы поотрывать тому, кто такие строчки на http://en.cppreference.com и http://www.cplusplus.com добавлял.
Да, тоже сильно удивился когда увидел это в примерах.
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
17.02.2017, 15:26
Но выглядит компактно

Добавлено через 37 секунд
Тобишь как я понял с итераторами match-инг будет всего 1 раз
И новые строки в цикле не нужны
1
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
17.02.2017, 15:34
Цитата Сообщение от sys_beginner Посмотреть сообщение
Тобишь как я понял с итераторами match-инг будет всего 1 раз
Э... Вы откуда match-инг один раз взяли?
C++
1
2
3
4
5
6
7
8
int main()
{
    const char str[]="another word?name:Вася:end*anoher_word.name:Петя:end\\:'name:Кирилл:end";
    std::regex regex("name:(.*?):end");
    for(std::cregex_iterator match(str,str+sizeof(str),regex); match!=std::cregex_iterator(); ++match)
        std::cout<<match->str(1)<<std::endl;
    return 0;
}
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
17.02.2017, 15:37
Цитата Сообщение от Renji Посмотреть сообщение
Э... Вы откуда match-инг один раз взяли?
Цитата Сообщение от Renji Посмотреть сообщение
C++
1
std::cregex_iterator match(str,str+sizeof(str),regex);
Тут под капотом разве не 1 раз матчинг будет? Первая часть цикла ж один раз выполнится
Далее как я понимаю создается итератор с набором найденных вхождений
И соответственно проходим по этому набору
Т.е поиск на совпадения происходит 1 раз, не?
1
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
17.02.2017, 15:44
Цитата Сообщение от sys_beginner Посмотреть сообщение
Тобишь как я понял с итераторами match-инг будет всего 1 раз
И новые строки в цикле не нужны
regex_iterator проходят по последовательности, чем-то похоже на istream_iterator.
2
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
17.02.2017, 15:45
Цитата Сообщение от sys_beginner Посмотреть сообщение
Тут под капотом разве не 1 раз матчинг будет?
Нет, конечно. Наиболее вероятная реализация будет такой:
1) Конструктор итератора сохраняет указатели на начало и конец строки.
2) Итератор делает поиск между началом и концом строки.
3) Итератор передвигает начало строки, на конец захваченного регуляркой текста.
4) Результаты идут на печать.
5) Начало и конец еще не совпадают? Го на пункт 2.
2
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
17.02.2017, 15:45
Цитата Сообщение от sys_beginner Посмотреть сообщение
Т.е поиск на совпадения происходит 1 раз, не?
Поиск следующего совпадения происходит при инкременте итератора.
1
93 / 69 / 22
Регистрация: 17.10.2011
Сообщений: 235
17.02.2017, 15:46
На регулярках:
C++
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include <regex>
#include <string>
 
int main()
{
    setlocale(LC_ALL, "");
    const std::string content = "another word?name:Вася:end*anoher_word.name:Петя:end\\:'name:Кирилл:end";
    std::regex reg("name:(.*?):end");
    for (auto it = std::sregex_iterator(content.begin(), content.end(), reg); it != std::sregex_iterator(); ++it)
        std::cout << it->str(1) << std::endl;
}
предлагаю поменять regex на
C++
1
"name:([a-zA-zа-яА-Я-_]*?):end"
, чтобы обрабатывались строчки типа
C++
1
"name:aadfname:NAME:end"
и вообще вот https://regex101.com/r/Dzl93t/1
1
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
17.02.2017, 15:51
Цитата Сообщение от vndtta Посмотреть сообщение
предлагаю поменять regex на "name:([a-zA-zа-яА-Я-_]*?):end", чтобы обрабатывались строчки типа "name:aadfname:NAME:end"
Дык они и так обрабатываются. Работающие в цикле регулярки, дважды один и тот же текст не захватывают. Так что второе NAME как маркер начала текста восприниматься не должно.
1
93 / 69 / 22
Регистрация: 17.10.2011
Сообщений: 235
17.02.2017, 15:59
Цитата Сообщение от Renji Посмотреть сообщение
Дык они и так обрабатываются. Работающие в цикле регулярки, дважды один и тот же текст не захватывают. Так что второе NAME как маркер начала текста восприниматься не должно.
я имел ввиду, что нужно ограничить символы, которые могут попасться в имени - странновато немного, если в имени есть двоеточие
что будет если обрабатывать строку типа "name:name:name:NAME:end" ? результат будет "name:name:NAME" - по-моему это не совсем то, что хотелось бы увидеть
1
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
17.02.2017, 16:09
Цитата Сообщение от Renji Посмотреть сообщение
Нет, конечно. Наиболее вероятная реализация будет такой:
Понятно, спасибо

Добавлено через 2 минуты
Сейчас кстати читаю книжку по С++. Скоро дойду до главы с описанием <regex>. Подтяну этот вопрос
1
Форумчанин
Эксперт CЭксперт С++
 Аватар для MrGluck
8216 / 5047 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
17.02.2017, 16:22
Цитата Сообщение от vndtta Посмотреть сообщение
"name:([a-zA-zа-яА-Я-_]*?):end"
строка "name:obj:NAME:end"

У ТС вполне конкретный случай, про вложенность name не говорилось

Добавлено через 2 минуты
А если просто хотите исключить двоеточие, то достаточно регулярки "name:([^:]*?):end"

Добавлено через 3 минуты
Но решать проблему двоеточием - костыль.
Можно переписать регулярку вот так:
C++
1
".*name:(.*):end"
.* жадная реализация отожмёт всё что можно перед name:
Для надёжности можно явно указать что группировка должна быть ленивой
C++
1
".*name:(.*?):end"
1
2784 / 1937 / 570
Регистрация: 05.06.2014
Сообщений: 5,602
17.02.2017, 16:31
Цитата Сообщение от MrGluck Посмотреть сообщение
.* жадная реализация отожмёт всё что можно перед name:
Поправка: жадная реализация отожмет все что можно перед самым последним name:. Так что если не хочется двоеточий в соответствии - надо явно задавать необходимый чарсет.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
17.02.2017, 16:31
Помогаю со студенческими работами здесь

Регулярные выражения. Поставить ! или ? в конце слова
Допустим у нас есть слово, которое мы вводим, затем нам предлагают выбрать что поставить в конце, допустим ! или ?, как это сделать?...

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

Регулярные выражения. Предложение начинается с - а заканчивается на ! или ?
Помогите вытащить из текста прямую речь. Предложение начинается с - а заканчивается на ! или ?

Регулярные выражения или if else для работы простейшего интерпретатора
у меня такой вопрос я делаю компилятор примитивный тоесть есть if else then и я их обрабатываю есть строка if(i&gt;==j) var+=...

Парсинг JSON - регулярные выражения, Collections или сериализация?
Имеется JSON-строка, имеющая в своем теле несколько типов данных. Конкретно какие, я просматриваю ответ с сервера через Чарли (Charles);...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru