![]() |
Модераторы: Daevaorn |
![]() ![]() ![]() |
|
Dims |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1016 Регистрация: 21.11.2006 Репутация: 1 Всего: 11 |
Допустим, я читаю некоторый файл.
Файл состоит из строк, причём, каждая строка может быть текстовым представлением одного из нескольких типов. Один из типов -- это CDataPoint. Его текстовое представление являет собой перечень чисел через запятую. Я не могу написать для него тупой оператор
потому, что я не знаю, сколько элементов будет в строке (число чисел разное). Ладно, здесь я могу выкрутиться. Я могу считывать элементы поштучно в какой-то массив, анализировать не прочитан ли конец строки и, когда прочитан, зная число элементов, перекладывать их по членам класса. Некрасиво, но работать будет. Однако, ситуация осложняется тем, что в строке может содержаться вообще что-то другое. Например, неправильно составленный CDataPoint или комментарий. Комментарий отличается тем, что в первой позиции находится символ комментария. Ладно, тут можно прочитать один символ, проверить его и вернуть назад в поток. А как быть со случаем, когда встретится что-то другое? Мне нужно, чтобы программа не прерывалась, а чтобы неудачный кусок потока просто был бы обработан иначе. Как правильно поступить? Единственное разумное решение, которое мне видится, это читать файл в виде текстовых строк и потом их разбирать. Но это получается, что система istream-ов не используется. Можно ли как-то ей воспользоваться тут? Например, можно ли поставить в потоке какую-то закладку, а потом, при неудаче, откатить поток к этой закладке? |
|||
|
||||
xvr |
|
||||||||||||||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 60 Всего: 223 |
Это автоматически означает, что прямое чтение из файла в переменные этих типов не пройдет - неизвестно куда надо читать. Т.е. надо предварительно считать данные, определить их тип, и только потом стримить в соотвествующую переменную.
Есть 2 класса данных: лексемы и грамматики. Лексема может быть описанна регулярным выражением, а для считывания такой лексемы достаточно иметь 1 lookahead символ, его потом можно вернуть в поток. В подавляющем большинстве случаев регулярное выражение, описывающее лексему, достаточно простое и ее чтение из потока кодируется элементарно (пример - целое число) С грамматиками сложнее. Они описываются не регулярными выражениями, а конечными автоматами со стековой памятью, и в качестве входных элементов у них выступают лексемы. В принципе, для чтения грамматики также достаточно 1 lookahead символа (только на это раз это будет лексема), а чтение из потока по такой грамматике сложнее, чем чтение лексем. Для такого чтения нужно применять либо явный автомат, либо его воплощение в виде набора рекурсивных процедур (метод рекурсивного спуска)
Классическая грамматика. Тебе нужен парсер на ВСЮ грамматику целиком.
Если твоя грамматика допускает построчный разбор - то тебе очень сильно повезло, и надо именно так и делать.
Можно, читай из istream'а в строку и разбирай ![]()
Можно, tellg/seekg - но многократное позиционирование потока будет хуже, чем предварительное чтение в строку. |
||||||||||||||
|
|||||||||||||||
Dims |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1016 Регистрация: 21.11.2006 Репутация: 1 Всего: 11 |
||||
|
||||
archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: 58 Всего: 93 |
Есть такие прекрасные штуки, как XML и сериализация. В XML и комментарии делать можно, и десериализация не так сложна, как в случае своих велосипедов. Добавлено через 15 секунд см. boost::serialization. -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
Dims |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1016 Регистрация: 21.11.2006 Репутация: 1 Всего: 11 |
У меня файл, за формат которого я не отвечаю. То есть, мне нужно прочитать. Собственно, я его уже читаю обычным scanf-ом, но подумал, не сделать ли новыми средствами...
А вообще, если сузить вопрос. Что положено делать в переопределённом операторе operator>> в случае, если при чтении обнаруживается, что формат данных не соблюдён? Исключение выкидывать? |
|||
|
||||
archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: 58 Всего: 93 |
bad_bit выставлять должно и, если istream.exceptions() != 0, то, тогда перебрасывать исключение(но, тогда его и ловить нужно, ибо поток сам кинуть может)...
Добавлено через 6 минут и 36 секунд Но, боюсь, тебе это не поможет, ибо ни bad_bit, ни исключение обратно данные в поток не засунет... -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
xvr |
|
|||
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Комодератор Сообщений: 7046 Регистрация: 28.8.2007 Где: Дублин, Ирландия Репутация: 60 Всего: 223 |
Есть, и первое, что сделает seekg - сбросит буфер (возможны реализации stl, где это не так, но это маловероятно)
И не говори ![]() |
|||
|
||||
Dims |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1016 Регистрация: 21.11.2006 Репутация: 1 Всего: 11 |
А какое? Есть в STL или надо своё определить? Что-то я не вижу в <stdexcept> подходящих.
Ну это понятно. Я теперь решил сделать проверку символа перед чтением, но всё же надо же что-то делать, если я ошибусь. Для этого и исключение. |
|||
|
||||
archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: 58 Всего: 93 |
Стандартные бросают ios_base::failure, который в свою очередь, является наследником std::exception.
-------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
![]() ![]() ![]() |
Правила форума "С++:Общие вопросы" | |
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей) | |
0 Пользователей: | |
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |