Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.92/13: Рейтинг темы: голосов - 13, средняя оценка - 4.92
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
1

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

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

Author24 — интернет-сервис помощи студентам
Привет)

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

Есть файлик, в котором заданное кол-во значений разделено точкой с запятой.
По типу:
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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
30.01.2013, 17:39
Ответы с готовыми решениями:

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

Как правильно считать матрицу из текстовый файла, если числа разделены запятой
Здравствуйте! Считываю матрицу из текстового файла следующим образом: m=importdata('in.txt');...

Ввести предложение, слова в котором разделены пробелами и запятыми. После каждой запятой поставить пробел, если его там нет
Ввести предложение, слова в котором разделены пробелами и запятыми. После каждой запятой поставить...

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

15
Higher
1953 / 1219 / 120
Регистрация: 02.05.2010
Сообщений: 2,925
Записей в блоге: 2
30.01.2013, 17:42 2
Чем плох вариант с boost::split с семиколонной в качестве разделителя?
1
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
30.01.2013, 17:43  [ТС] 3
Цитата Сообщение от diagon Посмотреть сообщение
Чем плох вариант с boost::split с семиколонной в качестве разделителя?
Ну видимо тем, что я про него не знал
Пасиб. Щас гляну.
0
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
30.01.2013, 17:59 4
C++
1
while(std::getline(in, token, ';')) tokens.push_back(token);
потом к любому элементу через tokens[индекс] где tokens - вектор, in - ifstream, token - стринг
1
What a waste!
1608 / 1300 / 180
Регистрация: 21.04.2012
Сообщений: 2,729
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
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
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
What a waste!
1608 / 1300 / 180
Регистрация: 21.04.2012
Сообщений: 2,729
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
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
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<I teratorT>>(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
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
30.01.2013, 18:49 9
Цитата Сообщение от Excogit8er Посмотреть сообщение
А при таком подходе строки не перепутаются? )
Нечему и не с чего перепутываться
Цитата Сообщение от Excogit8er Посмотреть сообщение
А так...
А как? Хоть бы что понятное написал, а то одни междометия.
0
What a waste!
1608 / 1300 / 180
Регистрация: 21.04.2012
Сообщений: 2,729
30.01.2013, 18:55 10
Цитата Сообщение от Excogit8er Посмотреть сообщение
Получил такое вот сообщение при компиляции:
Студии не нравятся алгоритмы из std? )
Цитата Сообщение от Excogit8er Посмотреть сообщение
"Expression: vector subscript out of range"
Очевидно в строке не было 19 значений, соответственно и в tokens тоже.
0
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
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
What a waste!
1608 / 1300 / 180
Регистрация: 21.04.2012
Сообщений: 2,729
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
Почетный модератор
7393 / 2639 / 281
Регистрация: 29.07.2006
Сообщений: 13,696
30.01.2013, 19:16 13
Цитата Сообщение от Excogit8er Посмотреть сообщение
как строки различать при таком считывании?
"ifstream" это не обязательно файл, а лишь пример. Любой наследник istream'а может его заменить. Если у нас есть несколько строк в файле, то есть istringstream и тот же алгоритм.
Цитата Сообщение от Excogit8er Посмотреть сообщение
Считать количество точек с запятой? А если в какой-то строке будет лишняя, скажем?
Научись смотреть на вопрос в общем, а не упираться лбом в стенку.
0
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
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
What a waste!
1608 / 1300 / 180
Регистрация: 21.04.2012
Сообщений: 2,729
30.01.2013, 19:19 15
Цитата Сообщение от Excogit8er Посмотреть сообщение
1я строкa (2 значения)
Ну так считай все значения в одну строку сначала, потом разбирай )
0
2 / 2 / 1
Регистрация: 23.10.2012
Сообщений: 66
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
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
31.01.2013, 11:20
Помогаю со студенческими работами здесь

Записать значение Double в файл не с запятой, а с точкой
Помогите пожалуйста(((((( При записи в файл числа, типа double, записываются с запятой, а нужно,...

Создать файл, в котором фамилии будут записаны в одну строку и разделены запятыми
Текстовый файл содержит несколько строк с фамилиями. Создать файл, в котором эти фамилии будут...


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

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru