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

Парсинг адресной строки, хочу извлечь индекс и название города - C++

Восстановить пароль Регистрация
 
 
Рейтинг: Рейтинг темы: голосов - 15, средняя оценка - 4.67
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
25.12.2012, 18:45     Парсинг адресной строки, хочу извлечь индекс и название города #1
Всем доброго дня.

Хочу распарсить такой вот файлик:

------------------------------------------------------------
125414, Москва г, Петрозаводская ул, дом № 24а, корпус 2
125493, Москва г, Смольная ул, дом № 5
Москва г, Онежская ул, дом № 11.11.2008"
------------------------------------------------------------

Считать индекс в отдельный массив, потом название города в отдельный массив, скопировать их в общий массив символов и вывести в консоль. Нашел на сайте (cyberforum) пример, сделал по аналогии, чет ни фига не работает, гляньте, если не сложно:

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
char zipcode[10] = { '0' };
char city[20] = { '0' };
char finalstring[30] = { '0' };
 
ifstream parsing_f ("parse_addresses.txt");
        while (!parsing_f.eof())
    {       
        parsing_f.getline(buff, 1024, '\n');
        
        char*  ptr_zip = buff;
            for (int zc = 0; zc < 10; zc++)
                zipcode[zc] = ' ';
        while ((ptr_zip = get_zipcode (zipcode, ptr_zip)))
        {
         for (int i = 0; i < 10; i++)
             finalstring[i] = zipcode[i]; }
            
        for (int ct = 0; ct < 20; ct++)
                city[ct] = ' ';
        const char * ptr_city = buff;
        while ((ptr_city = get_city(city, ptr_city, " г,")))
        {
         for (int i = 10; i < 30; i++)
             finalstring[i] = city[i]; }
                
        finalstring[30] = '\0';
        cout << finalstring << endl;
            
    }
        
    parsing_f.close();  
 
//функции получения адреса и индекса:
 
char*  get_zipcode(char* strzip, char* sourcestr) {
    
    char* ps = sourcestr;
    for (int i = 0; *ps && i < 6 &&  isdigit(*ps); i++)
    *strzip++ = *ps++;
 
    return ps;
}
 
const char*  get_city(char* strcity, const char* sourcestr, const char* searchstr) {
    const char* ps = strstr(sourcestr, searchstr);
    if(! ps)
        return NULL;
    while ((&sourcestr[0] != ps) && (*ps != ' '))
        ps--;
    while (*ps && *ps != ' ')
        *++strcity = *ps++;   
    return ps;
}
В функии, которая возвращает адрес символы, по которым осуществляется поиск, идут после названия города. Т.е. я сначала хочу "отмотать" указатель на название города, а потом уже считать его в массив символов. Поэтому и проверка: (&sourcestr[0] == ps) - чтобы не выйти за границы массива - город может начинаться с первого же символа в строке.

ЗЫ Только не советуйте boost и прочее, задачка вроде элементарная.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
25.12.2012, 18:45     Парсинг адресной строки, хочу извлечь индекс и название города
Посмотрите здесь:

!извлечь из строки числа! C++
Строки. Спортивные команды одного города. C++
получить индекс строки C++
Как извлечь только цифры из строки C++
Извлечь число из строки C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 17
25.12.2012, 19:03     Парсинг адресной строки, хочу извлечь индекс и название города #2
Элементарное как раз с boost/regex. а главное гибко
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
25.12.2012, 20:26  [ТС]     Парсинг адресной строки, хочу извлечь индекс и название города #3
Цитата Сообщение от Avazart Посмотреть сообщение
Элементарное как раз с boost/regex. а главное гибко
Судя по всему (складывается у меня ощущение), что без boost'a в С++ вообще делать нечего.
Как без него раньше обходились? (вопрос риторический, of course)

Придется изучить.
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 17
25.12.2012, 20:33     Парсинг адресной строки, хочу извлечь индекс и название города #4
Обходились, но щас то он есть зачем велосипеды писать ?

Более того regex теперь уже есть в STL в новом стандарте, поставьте если это допустимо компилятор с потдержкой С++11 и используйте std::regex
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
25.12.2012, 20:53  [ТС]     Парсинг адресной строки, хочу извлечь индекс и название города #5
Цитата Сообщение от Avazart Посмотреть сообщение
Обходились, но щас то он есть зачем велосипеды писать ?

Более того regex теперь уже есть в STL в новом стандарте, поставьте если это допустимо компилятор с потдержкой С++11 и используйте std::regex
У меня компилятор с поддержкой С++ 11 (VS 2010), просто не изучил ещё эти возможности, но собираюсь.
Есть вроде как книжка по нему: "Beyond the C++ Standard Library:An Introduction to Boost", хочу прочесть.
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 17
25.12.2012, 21:01     Парсинг адресной строки, хочу извлечь индекс и название города #6
Я доку по boost/regex переводил читал, но только в новом стандарте немного другие регулярки что в бусте.
(тема std::regex и boost::regex )

А в VS 2010 как я помню только намек на новый стандарт, а в реальности...
Для VS 2010 есть собственно инсталятор boost, так что проблем в данном случае ноль ... только пути прописать...
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
25.12.2012, 21:13  [ТС]     Парсинг адресной строки, хочу извлечь индекс и название города #7
Цитата Сообщение от Avazart Посмотреть сообщение
Я доку по boost/regex переводил читал, но только в новом стандарте немного другие регулярки что в бусте.
(тема std::regex и boost::regex )

А в VS 2010 как я помню только намек на новый стандарт, а в реальности...
Для VS 2010 есть собственно инсталятор boost, так что проблем в данном случае ноль ... только пути прописать...
Только намек на новый стандарт? Хз, я пытался использовать некоторые фичи, типа автовыведения указателей при помощи ключевого слова auto, вроде сработало. А так я ещё слишком мало знаю в принципе, чтобы о полноте поддержки стандартов рассуждать) Хотя - может тогда сразу VS 2012 поставить, там по идее поддержка должна быть полнее?
Доки совсем скучно читать, вроде бы в "Beyond the C++ Standard Library:An Introduction to Boost" поувлекательнее написано, я скачал, но никак не начну читать) А что инглиш и в оригинале, так это только плюс, нет погрешностей русского перевода.
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 17
25.12.2012, 21:27     Парсинг адресной строки, хочу извлечь индекс и название города #8
Ну собственно несмотря на мой плохой английский, дока мне показалась толковой
Добавлено через 5 минут
Насчет VC++ она мне никогда не нравилась, я недавно только поставли MinGW что в подписи у niXman и высатвил его в CodeBlocks

А так вообще использую Builder из-за VCL и Indy, а у него со стандартом голяк пока и boost 1.39 стоит частично.
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
25.12.2012, 21:32  [ТС]     Парсинг адресной строки, хочу извлечь индекс и название города #9
Цитата Сообщение от Avazart Посмотреть сообщение
Ну собственно несмотря на мой плохой английский, дока мне показалась толковой
Добавлено через 5 минут
Насчет VC++ она мне никогда не нравилась, я недавно только поставли MinGW что в подписи у niXman и высатвил его в CodeBlocks

А так вообще использую Builder из-за VCL и Indy, а у него со стандартом голяк пока и boost 1.39 стоит частично.
Понятно, но это все серьезный подход, а я пока так, балуюсь... Для моих нужд и VS 2010 сойдет.
prazuber
108 / 108 / 3
Регистрация: 29.04.2010
Сообщений: 240
25.12.2012, 22:30     Парсинг адресной строки, хочу извлечь индекс и название города #10
О боже, какой boost, какой regex? Вы мне можете объяснить, зачем они здесь?

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
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string>
 
struct CityIndex {
    std::string name;
    int index;
};
 
int main()
{
    std::ifstream fi("input.txt");
    std::string str;
    std::vector<CityIndex> vec;
    int index = 0;
 
    while (std::getline(fi, str)) {
        std::string name;
        std::istringstream ss(str);
 
        if (ss >> index) {
            ss.ignore(1); // ignore ','
        } else {
            ss.clear();
        }
 
        ss >> name;
 
        CityIndex ci = {name, index};
        vec.push_back(ci);
    }
 
    for (size_t i = 0; i < vec.size(); ++i) {
        std::cout << vec[i].index << ' ' << vec[i].name << std::endl;
    }
}
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
25.12.2012, 23:17  [ТС]     Парсинг адресной строки, хочу извлечь индекс и название города #11
Цитата Сообщение от prazuber Посмотреть сообщение
О боже, какой boost, какой regex? Вы мне можете объяснить, зачем они здесь?
Ну я, конечно, STL знаю не сильно лучше, чем boost (т.е. вообще никак) и в этом коде мало что понял, но сдается мне, что тут что-то не так. Вот строки, которые нужно распарсить:

--------------------
125414, Москва г, Петрозаводская ул, дом № 24а, корпус 2
125493, Москва г, Смольная ул, дом № 5
Москва г, Онежская ул, дом № 11.11.2008""
--------------------


Прикол в том, что индекс может находиться в начале строки, а может и не находиться, т.е. его может не быть (я для проверки использовал isdigit), плюс индекс - это всегда 6 цифр (у меня в цикле for это проверяется). Город может быть какой угодно и находиться в любом месте строки, не обязательно Москва, стабильно лишь то, что после названия города идут символы: " г,", каким образом в структуру копируется именно то, что нужно?? С примером с указателями там хоть "прозрачно" все было, а тут...
prazuber
108 / 108 / 3
Регистрация: 29.04.2010
Сообщений: 240
25.12.2012, 23:28     Парсинг адресной строки, хочу извлечь индекс и название города #12
Excogit8er, да, я не совсем верно понял задание. Проясните пожалуйста, город может находится в совсем любом месте строки? Я исходил из формата

[индекс ]<ИмяГорода> г, мусор мусор мусор


Является ли

125493, Смольная ул, Москва г, дом № 5

одним из возможных вводов?

Также, что делать, если индекс не из 6 цифр? Что делать, если индекс отсутствует? (я в этом случае брал предыдущий индекс)

Опишите, пожалуйста, задачу, желательно с примером ввода и вывода.
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
25.12.2012, 23:45  [ТС]     Парсинг адресной строки, хочу извлечь индекс и название города #13
Цитата Сообщение от prazuber Посмотреть сообщение
Excogit8er, да, я не совсем верно понял задание. Проясните пожалуйста, город может находится в совсем любом месте строки? Я исходил из формата

[индекс ]<ИмяГорода> г, мусор мусор мусор


Является ли

125493, Смольная ул, Москва г, дом № 5

одним из возможных вводов?
>> 125493, Смольная ул, Москва г, дом № 5
Ага, или, например, так:
125493, Московская область, Ногинск г, Нижняя ул, дом № 5

Т.е. реально, по сути, он может быть где угодно в строке. Ну и я не то, чтобы в спор, просто хочу для себя разобраться - а чем плох такой подход:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const char * ptr_city = buff;
        while ((ptr_city = get_city(city, ptr_city, " г,")))
        {
         for (int i = 10; i < 30; i++)
             finalstring[i] = city[i]; }
 
const char*  get_city(char* strcity, const char* sourcestr, const char* searchstr) {
    const char* ps = strstr(sourcestr, searchstr);
    if(! ps)
        return NULL;
    while ((&sourcestr[0] != ps) && (*ps != ' '))
        ps--;
    while (*ps && *ps != ' ')
        *++strcity = *ps++;   
    return ps;
}
Нашли " г,", отмотали указатель на название города, скопировали (до первого пробела).
Типа это вчерашний день и так никто не делает?

Добавлено через 5 минут
>> Что делать, если индекс отсутствует? (я в этом случае брал предыдущий индекс)
Не, если индекс отсутствует - то и черт с ним, берем только название города (предыдущий индекс тут как-то не к месту, ведь это уже другая строка и может быть даже другой город).

А задача - есть, скажем, несколько строк, откуда нужно вытащить индекс, город (ну и на самом деле улицу тоже, но это я уже по аналогии и сам доделаю). Ну и все, собственно (там дальше уже понятно все - можно в консоль вывести, можно скопировать в отдельную строку и т.д.)
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 17
26.12.2012, 01:51     Парсинг адресной строки, хочу извлечь индекс и название города #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
#include <iostream>
#include <string>
#include <fstream>
#include <boost/regex.hpp>
 
using namespace std;
//----------------------------------------------------------------------
int main()
{
ifstream ifs("1.txt");
if(!ifs) { cerr<<"file not found"<<endl; return 0; }
 
string s;
 
boost::regex re("([[:digit:]]{0,6}),?\\s*(.*?)\\sг,(.*)");
boost::smatch m;
 
while (getline(ifs,s) &&  boost::regex_search(s,m,re) )
  {
    std::cout<<"<"<< m[1] <<">  ["<<m[2]<<"]"<<endl;
  }
 
return 0;
}
Добавлено через 2 минуты
Дело в том что саму регулярку можно тоже подгружать с файла, а значит можно будет в определенной степени менять поведение программы без перекомпиляции.
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
26.12.2012, 11:22  [ТС]     Парсинг адресной строки, хочу извлечь индекс и название города #15
Цитата Сообщение от Avazart Посмотреть сообщение
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
#include <iostream>
#include <string>
#include <fstream>
#include <boost/regex.hpp>
 
using namespace std;
//----------------------------------------------------------------------
int main()
{
ifstream ifs("1.txt");
if(!ifs) { cerr<<"file not found"<<endl; return 0; }
 
string s;
 
boost::regex re("([[:digit:]]{0,6}),?\\s*(.*?)\\sг,(.*)");
boost::smatch m;
 
while (getline(ifs,s) &&  boost::regex_search(s,m,re) )
  {
    std::cout<<"<"<< m[1] <<">  ["<<m[2]<<"]"<<endl;
  }
 
return 0;
}
Добавлено через 2 минуты
Дело в том что саму регулярку можно тоже подгружать с файла, а значит можно будет в определенной степени менять поведение программы без перекомпиляции.
Пасиб. Аццкая жесть какая-то, особенно это регулярное выражение: boost::regex re("([[:digit:]]{0,6}),?\\s*(.*?)\\sг,(.*)");
Но изящней намного варианта с функциями-указателями, спору нет. В общем, почитаю про boost::regex, заинтересовало.

PS. Скажи, а вот такое тоже решается через boost:regex?
Считываем весь файл в string и потом сравниваем?
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 17
26.12.2012, 14:42     Парсинг адресной строки, хочу извлечь индекс и название города #16
Цитата Сообщение от Excogit8er Посмотреть сообщение
PS. Скажи, а вот такое тоже решается через boost:regex?
Можно,но нет такой особой необходимости, ничто там не мешает считывать манипулируя потоками как ранее приведенный пример, не используя регулярки.

Добавлено через 1 минуту
Цитата Сообщение от Excogit8er Посмотреть сообщение
Аццкая жесть какая-то, особенно это регулярное выражение: boost::regex re("([[:digit:]]{0,6}),?\\s*(.*?)\\sг,(.*)");
Да основное время тратится именно на формирование этого выражения и его тестирование, зато код почти не меняется если фомат файла поменялся.

Я обычно заглядываю сюда http://regexpr.ru/cheatsheet/ , http://regexpr.ru/

Добавлено через 1 час 44 минуты
Кстати попробовал в VC++2010, работает если заменить и с std::regex
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
26.12.2012, 15:13  [ТС]     Парсинг адресной строки, хочу извлечь индекс и название города #17
Цитата Сообщение от Avazart Посмотреть сообщение
Можно,но нет такой особой необходимости, ничто там не мешает считывать манипулируя потоками как ранее приведенный пример, не используя регулярки.
Предыдущее, это которое с std::istringstream выше по теме?

Да основное время тратится именно на формирование этого выражения и его тестирование, зато код почти не меняется если фомат файла поменялся.
Я обычно заглядываю сюда http://regexpr.ru/cheatsheet/ , http://regexpr.ru/
Ага, спасибо. Чувствую, мне в ближайшее время есть что читать )

Кстати попробовал в VC++2010, работает если заменить и с std::regex
Вот прямо скопировать, заменив boost::regex на std::regex? У меня intellismart (или как его) сразу же подчеркивает слово regex, типа identifier undefined. Может нужно еще какие-нить #include прописать?
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 17
26.12.2012, 15:16     Парсинг адресной строки, хочу извлечь индекс и название города #18
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 "stdafx.h"
#include <windows.h>
 
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <regex>
 
using namespace std;
//----------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
::system("chcp 1251");
ifstream ifs("1.txt");
if(!ifs) { cerr<<"file not found"<<endl; return 0; }
 
 
string s;
string sre= "([[:digit:]]{0,6}),?\\s*(.*?)\\sг,(.*)";
 
regex re(sre);
smatch m;
 
while (getline(ifs,s) &&  regex_search(s,m,re) )
  {
    cout<<"<"<< m[1] <<">  ["<<m[2]<<"]"<<endl;
  }
    
::system("pause");
return 0;
}
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
26.12.2012, 17:02  [ТС]     Парсинг адресной строки, хочу извлечь индекс и название города #19
Цитата Сообщение от Avazart Посмотреть сообщение
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 "stdafx.h"
#include <windows.h>
 
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <regex>
 
using namespace std;
//----------------------------------
int _tmain(int argc, _TCHAR* argv[])
{
::system("chcp 1251");
ifstream ifs("1.txt");
if(!ifs) { cerr<<"file not found"<<endl; return 0; }
 
 
string s;
string sre= "([[:digit:]]{0,6}),?\\s*(.*?)\\sг,(.*)";
 
regex re(sre);
smatch m;
 
while (getline(ifs,s) &&  regex_search(s,m,re) )
  {
    cout<<"<"<< m[1] <<">  ["<<m[2]<<"]"<<endl;
  }
    
::system("pause");
return 0;
}

В общем, ничего не подчеркивается и даже комплируется. Но и в консоль ничего не выводится при запуске )
При этом файл я, само собой, переименовал (и закрыл после цикла while)

Кстати, воспользовался твоим советом, скачал инсталлятор boost'a, отметил там при установке, что нужна именно 2010 и выставил галочки multithreaded, single threaded и прочее. Все установилось, но тока никаких бустов VS не видит ни фига, видимо, там вручную надо прописывать пути к директориям и библиотекам. Я думал, исталлятор избавляет от этой приятной задачи... Нах он тогда нужен - вообще не ясно.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.12.2012, 17:07     Парсинг адресной строки, хочу извлечь индекс и название города
Еще ссылки по теме:

C++ Из строки извлечь символы операций в стек, а цифры - в другую строку
C++ Как извлечь числа из строки
C++ Строки. Игра в города

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

Или воспользуйтесь поиском по форуму:
Avazart
 Аватар для Avazart
6897 / 5137 / 252
Регистрация: 10.12.2010
Сообщений: 22,578
Записей в блоге: 17
26.12.2012, 17:07     Парсинг адресной строки, хочу извлечь индекс и название города #20
Цитата Сообщение от Excogit8er Посмотреть сообщение
В общем, ничего не подчеркивается и даже комплируется. Но и в консоль ничего не выводится при запуске )
При этом файл я, само собой, переименовал (и закрыл после цикла while)
Ну не знаю если файл находится, значит нет совпадений с регуляркой.
Может содержание файла изменилось?

Цитата Сообщение от Excogit8er Посмотреть сообщение
Все установилось, но тока никаких бустов VS не видит ни фига, видимо, там вручную надо прописывать пути к либам и библиотекам.
Ну я об этом и говорил что нужно прописывать пути руками в проекте как и для любой сторонней либы...
Цитата Сообщение от Excogit8er Посмотреть сообщение
Я думал, исталлятор избавляет от этой приятной задачи... Нах он тогда нужен - вообще не ясно.
Чтоб не компилировать исходники вручную ...
Yandex
Объявления
26.12.2012, 17:07     Парсинг адресной строки, хочу извлечь индекс и название города
Ответ Создать тему
Опции темы

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