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

Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? - C++

Восстановить пароль Регистрация
 
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
30.01.2013, 17:39     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? #1
Привет)

В общем, вопрос в том, как сделать правильнее и "красивее", что ли, такое вот задание.

Есть файлик, в котором заданное кол-во значений разделено точкой с запятой.
По типу:
value1;value2;value3;value4;value5; (et cetera)

Мне нравится вариант с регексом.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{ 
ifstream inpf ("C:\\datafile.txt", std::ios_base::in);
if (!inpf) cout << "datafile is missing";
else cout << "processing ...\n\n";
string data;                
boost::regex reg("(\\d{15});(\\d{16});(.*?);(.*?);(.*?);");         
boost::smatch m;
   while (std::getline (inpf, data)) {                      
    if (boost::regex_search(data, m, reg ))                 
            {
                cout << m[2] << "     " << m[5] << endl;
            }   
                else 
                cout << endl;
        }
inpf.close();
Все бы ок, но прикол в том, что значений этих 35, а мне нужны, грубо говоря, только 3е и 19е
Ну не писать же такое вот выражение:

C++
1
boost::regex reg("(\\d{15});(\\d{16});(.*?);(.*?);(.*?);(.*?);(.*?);(.*?);(.*?);(.*?);(.*?);(.*?);(.*?);(.*?);(.*?);");(.*?);(.*?);(.*?);(.*?);
Можно, конечно, через потоки, по типу:

C++
1
2
3
4
std::string str;
std::istringstream ss(str);
std::string value1;
ss >> value1;
Но тут прикол в том, что между двумя точками с запятой может быть и строка, разделенная пробелами:
";вот такая длинная строка с пробелами;".

В общем, как правильней, или, точнее, грамотней было бы это сделать?

Добавлено через 8 минут
ЗЫ Выражение с регекспом можно и подсократить, конечно:

C++
1
boost::regex reg("(\\d{15});(\\d{16});(.*?);(\\3){30};");
(Не уверен только, как тогда обратиться к 19му subexpression'у и правильно ли я написал вот эту часть: ;(\\3){30};

Но все равно, чувствую, не нужен тут regex, можно сильно проще ))
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.01.2013, 17:39     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex?
Посмотрите здесь:

C++ Ввод нецелого числа с запятой и точкой.
C++ классы, что пишется перед точкой с запятой?
C++ Дан текстовый файл, в котором записана последовательность целых чисел. Записать в новый файл только четные из них
Текстовый файл, в котором записана строка C++
Работа с бинарным файлом (Создать новый текстовый файл, в котором числа будут отсортированы в порядке возрастания.) C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
diagon
Higher
 Аватар для diagon
1920 / 1186 / 49
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
30.01.2013, 17:42     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? #2
Чем плох вариант с boost::split с семиколонной в качестве разделителя?
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
30.01.2013, 17:43  [ТС]     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? #3
Цитата Сообщение от diagon Посмотреть сообщение
Чем плох вариант с boost::split с семиколонной в качестве разделителя?
Ну видимо тем, что я про него не знал
Пасиб. Щас гляну.
Vourhey
Почетный модератор
6468 / 2243 / 123
Регистрация: 29.07.2006
Сообщений: 12,635
30.01.2013, 17:59     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? #4
C++
1
while(std::getline(in, token, ';')) tokens.push_back(token);
потом к любому элементу через tokens[индекс] где tokens - вектор, in - ifstream, token - стринг
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
30.01.2013, 18:06     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? #5
Excogit8er, может как-нибудь так?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <string>
 
#include <boost/regex.hpp>
 
 
int main() {
   std::string line;
   std::getline(std::cin, line);
   boost::regex regex("^(((.*?);)){2}(.*?);((.*?);){16}(.*?);");
   boost::smatch match;
   if (boost::regex_match(line, match, regex)) {
      std::cout << match[4] << std::endl;
      std::cout << match[6] << std::endl;
   }
}
http://liveworkspace.org/code/3B2Vcq

Добавлено через 1 минуту
Так то со split попроще будет, пожалуй)
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
30.01.2013, 18:20  [ТС]     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? #6
Цитата Сообщение от Vourhey Посмотреть сообщение
C++
1
while(std::getline(in, token, ';')) tokens.push_back(token);
потом к любому элементу через tokens[индекс] где tokens - вектор, in - ifstream, token - стринг
А при таком подходе строки не перепутаются? )
Так-то все ясно: while(std::getline(filename, str, '\n'))
И каждая строка потом парсится.
А так...

Добавлено через 2 минуты
Цитата Сообщение от gray_fox Посмотреть сообщение
Excogit8er, может как-нибудь так?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <string>
 
#include <boost/regex.hpp>
 
 
int main() {
   std::string line;
   std::getline(std::cin, line);
   boost::regex regex("^(((.*?);)){2}(.*?);((.*?);){16}(.*?);");
   boost::smatch match;
   if (boost::regex_match(line, match, regex)) {
      std::cout << match[4] << std::endl;
      std::cout << match[6] << std::endl;
   }
}
http://liveworkspace.org/code/3B2Vcq

Добавлено через 1 минуту
Так то со split попроще будет, пожалуй)
Ну, кстати, вариант. Со сплит я уже посмотрел примеры:

C++
1
2
3
4
5
6
7
8
9
   std::string s = "value1;value2;value number fucking 3;value4";
   s.erase(s.size() - 1);
   std::vector<std::string> v;
   boost::split(v, s, [](const char c) { return c == ';'; }, boost::token_compress_on);
   boost::copy(v | boost::adaptors::filtered([](const std::string& s)
   {
      return *s.begin() == *s.rbegin();
   }), std::ostream_iterator<std::string>(std::cout, "\n"));  
}
Жесть как она есть ) При этом пока не понял, как, скажем, вывести в консоль только (скажем) 3е и 19е subexpressions.
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
30.01.2013, 18:32     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? #7
Excogit8er, v[2], v[18]?

Добавлено через 2 минуты
Собственно
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <string>
#include <vector>
 
#include <boost/algorithm/string.hpp>
 
 
int main() {
   std::string line;
   std::getline(std::cin, line);
   std::vector<std::string> tokens;
   boost::split(tokens, line, boost::is_any_of(";"), boost::token_compress_on);
   std::cout << tokens[2] << std::endl;
   std::cout << tokens[18] << std::endl;
}
http://liveworkspace.org/code/4zSbo8
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
30.01.2013, 18:43  [ТС]     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? #8
Цитата Сообщение от gray_fox Посмотреть сообщение
Excogit8er, v[2], v[18]?

Добавлено через 2 минуты
Собственно
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <string>
#include <vector>
 
#include <boost/algorithm/string.hpp>
 
 
int main() {
   std::string line;
   std::getline(std::cin, line);
   std::vector<std::string> tokens;
   boost::split(tokens, line, boost::is_any_of(";"), boost::token_compress_on);
   std::cout << tokens[2] << std::endl;
   std::cout << tokens[18] << std::endl;
}
http://liveworkspace.org/code/4zSbo8
Ну это намного проще, спасибо ) Проверил только что:
C++
1
2
3
4
5
6
7
std::string s;
while (std::getline (inpf, s)) {    
std::vector<std::string> tokens;
boost::split(tokens, s, boost::is_any_of(";"), boost::token_compress_on);
std::cout << tokens[2] << std::endl;
std::cout << tokens[18] << std::endl;
}
Получил такое вот сообщение при компиляции:

"c:\program files\microsoft visual studio 10.0\vc\include\xutility(2227): warning C4996: 'std::_Copy_impl': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators'
1> c:\program files\microsoft visual studio 10.0\vc\include\xutility(2212) : see declaration of 'std::_Copy_impl'
1> c:\program files\boost\boost_1_51\boost\algorithm\string\detail\classification.hpp(102) : see reference to function template instantiation '_OutIt std::copy<const char*,char*>(_InIt,_InIt,_OutIt)' being compiled
1> with
1> [
1> _OutIt=char *,
1> _InIt=const char *
1> ]
1> c:\program files\boost\boost_1_51\boost\algorithm\string\classification.hpp(206) : see reference to function template instantiation 'boost::algorithm::detail::is_any_ofF<CharT>::is_any_ofF<boost::iterator_range<IteratorT>>(const RangeT &)' being compiled
1> with
1> [
1> CharT=char,
1> IteratorT=const char *,
1> RangeT=boost::iterator_range<const char *>
1> ]
1> c:\users\documents\visual studio 2010\projects\xml2roadnet\xml2roadnet\xml2roadnet.cpp(91) : see reference to function template instantiation 'boost::algorithm::detail::is_any_ofF<CharT> boost::algorithm::is_any_of<const char[2]>(RangeT (&))' being compiled
1> with
1> [
1> CharT=char,
1> RangeT=const char [2]
1> ]"


А сама программка "валится" с ошибкой: "Expression: vector subscript out of range"
Vourhey
Почетный модератор
6468 / 2243 / 123
Регистрация: 29.07.2006
Сообщений: 12,635
30.01.2013, 18:49     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? #9
Цитата Сообщение от Excogit8er Посмотреть сообщение
А при таком подходе строки не перепутаются? )
Нечему и не с чего перепутываться
Цитата Сообщение от Excogit8er Посмотреть сообщение
А так...
А как? Хоть бы что понятное написал, а то одни междометия.
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
30.01.2013, 18:55     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? #10
Цитата Сообщение от Excogit8er Посмотреть сообщение
Получил такое вот сообщение при компиляции:
Студии не нравятся алгоритмы из std? )
Цитата Сообщение от Excogit8er Посмотреть сообщение
"Expression: vector subscript out of range"
Очевидно в строке не было 19 значений, соответственно и в tokens тоже.
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
30.01.2013, 19:03  [ТС]     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? #11
Цитата Сообщение от Vourhey Посмотреть сообщение
Нечему и не с чего перепутываться

А как? Хоть чтоб что понятное написал, а то одни междометия.
Я просто не понял, как строки различать при таком считывании?
Считать количество точек с запятой? А если в какой-то строке будет лишняя, скажем?

Ну, т.е.

C++
1
2
while(std::getline(in, token, ';')) tokens.push_back(token);
\\как понять, где конец строки?
Добавлено через 5 минут
Цитата Сообщение от gray_fox Посмотреть сообщение
Студии не нравятся алгоритмы из std? )
Ну, boost::split вроде бы не std ))
Но, блин, я VS только недавно начал пользоваться и уже понимаю, почему все плюются)

Очевидно в строке не было 19 значений, соответственно и в tokens тоже.
Не, вот кстати было - там их 38 (в каждой строке), или что-то около того. Но 19 точно есть.
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
30.01.2013, 19:08     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? #12
Цитата Сообщение от Excogit8er Посмотреть сообщение
Ну, boost::split вроде бы не std ))
Я про
warning C4996: 'std::_Copy_impl': Function call with parameters that may be unsafe
Не, вот кстати было - там их 38 (в каждой строке), или что-то около того. Но 19 точно есть.
Ну как бы assertion говорит о выходе индекса за допустимые пределы. Может в конце пустую строку читаешь?
Vourhey
Почетный модератор
6468 / 2243 / 123
Регистрация: 29.07.2006
Сообщений: 12,635
30.01.2013, 19:16     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? #13
Цитата Сообщение от Excogit8er Посмотреть сообщение
как строки различать при таком считывании?
"ifstream" это не обязательно файл, а лишь пример. Любой наследник istream'а может его заменить. Если у нас есть несколько строк в файле, то есть istringstream и тот же алгоритм.
Цитата Сообщение от Excogit8er Посмотреть сообщение
Считать количество точек с запятой? А если в какой-то строке будет лишняя, скажем?
Научись смотреть на вопрос в общем, а не упираться лбом в стенку.
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
30.01.2013, 19:16  [ТС]     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? #14
Цитата Сообщение от gray_fox Посмотреть сообщение
Я про
warning C4996: 'std::_Copy_impl': Function call with parameters that may be unsafe
Да, не заметил) Похоже, что не нравятся...

Ну как бы assertion говорит о выходе индекса за допустимые пределы. Может в конце пустую строку читаешь?
Нет, я перенаправил вывод с консоли в файл - видно, что верно считывается 1я строкa (2 значения), а вот
на второй все заваливается. Но там пустые значения, т.е. просто две точки с запятой подряд.
gray_fox
What a waste!
 Аватар для gray_fox
1244 / 1127 / 53
Регистрация: 21.04.2012
Сообщений: 2,350
Завершенные тесты: 3
30.01.2013, 19:19     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? #15
Цитата Сообщение от Excogit8er Посмотреть сообщение
1я строкa (2 значения)
Ну так считай все значения в одну строку сначала, потом разбирай )
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.01.2013, 11:20     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex?
Еще ссылки по теме:

C++ Слова в тексте разделены точкой с запятой. Определить сколько слов, заканчиваются буквой а.
C++ Составить текстовый файл, в котором будет несколько слов, разделенных пробелами
C++ Класс : Число с плавающей запятой(точкой)

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

Или воспользуйтесь поиском по форуму:
Excogit8er
2 / 2 / 0
Регистрация: 23.10.2012
Сообщений: 66
31.01.2013, 11:20  [ТС]     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? #16
Цитата Сообщение от gray_fox Посмотреть сообщение
Ну так считай все значения в одну строку сначала, потом разбирай )
)) Все равно я не понял - если в массиве (vector<string>) строк одно из значений оказалось пустым, то это типа exception?

Спасибо всем. Завтра попробую оба варианта (поток и boost::split)


Добавлено через 15 часов 40 минут
Ну, в общем, как-то так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
std::string data;
while (std::getline (inpf, data)) {
std::istringstream sstr (data);
std::vector<std::string> tokens;
std::string token;
while(std::getline(sstr, token, ';')) 
tokens.push_back(token);            
for (int i = 0; i < tokens.size(); i++)
  { 
    if (i == 1)
                cout << tokens[i] << "---";
    if (i == 18)
        cout << tokens[i] << "---";  
  }
Причем, как мне показалось, так даже быстрее (скорость выполнения) чем через boost::split.

Vourhey
Ты был прав, все элементарно) Thanx
Yandex
Объявления
31.01.2013, 11:20     Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex?
Ответ Создать тему
Опции темы

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