Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Excogit8er
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
Завершенные тесты: 3
#1

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

30.01.2013, 17:39. Просмотров 1221. Ответов 15
Метки нет (Все метки)

Привет)

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

Есть файлик, в котором заданное кол-во значений разделено точкой с запятой.
По типу:
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, можно сильно проще ))
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
30.01.2013, 17:39
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Текстовый файл, в котором значения разделены точкой с запятой. Нужен ли regex? (C++):

Слова в тексте разделены точкой с запятой. Определить сколько слов, заканчиваются буквой а.
Здравствуйте, помогите пожалуйста со троками Как можно решить эту задачу? ...

Дан текстовый файл, в котором записана последовательность целых чисел. Записать в новый файл только четные из них
Дан текстовый файл, в котором записана последовательность целых чисел. Записать...

Текстовый файл, в котором записана строка
Имеется текстовый файл, в котором записана одна строка: &quot;Здравствуйте, дорогие...

Составить текстовый файл, в котором будет несколько слов, разделенных пробелами
Я не могу решить задачу. Задание такое написать текстовый файл в котором будет...

Работа с бинарным файлом (Создать новый текстовый файл, в котором числа будут отсортированы в порядке возрастания.)
Аларм! Срочно прошу помощи! Есть задача: Записать бинарный файл с массивом...

Дано предложение, слова в котором разделены произвольным числом пробелов
Дано предложение, слова в котором разделены произвольным числом пробелов. Найти...

15
diagon
Higher
1937 / 1203 / 120
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
30.01.2013, 17:42 #2
Чем плох вариант с boost::split с семиколонной в качестве разделителя?
1
Excogit8er
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
Завершенные тесты: 3
30.01.2013, 17:43  [ТС] #3
Цитата Сообщение от diagon Посмотреть сообщение
Чем плох вариант с boost::split с семиколонной в качестве разделителя?
Ну видимо тем, что я про него не знал
Пасиб. Щас гляну.
0
Vourhey
Почетный модератор
6490 / 2264 / 187
Регистрация: 29.07.2006
Сообщений: 12,534
30.01.2013, 17:59 #4
C++
1
while(std::getline(in, token, ';')) tokens.push_back(token);
потом к любому элементу через tokens[индекс] где tokens - вектор, in - ifstream, token - стринг
1
gray_fox
What a waste!
1552 / 1257 / 165
Регистрация: 21.04.2012
Сообщений: 2,634
Завершенные тесты: 3
30.01.2013, 18:06 #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 попроще будет, пожалуй)
0
Excogit8er
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
Завершенные тесты: 3
30.01.2013, 18:20  [ТС] #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.
0
gray_fox
What a waste!
1552 / 1257 / 165
Регистрация: 21.04.2012
Сообщений: 2,634
Завершенные тесты: 3
30.01.2013, 18:32 #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
0
Excogit8er
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
Завершенные тесты: 3
30.01.2013, 18:43  [ТС] #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"
0
Vourhey
Почетный модератор
6490 / 2264 / 187
Регистрация: 29.07.2006
Сообщений: 12,534
30.01.2013, 18:49 #9
Цитата Сообщение от Excogit8er Посмотреть сообщение
А при таком подходе строки не перепутаются? )
Нечему и не с чего перепутываться
Цитата Сообщение от Excogit8er Посмотреть сообщение
А так...
А как? Хоть бы что понятное написал, а то одни междометия.
0
gray_fox
What a waste!
1552 / 1257 / 165
Регистрация: 21.04.2012
Сообщений: 2,634
Завершенные тесты: 3
30.01.2013, 18:55 #10
Цитата Сообщение от Excogit8er Посмотреть сообщение
Получил такое вот сообщение при компиляции:
Студии не нравятся алгоритмы из std? )
Цитата Сообщение от Excogit8er Посмотреть сообщение
"Expression: vector subscript out of range"
Очевидно в строке не было 19 значений, соответственно и в tokens тоже.
0
Excogit8er
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
Завершенные тесты: 3
30.01.2013, 19:03  [ТС] #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 точно есть.
0
gray_fox
What a waste!
1552 / 1257 / 165
Регистрация: 21.04.2012
Сообщений: 2,634
Завершенные тесты: 3
30.01.2013, 19:08 #12
Цитата Сообщение от Excogit8er Посмотреть сообщение
Ну, boost::split вроде бы не std ))
Я про
warning C4996: 'std::_Copy_impl': Function call with parameters that may be unsafe
Не, вот кстати было - там их 38 (в каждой строке), или что-то около того. Но 19 точно есть.
Ну как бы assertion говорит о выходе индекса за допустимые пределы. Может в конце пустую строку читаешь?
0
Vourhey
Почетный модератор
6490 / 2264 / 187
Регистрация: 29.07.2006
Сообщений: 12,534
30.01.2013, 19:16 #13
Цитата Сообщение от Excogit8er Посмотреть сообщение
как строки различать при таком считывании?
"ifstream" это не обязательно файл, а лишь пример. Любой наследник istream'а может его заменить. Если у нас есть несколько строк в файле, то есть istringstream и тот же алгоритм.
Цитата Сообщение от Excogit8er Посмотреть сообщение
Считать количество точек с запятой? А если в какой-то строке будет лишняя, скажем?
Научись смотреть на вопрос в общем, а не упираться лбом в стенку.
0
Excogit8er
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
Завершенные тесты: 3
30.01.2013, 19:16  [ТС] #14
Цитата Сообщение от gray_fox Посмотреть сообщение
Я про
warning C4996: 'std::_Copy_impl': Function call with parameters that may be unsafe
Да, не заметил) Похоже, что не нравятся...

Ну как бы assertion говорит о выходе индекса за допустимые пределы. Может в конце пустую строку читаешь?
Нет, я перенаправил вывод с консоли в файл - видно, что верно считывается 1я строкa (2 значения), а вот
на второй все заваливается. Но там пустые значения, т.е. просто две точки с запятой подряд.
0
gray_fox
What a waste!
1552 / 1257 / 165
Регистрация: 21.04.2012
Сообщений: 2,634
Завершенные тесты: 3
30.01.2013, 19:19 #15
Цитата Сообщение от Excogit8er Посмотреть сообщение
1я строкa (2 значения)
Ну так считай все значения в одну строку сначала, потом разбирай )
0
Excogit8er
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
Завершенные тесты: 3
31.01.2013, 11:20  [ТС] #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
0
31.01.2013, 11:20
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
31.01.2013, 11:20
Привет! Вот еще темы с решениями:

Класс : Число с плавающей запятой(точкой)
Подскажите,где можно побольше узнать о числах с плавающей запятой,желательно не...

Дано скобочное выражение, оканчивающееся точкой с запятой
Дано скобочное выражение, оканчивающееся точкой с запятой. Определить:...

Дано скобочное выражение, оканчивающееся точкой с запятой
Дано скобочное выражение, оканчивающееся точкой с запятой. Определить:...

классы, что пишется перед точкой с запятой?
class example { ... }//перед точкой с запятой иногда что-то пишут, какие-то...


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

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
Опции темы

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