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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 11, средняя оценка - 4.73
rusianvodka
0 / 0 / 0
Регистрация: 20.06.2013
Сообщений: 47
#1

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

03.05.2014, 20:04. Просмотров 1760. Ответов 8
Метки нет (Все метки)

Здравствуйте Уважаемые Дамы и Господа.
Уже какой вечер мучаюсь, пытаюсь понять как решить поставленную задачу.
Имеется строчка:
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 в строчке, но как это реализовать я даже не представляю.
Возможно меня всё также спасут регулярные выражения.
Надеюсь найдутся гуру регулярных выражений которые осилят данную простыню.
И я буду премного вам благодарен за советы и помощь.
0
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.05.2014, 20:04
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Регулярные выражения, Поиск всех видов чисел в строке, CString (C++):

Подсчитайте количество скобок всех видов в строке - C++
Здравствуйте уважаемые любители и ценители языка С++! У меня к вам огромная просьба. На днях нужно сдать контрольную работу по предмету...

Поиск всех тандемных повторов в строке - C++
Поиск всех тандемных повторов в строке. Алгоритм Мейна-Лоренца. Помогите привести в действие, голова разрывается уже от 3 задачи.. ...

Как CString преобразовать к нормальной строке? - C++
// ... CRecordset *m_rs; // ... LVITEM lvi; // ... СString s; m_rs-&gt;GetFieldValue(j, s); lvi.pszText = ?;Тип lvi.pszText -...

Поиск в строке всех повторений заданного слова, замена их звездочками - C++
Привет, помогите написать программу по с++. Дело в том, что я в этом языке не разбираюсь абсолютно, и даже не пытался, так как учусь в...

Сумма всех чисел в строке - C++
Сумма всех чисел в строке. Кто нибудь может это транслировать на C++ #include &lt;stdio.h&gt; #include &lt;stdlib.h&gt; #include &lt;string.h&gt; ...

Определить соответствие разных видов скобок в строке - C++
проверить текстовый файл(содержащий текст) на предмет соответствия разных видов скобок, т.е при выборе одной из скобок должна указываться...

8
BlackSpace
137 / 130 / 52
Регистрация: 15.03.2014
Сообщений: 277
03.05.2014, 22:17 #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
1
rusianvodka
0 / 0 / 0
Регистрация: 20.06.2013
Сообщений: 47
03.05.2014, 23:20  [ТС] #3
Просто божественно, то к чему я сам хотел придти) спасибо за решение задачи.
Но всё же спрошу, может посоветуете какой-либо ресурс, книги, место, где можно разобраться, научиться писать шаблоны. По примерам.
Как вы написали этот:
C
1
("[\\+|-]?((\\d+\\.?\\d*)|(\\.\\d+))([e|E][\\+|-]?\\d+)?");
Нашёл небольшую ошибку.. Например если число восьмеричное 011 он его распознает как 011 а не как 9.

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

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

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

Чтобы немного разобраться - пробуйте писать самостоятельно сначала простые регулярные выражения и проверяйте их работу, например с помощью данного кода.
0
rusianvodka
0 / 0 / 0
Регистрация: 20.06.2013
Сообщений: 47
03.05.2014, 23:33  [ТС] #6
Окей) спасибо, сам осознал что к этому и буду стремиться.
По глупости немного не подумал и написал не правильно про ошибки..(забыл что он только их выдёргивает, а не распознаёт )
Единственная проблема это то что он не выдёргивает 0xa11 целиком. Он делит пополам и получается 0 и 11.
0
BlackSpace
137 / 130 / 52
Регистрация: 15.03.2014
Сообщений: 277
04.05.2014, 03:10 #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
1
rusianvodka
0 / 0 / 0
Регистрация: 20.06.2013
Сообщений: 47
06.05.2014, 00:02  [ТС] #8
ох, я благодарен вам) спасибо.

Добавлено через 23 часа 34 минуты
У меня возник небольшой затык вопрос, никак не могу понять и разобрать как мне данные значения не выводить а например сохранить в строку, или массив. Как вообще взаимодействовать с найденными числами.
Пытался разобраться по шагам в студии наблюдая локальные и видимые переменные. Но к сожалению так и не понял.
0
BlackSpace
137 / 130 / 52
Регистрация: 15.03.2014
Сообщений: 277
06.05.2014, 02:57 #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
0
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.05.2014, 02:57
Привет! Вот еще темы с ответами:

Определить сумму всех чисел в строке символов - C++
Доброго времени суток. Помогите пожалуйста. Задачка по С++. Задание: посчитать сумму всех чисел которые встречаются в СТРОКЕ СИМВОЛОВ....

Поиск чисел в строке символов - C++
Прошу помочь с алгоритмом,т к сама не понимаю. Пыталась записать каждое число в отдельную строку,а потом призвоить float строке,но это...

Найти и вывести сумму всех дробных чисел в строке - C++
Найти и вывести сумму всех дробных чисел в строке. Размер строки 80. Вводится пользователь, но проблема в нахождении самих дробных чисел....

Найти сумму всех слов-чисел, содержащихся в строке - C++
С клавиатуры вводиться строка длинной не более 100 символов. Строка состоит из слов, отделённых друг от друга один или несколькими...


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

Или воспользуйтесь поиском по форуму:
9
Yandex
Объявления
06.05.2014, 02:57
Ответ Создать тему
Опции темы

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