OberonCore
https://forum.oberoncore.ru/

Порядок чтения из файла
https://forum.oberoncore.ru/viewtopic.php?f=30&t=6050
Страница 1 из 1

Автор:  kekc_leader [ Вторник, 09 Май, 2017 00:20 ]
Заголовок сообщения:  Порядок чтения из файла

В книге «Программирование на Обероне» приведён такой пример чтения из файла (стр. 52):

Цитата:
The file can thereafter be read by the following pattern. First, the file with specified name is associated
with variable f. Then a rider is placed at the start of the file, and then advanced by reading.
Код:
f := Files.Old(“MyFile”); Files.Set(r, f, 0);
WHILE ~r.eof DO Files.Read(f, next); process(next) END
Note that the rider indicates that the end of the file had been reached after the first unsuccessful attempt
of reading.

Тогда как в книге «Проект Оберон» приведён следующий пример (стр. 85):

Код:
VAR f: Files.File; r: Files.Rider;
f := Files.Old(name);
IF f # NIL THEN
 Files.Set (r, f, 0); Files.Read(r, x);
 WHILE ~ r.eof DO ... x ...; Files.Read(r, x) END
END

По-моему, в первой книжке ошибка, т. к. код не стыкуется с комментарием («Заметим, что бегунок указывает, достигнут ли конец файла, только после первой неудачной попытки чтения»).

Вопрос:
Надо ли производить вызов Files.Read до начала цикла? Понятно, что среди различных реализаций Оберона можно найти оба варианта, но интересней всего знать, как должно быть по науке.

Автор:  Valery Solovey [ Вторник, 09 Май, 2017 01:06 ]
Заголовок сообщения:  Re: Порядок чтения из файла

Зависит от спецификации. Лично мне больше нравится первый вариант, но он не всегда возможен или приемлем.

Автор:  Александр Ильин [ Вторник, 09 Май, 2017 01:41 ]
Заголовок сообщения:  Re: Порядок чтения из файла

Valery Solovey писал(а):
Зависит от спецификации. Лично мне больше нравится первый вариант, но он не всегда возможен или приемлем.
В первом варианте мне не нравится то, что process(next) вызывается даже в том случае, если последний Read ничего не прочитал. Т.е. непосредственно перед process(next) нет проверки r.eot.
Поэтому я предпочитаю код вида
Код:
WHILE Files.Read(f, next) DO process(next) END
Второй вариант ближе всего к этому.

Автор:  Илья Ермаков [ Вторник, 09 Май, 2017 02:38 ]
Заголовок сообщения:  Re: Порядок чтения из файла

На эту тему тут разбиралось:
http://oberoncore.ru/wiki/%D0%BF%D0%B0% ... 0%BE%D0%B2

Автор:  Valery Solovey [ Вторник, 09 Май, 2017 21:19 ]
Заголовок сообщения:  Re: Порядок чтения из файла

Александр Ильин писал(а):
В первом варианте мне не нравится то, что process(next) вызывается даже в том случае, если последний Read ничего не прочитал.
Cамый простой и эффективный способ понять, достигнут ли конец файла - это сравнить текущую позицию с размером файла. Если они равны, значит EOT. Но такой вариант не будет работать, например, с http-ответами или файловыми системами, где файл может быть больше максимального значения "размера файла" (поля в файловой записи).

Автор:  Valery Solovey [ Вторник, 09 Май, 2017 21:24 ]
Заголовок сообщения:  Re: Порядок чтения из файла

Илья Ермаков писал(а):
На эту тему тут разбиралось:
http://oberoncore.ru/wiki/%D0%BF%D0%B0% ... 0%BE%D0%B2
Там разбирался общий случай, а это - частный.

Автор:  kekc_leader [ Четверг, 11 Май, 2017 23:49 ]
Заголовок сообщения:  Re: Порядок чтения из файла

Вопрос, собственно, сводится к тому, как работает r.eof.
Например, если мы только-только открыли файл и вызвали Files.Set(r, f, 0), а файл был пустым, будет ли значение r.eof = TRUE или сперва надо вызвать процедуру Files.Read(r, ch), а уж затем смотреть r.eof? Как должно быть?

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

Автор:  Иван Денисов [ Пятница, 12 Май, 2017 04:48 ]
Заголовок сообщения:  Re: Порядок чтения из файла

В первом случае предполагается, что в записях поля типа BOOLEAN устанавливаются при выделении памяти в FALSE. Поэтому первое чтение пройдет гарантированно. Также предполагается, что в process при этом есть корректная обработка ситуации с r.eof = TRUE.

Второй же вариант более общий и не зависит от каких либо допущений о реализации компилятора и обработчика.

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

Автор:  Info21 [ Пятница, 12 Май, 2017 08:54 ]
Заголовок сообщения:  "принцип нуля"

kekc_leader писал(а):
Вопрос, собственно, сводится к тому, как работает r.eof.
Например, если мы только-только открыли файл и вызвали Files.Set(r, f, 0), а файл был пустым, будет ли значение r.eof = TRUE или сперва надо вызвать процедуру Files.Read(r, ch), а уж затем смотреть r.eof? Как должно быть?
Должно быть так, чтобы r.eof устанавливалось в TRUE только после попытки чтения.

Это частный случай принципа, что программа/процедура/etc. должна корректно отрабатывать "нулевой" случай.
Польза от этого такая же, как от нуля в позиционной системе счисления: всё заметно упрощается и упорядочивается.
Это не мешает делать любые оптимизации, потом. Или не делать )))

Полезно назвать это как-нибудь: скажем, принцип нуля.

Об оптимизации тут речь, потому что в старых книгах, написанных во времена, когда вызов процедуры был дорог (включая виртовские "Алгоритмы ...", которые мне пришлось чистить), программы писали так, чтобы избегать "пустых" процедурных вызовов -- как раз для "нулевых" случаев. Тогда вместо одной проверки внутри рекурсивной процедуры нужно было не забыть поставить проверку-охрану перед любым вызовом -- а иногда эта проверка была не нужна по построению алгоритма, но при изменении про это можно было забыть -- и т.д. -- прямой путь в трясину "отладки".

Автор:  Александр Ильин [ Пятница, 12 Май, 2017 11:15 ]
Заголовок сообщения:  Re: Порядок чтения из файла

Иван Денисов писал(а):
В первом случае предполагается, что в записях поля типа BOOLEAN устанавливаются при выделении памяти в FALSE.
Замечу в этом месте, что в вызове "Files.Set(r, f, 0);" не происходит выделения памяти. В контексте ОС Оберон переменная r - это RECORD в стеке.

Автор:  albobin [ Пятница, 12 Май, 2017 11:51 ]
Заголовок сообщения:  Re: Порядок чтения из файла

Добавлю свои 2 коп.
ИМХО " r.eof устанавливалось в TRUE только после попытки чтения." - это потому, что флаг (eof) должен выражать успешность/не успешность операции чтения по причине исчерпания доступных данных (в общем случае), а не отражать взаиморасположение текущей позиции для чтения и границы данных, которая (в общем случае) может динамично изменяться.

PS.
Сразу не прошёлся по ссылке из замечания И.Ермакова. Конечно типичный "полный проход".

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/