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

Регулярные выражения, Поиск всех видов чисел в строке, CString - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.73
rusianvodka
0 / 0 / 0
Регистрация: 20.06.2013
Сообщений: 47
03.05.2014, 20:04     Регулярные выражения, Поиск всех видов чисел в строке, CString #1
Здравствуйте Уважаемые Дамы и Господа.
Уже какой вечер мучаюсь, пытаюсь понять как решить поставленную задачу.
Имеется строчка:
C
1
CString str = " int z, a=245;int b = 4.6;int b = 0xa11;int c = 011; for(int a = 1;i<123; i++) ";a=437-(-0xab24)"
Задача выдернуть из неё все числа.
С помощью:
C
1
str.FindOneOf(L"01234567890");
Получается найти число(любого вида, что очень важно).
Данной функцией я перевожу число из строкового типа в целочисленный.
C
1
swscanf_s(str, L"%i", &a);
Но если необходимо найти отрицательное число, возникают проблемы..
C
1
str.FindOneOf(L"-01234567890");
Находится первое вхождение символа без цифры.
Поэтому как я осознал, в решение поставленной задачи мне помогут регулярные выражения std regex(если это не так, буду рад вариантам иного решения данной задачи).
К сожалению в данной технологии я полный профан, поэтому хотел бы попросить помощи, совета по хорошим ресурсам, книгам, статьям где можно получить необходимые знания.
Если напишите шаблон решения поставленной задачи тоже буду примного благодарен, буду по нему понимать что как происходит.

Также задам вопрос наперёд, если решать поставленную задачу без знаков то всё облегчается и регулярные выражения не нужны.
Так как swscanf_s нужно передавать строчку где первые символы и есть необходимое число перевода.
А FindOneOf возвращает только номер от начала строки.
То возникает проблема, как передать адрес места, найденного числа в строке.

Данную проблему я решил с помощью очистки строчки до необходимого числа.(Если имеются другие варианты более простые или удобные также буду благодарен.)
Например:
C
1
CString str = " int z, a=245;int b = 4.6;int b = 0xa11;int c = 011; for(int a = 1;i<123; i++) ";a=437-(-0xab24)"
После моего быдлокодинга, строка становится такой:
C
1
CString str = "          245;int b = 4.6;int b = 0xa11;int c = 011; for(int a = 1;i<123; i++) ";a=437-(-0xab24)"
Дальше передавая str в swscanf_s число прекрасно распознаётся.
Но возникает другая проблема.
Как заставить FindOneOf перейти к поиску следующего числа 4.6.
Была идея убивать число 245 в строчке, но как это реализовать я даже не представляю.
Возможно меня всё также спасут регулярные выражения.
Надеюсь найдутся гуру регулярных выражений которые осилят данную простыню.
И я буду премного вам благодарен за советы и помощь.
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.05.2014, 20:04     Регулярные выражения, Поиск всех видов чисел в строке, CString
Посмотрите здесь:

поиск в строке всех повторений заданного слова, заменить его *. C++
C++ Как CString преобразовать к нормальной строке?
С++ и регулярные выражения C++
Найти сумму всех слов-чисел, содержащихся в строке C++
Сумма всех чисел в строке C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
BlackSpace
135 / 128 / 50
Регистрация: 15.03.2014
Сообщений: 275
03.05.2014, 22:17     Регулярные выражения, Поиск всех видов чисел в строке, CString #2
rusianvodka, как вариант использовать Boost.Regex.
Вариант решения задачи по нахождению всех чисел в строке. В том числе если числа заданы в научной форме. Вашу строку изменил немного.
C++
1
2
3
4
5
6
7
8
9
10
11
#include <boost/regex.hpp>
#include <iostream>
 
int main()
{
    std::string line = " int z, a=-+245;int b = -4.6567-55.6..,7..7;int b = 0xa11;int c = 01.1.1.2; -1.04e12for(int a = 1;i<123; i++) \";a=-437-(-0xab24) +3.12085E-12";
    boost::regex regex_float( "[\\+|-]?((\\d+\\.?\\d*)|(\\.\\d+))([e|E][\\+|-]?\\d+)?" );
 
    for ( boost::sregex_iterator it( line.begin(), line.end(), regex_float ); it != boost::sregex_iterator(); ++it )
        std::cout << *it << "  ";
}
Вот вывод программы
Код
+245  -4.6567  -55.6  7.  .7  0  11  01.1  .1  .2  -1.04e12  1  123  -437  -0  24  +3.12085E-12
Boost нужно предварительно установить.
Собирать нужно с ключиком -lboost_regex
rusianvodka
0 / 0 / 0
Регистрация: 20.06.2013
Сообщений: 47
03.05.2014, 23:20  [ТС]     Регулярные выражения, Поиск всех видов чисел в строке, CString #3
Просто божественно, то к чему я сам хотел придти) спасибо за решение задачи.
Но всё же спрошу, может посоветуете какой-либо ресурс, книги, место, где можно разобраться, научиться писать шаблоны. По примерам.
Как вы написали этот:
C
1
("[\\+|-]?((\\d+\\.?\\d*)|(\\.\\d+))([e|E][\\+|-]?\\d+)?");
Нашёл небольшую ошибку.. Например если число восьмеричное 011 он его распознает как 011 а не как 9.

Также вопрос по поводу CString и string.
Проблема в том что изначально строчка в формате CString(проект на мфс), поэтому как я понимаю единственный вариант решения данной проблемы так это нужно её перевести в формат string?
DU
1477 / 1053 / 45
Регистрация: 05.12.2011
Сообщений: 2,279
03.05.2014, 23:24     Регулярные выражения, Поиск всех видов чисел в строке, CString #4
вот тут пишут что вроде как без буста в рамках mfc можно оставаться:
http://www.codeproject.com/Articles/...essions-in-MFC
в случае если это не так - перевод CString в std::string - не проблема. У CString наверняка есть какой-нибудь метод, возвращающий c строку (const char*)

для быстрой проверки своих шаблонов - в сети полно онлайн проверялок\мэтчеров. в поисковике поищите
что-нибудь типа RegExp online.
BlackSpace
135 / 128 / 50
Регистрация: 15.03.2014
Сообщений: 275
03.05.2014, 23:30     Регулярные выражения, Поиск всех видов чисел в строке, CString #5
MFC не использовал никогда, так как не работаю в Windows.
Как boost будет будет воспринимать CString - понятия не имею.

О регулярных выражениях можно кратко прочитать на Wikipedia. Есть основные сведения.
Есть книги по регулярным выражениям - легко ищутся в google, но посоветовать ничего не могу, так как сам не читал ни одной по данной теме.

Чтобы немного разобраться - пробуйте писать самостоятельно сначала простые регулярные выражения и проверяйте их работу, например с помощью данного кода.
rusianvodka
0 / 0 / 0
Регистрация: 20.06.2013
Сообщений: 47
03.05.2014, 23:33  [ТС]     Регулярные выражения, Поиск всех видов чисел в строке, CString #6
Окей) спасибо, сам осознал что к этому и буду стремиться.
По глупости немного не подумал и написал не правильно про ошибки..(забыл что он только их выдёргивает, а не распознаёт )
Единственная проблема это то что он не выдёргивает 0xa11 целиком. Он делит пополам и получается 0 и 11.
BlackSpace
135 / 128 / 50
Регистрация: 15.03.2014
Сообщений: 275
04.05.2014, 03:10     Регулярные выражения, Поиск всех видов чисел в строке, CString #7
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от rusianvodka Посмотреть сообщение
Единственная проблема это то что он не выдёргивает 0xa11 целиком. Он делит пополам и получается 0 и 11.
Можно дописать регулярное выражение. Я опять изменил строку чтобы предусмотреть разные случаи. Обратите внимание на вывод программы, когда в строке встречаются случаи 0XxXxXFF или 0Xabc0x44 или 0xab240X2
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <boost/regex.hpp>
#include <iostream>
 
int main()
{
    std::string line = " int z, a=-+245;int b = -4.6567-55.6..,7..7;int b = -0x34 0xa11;0Xabc0x44}{-+0xE34 0XxXxXFF 0XABC12/0X45-0xf int c = 01.1.1.2; -1.04e12for(int a = 1;i<123; i++) \";a=-437-(-0xab240X2) +3.12085E-12";
    boost::regex regex_float( "[\\+|-]?((\\d+\\.?\\d*)|(\\.\\d+))([e|E][\\+|-]?\\d+)?([0x|0X](([A-F|a-f])+|(\\d)+)+)?" );
 
    for ( boost::sregex_iterator it( line.begin(), line.end(), regex_float ); it != boost::sregex_iterator(); ++it )
        std::cout << *it << "  ";
 
    return 0;
}
Вывод программы
Код
+245  -4.6567  -55.6  7.  .7  -0x34  0xa11  0Xabc0  44  +0xE34  0  0XABC12  0X45  -0xf  01.1  .1  .2  -1.04e12  1  123  -437  -0xab240  2  +3.12085E-12
rusianvodka
0 / 0 / 0
Регистрация: 20.06.2013
Сообщений: 47
06.05.2014, 00:02  [ТС]     Регулярные выражения, Поиск всех видов чисел в строке, CString #8
ох, я благодарен вам) спасибо.

Добавлено через 23 часа 34 минуты
У меня возник небольшой затык вопрос, никак не могу понять и разобрать как мне данные значения не выводить а например сохранить в строку, или массив. Как вообще взаимодействовать с найденными числами.
Пытался разобраться по шагам в студии наблюдая локальные и видимые переменные. Но к сожалению так и не понял.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.05.2014, 02:57     Регулярные выражения, Поиск всех видов чисел в строке, CString
Еще ссылки по теме:

Поиск чисел в строке символов C++
C++ Поиск всех тандемных повторов в строке
C++ Регулярные выражения

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

Или воспользуйтесь поиском по форуму:
BlackSpace
135 / 128 / 50
Регистрация: 15.03.2014
Сообщений: 275
06.05.2014, 02:57     Регулярные выражения, Поиск всех видов чисел в строке, CString #9
rusianvodka, покажу пример как можно добавить найденные лексемы в вектор. Вообще их как тип std::string можно почти куда угодно добавлять, потом переводить в double, int и другие типы.
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
#include <boost/regex.hpp>
#include <vector>
#include <iostream>
 
// функция вывода на экран элементов вектора
template < class T >
void PrintVec( std::vector < T >& vec ) {
    for_each( vec.begin(), vec.end(), []( T n ) {std::cout << n << " ";} );
    std::cout << std::endl;
}
 
int main() {
    std::string line =
            " int z, a=-+245;int b = -4.6567-55.6..,7..7;int b = -0x34 0xa11;0Xabc0x44}{-+0xE34 0XxXxXFF 0XABC12/0X45-0xf int c = 01.1.1.2; -1.04e12for(int a = 1;i<123; i++) \";a=-437-(-0xab240X2) +3.12085E-12";
    boost::regex regex_float( "[\\+|-]?((\\d+\\.?\\d*)|(\\.\\d+))([e|E][\\+|-]?\\d+)?([0x|0X](([A-F|a-f])+|(\\d)+)+)?" );
 
    std::vector < std::string > sVec; // вектор, куда будем складывать лексемы
    for ( boost::sregex_iterator it( line.begin(), line.end(), regex_float ); it != boost::sregex_iterator(); ++it )
        sVec.push_back( it->str() );
 
 
    PrintVec( sVec ); // распечатаем вектор
 
    return 0;
}
Для успешной сборки нужен ключик -std=c++11
Yandex
Объявления
06.05.2014, 02:57     Регулярные выражения, Поиск всех видов чисел в строке, CString
Ответ Создать тему
Опции темы

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