Модераторы: Daevaorn
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как правильно читать из istream неизвестное? 
:(
    Опции темы
Dims
Дата 29.11.2007, 13:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 1
Всего: 11



Допустим, я читаю некоторый файл.

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

Один из типов -- это CDataPoint. Его текстовое представление являет собой перечень чисел через запятую.

Я не могу написать для него тупой оператор 

Код

istream& operator>>(istream& is, CDataPoint& dp);


потому, что я не знаю, сколько элементов будет в строке (число чисел разное).

Ладно, здесь я могу выкрутиться. Я могу считывать элементы поштучно в какой-то массив, анализировать не прочитан ли конец строки и, когда прочитан, зная число элементов, перекладывать их по членам класса. Некрасиво, но работать будет.

Однако, ситуация осложняется тем, что в строке может содержаться вообще что-то другое. Например, неправильно составленный CDataPoint или комментарий. Комментарий отличается тем, что в первой позиции находится символ комментария. Ладно, тут можно прочитать один символ, проверить его и вернуть назад в поток. А как быть со случаем, когда встретится что-то другое? Мне нужно, чтобы программа не прерывалась, а чтобы неудачный кусок потока просто был бы обработан иначе. 

Как правильно поступить?

Единственное разумное решение, которое мне видится, это читать файл в виде текстовых строк и потом их разбирать. Но это получается, что система istream-ов не используется. Можно ли как-то ей воспользоваться тут? Например, можно ли поставить в потоке какую-то закладку, а потом, при неудаче, откатить поток к этой закладке?
PM MAIL   Вверх
xvr
Дата 29.11.2007, 13:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(Dims @ 29.11.2007,  13:08)
Допустим, я читаю некоторый файл.

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

Это автоматически означает, что прямое чтение из файла в переменные этих типов не пройдет - неизвестно куда надо читать. Т.е. надо предварительно считать данные, определить их тип, и только потом стримить в соотвествующую переменную.
Цитата

Один из типов -- это CDataPoint. Его текстовое представление являет собой перечень чисел через запятую.

Я не могу написать для него тупой оператор 

Код

istream& operator>>(istream& is, CDataPoint& dp);


потому, что я не знаю, сколько элементов будет в строке (число чисел разное).

Ладно, здесь я могу выкрутиться. Я могу считывать элементы поштучно в какой-то массив, анализировать не прочитан ли конец строки и, когда прочитан, зная число элементов, перекладывать их по членам класса. Некрасиво, но работать будет.

Есть 2 класса данных: лексемы и грамматики. Лексема может быть описанна регулярным выражением, а для считывания такой лексемы достаточно иметь 1 lookahead символ, его потом можно вернуть в поток. В подавляющем большинстве случаев регулярное выражение, описывающее лексему, достаточно простое и ее чтение из потока кодируется элементарно (пример - целое число)

С грамматиками сложнее. Они описываются не регулярными выражениями, а конечными автоматами со стековой памятью, и в качестве входных элементов у них выступают лексемы. В принципе, для чтения грамматики также достаточно 1 lookahead символа (только на это  раз это будет лексема), а чтение из потока по такой грамматике сложнее, чем чтение лексем. Для такого чтения нужно применять либо явный автомат, либо его воплощение в виде набора рекурсивных процедур (метод рекурсивного спуска)

Цитата

Однако, ситуация осложняется тем, что в строке может содержаться вообще что-то другое. Например, неправильно составленный CDataPoint или комментарий. Комментарий отличается тем, что в первой позиции находится символ комментария. Ладно, тут можно прочитать один символ, проверить его и вернуть назад в поток. А как быть со случаем, когда встретится что-то другое? Мне нужно, чтобы программа не прерывалась, а чтобы неудачный кусок потока просто был бы обработан иначе. 
Как правильно поступить?

Классическая грамматика. Тебе нужен парсер на ВСЮ грамматику целиком.

Цитата

Единственное разумное решение, которое мне видится, это читать файл в виде текстовых строк и потом их разбирать. 

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

Цитата

Но это получается, что система istream-ов не используется. Можно ли как-то ей воспользоваться тут? 

Можно, читай из istream'а в строку и разбирай smile

Цитата

Например, можно ли поставить в потоке какую-то закладку, а потом, при неудаче, откатить поток к этой закладке?

Можно, tellg/seekg - но многократное позиционирование потока будет хуже, чем предварительное чтение в строку.

PM MAIL   Вверх
Dims
Дата 29.11.2007, 15:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 1
Всего: 11



Цитата(xvr @  29.11.2007,  13:33 Найти цитируемый пост)
Можно, tellg/seekg - но многократное позиционирование потока будет хуже, чем предварительное чтение в строку.

А разве там нет буфера? Или буфер не поможет в отмотке назад?

Да, как-то не кузяво.
PM MAIL   Вверх
archimed7592
Дата 29.11.2007, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


Профиль
Группа: Завсегдатай
Сообщений: 2531
Регистрация: 12.6.2004
Где: Moscow

Репутация: 58
Всего: 93



Цитата(Dims @  29.11.2007,  15:07 Найти цитируемый пост)
Да, как-то не кузяво. 

Есть такие прекрасные штуки, как 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
PM Jabber   Вверх
Dims
Дата 29.11.2007, 16:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 1
Всего: 11



У меня файл, за формат которого я не отвечаю. То есть, мне нужно прочитать. Собственно, я его уже читаю обычным scanf-ом, но подумал, не сделать ли новыми средствами...

А вообще, если сузить вопрос.

Что положено делать в переопределённом операторе operator>> в случае, если при чтении обнаруживается, что формат данных не соблюдён? Исключение выкидывать?
PM MAIL   Вверх
archimed7592
Дата 29.11.2007, 16:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


Профиль
Группа: Завсегдатай
Сообщений: 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
PM Jabber   Вверх
xvr
Дата 29.11.2007, 18:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 7046
Регистрация: 28.8.2007
Где: Дублин, Ирландия

Репутация: 60
Всего: 223



Цитата(Dims @ 29.11.2007,  15:07)
Цитата(xvr @  29.11.2007,  13:33 Найти цитируемый пост)
Можно, tellg/seekg - но многократное позиционирование потока будет хуже, чем предварительное чтение в строку.

А разве там нет буфера? Или буфер не поможет в отмотке назад?

Есть, и первое, что сделает seekg - сбросит буфер (возможны реализации stl, где это не так, но это маловероятно)

Цитата

Да, как-то не кузяво.

И не говори smile

PM MAIL   Вверх
Dims
Дата 30.11.2007, 09:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1016
Регистрация: 21.11.2006

Репутация: 1
Всего: 11



Цитата(archimed7592 @  29.11.2007,  16:46 Найти цитируемый пост)
то, тогда перебрасывать исключение

А какое? Есть в STL или надо своё определить? Что-то я не вижу в <stdexcept> подходящих.

Цитата(archimed7592 @  29.11.2007,  16:46 Найти цитируемый пост)
Но, боюсь, тебе это не поможет, ибо ни bad_bit, ни исключение обратно данные в поток не засунет... 

Ну это понятно. Я теперь решил сделать проверку символа перед чтением, но всё же надо же что-то делать, если я ошибусь. Для этого и исключение.

PM MAIL   Вверх
archimed7592
Дата 30.11.2007, 10:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Архимед
****


Профиль
Группа: Завсегдатай
Сообщений: 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
PM Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0682 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.