Смекни!
smekni.com

Программирование и разработка приложений в Maple (стр. 105 из 135)

statf := proc() local a t k, , ; assign67(a = iostatus( ), t['TEXT'] = NULL, t['BINARY'] = NULL), `if`( nops(a) = 3, NULL, [seq assign67( (' [t a k[ ][-1]]' = t[a k[ ][-1]],

[op(a k[ ][1 .. 3]), filepos( a k[ ][1]), a k[ ][-2]]), k = 4 .. nops(a)),

RETURN(eval(t))]) end proc

> fopen("C:/a", 'WRITE'): writebytes("C:/b", [64, 59,39]): statf(); table([TEXT = [0, "C:/a", STREAM, 0, WRITE], BINARY = [1, "C:/b", STREAM, 3, WRITE]])

6.5. Обеспечение форматированного доступа к внешним файлам данных

Рассмотрев в предыдущих разделах главы средства работы с внешними файлами типов TEXT и BINARY, структурная организация которых основывается соответственно на логических записях строчного и символьного типов, здесь остановимся на средствах доступа Maple-языка для обеспечения работы как с числовыми, так и с более сложной форматизации структурами логических записей. Для этих целей Maple-язык располагает двумя парами процедур {writedata, readdata} и встроенных функций {fprintf, fscanf}, две последние из которых довольно детально рассматривались выше и здесь будут рассмотрены лишь в контекстуальном плане. В дальнейшем ради унификации будем и процедуры {writedata, readdata} именовать функциями, принимая во внимание, что с точки зрения концепции функциональных средств пакета эти понятия можно отождествлять.

По функции writedata, имеющей следующий формат кодирования:

writedata(<СФ>, <Данные> {, <Формат>} {, Proc})

производится запись в указанный первым фактическим СФ-аргументом (спецификатор или номер приписанного файлу логического канала в/в) файл TEXT-типа числовых данных, представленных в виде списка, вложенного списка, множества или матрицы и определяемых вторым фактическим аргументом функции. При необходимости записи числового массива его предварительно по convert-функции следует конвертировать в вектор, матрицу, список либо множество. Два последующих аргумента функции необязательны и при их наличии расширяют форматирующие возможности функции. При определении для СФ-аргумента terminal-значения вывод данных производится на экран монитора. Данный прием рекомендуется использовать перед окончательным сохранением данных в файле в целях их визуального контроля, особенно в случае достаточно сложно структурированных (форматированных) данных.

Если данные представлены в виде списка, вектора либо множества, то каждое числовое значение его элементов представляется в файле (или выводится на печать) в виде отдельной логической записи-строки, завершающейся управляющим символом hex(0D0A) «перевода строки и возврата каретки». Поэтому, например, по readline-функции их можно циклически считывать. Если же данные представлены в виде вложенного списка либо матрицы, то они выгружаются в файл (или выводятся на печать) построчно с символами табуляции {hex(09)} в качестве разделителей элементов строк. В этом случае их можно считывать построчно посредством, например, той же readline-функции. Начало нижеследующего фрагмента иллюстрирует сказанное. Как правило, в качестве элементов структур данных используются вычисляемые выражения типа {integer|float}, однако допускаются как комплексные, так и символьные выражения.

Третий необязательный аргумент writedata-функции определяет формат данных, в котором они сохраняются в дисковом файле либо выводятся на печать. Для данного аргумента допускается {integer|float (по умолчанию)|string}-значение, на основе которого форматирование writedata-функцией производится следующим образом:

Формат

выводится в файл либо на печать числовое N-значение:

integer

N, если whattype(N); ⇒ integer либо trunc(N), если whattype(N); ⇒ {float| fraction}; числовые N-значения других типов инициируют ошибки

float

evalf(N, 7); для N-значения допускаются типы {integer, float, fraction}

string

string-значение; допускается только string-тип

Так как по float-формату не допускается использования в качестве выводимых по функции writedata алгебраических чисел и пакетных констант {Pi, gamma, Catalan, exp(1)}, то для них требуется предварительная конвертация в float-тип, например, по evalf-функции. В случае структуры данных матричной или вложенного списка третий аргумент writedata-функции должен кодироваться в виде списка {integer, float, string}-значений, по длине соответствующего числу столбцов выводимой структуры данных. В этом случае каждый элемент списка определяет формат выводимых значений для элементов соответствующего ему столбца структуры данных. Например, по третьему фактическому аргументу вида [string, integer, float, string] для столбцов выводимой по writedata-функции структуры данных определяются форматы string, integer, float и string соответственно. Следующий простой фрагмент иллюстрирует вышесказанное:

> V:= array(1..2, [ 10, 17]): writedata(terminal, convert(V, 'set'));

10

17

> writedata("C:/Temp/grsu&bsol;data", [[57, 52, 32], [3, 10, 37], [42, 47, 67]]); writedata(default, [[64, 59, 39], [10, 17, 44], [42, 47, 67]]);

64 59 39 10 17 44 42 47 67

> writedata("C:/Temp/grsu&bsol;data"); ⇒ "64 &bsol;t59 &bsol;t39" > writedata(terminal, [64/59, 2006], integer);

1 2006

> writedata(terminal, [52/10, -57, 95/99], float);

5.200000000

-57

0.9595959596

> writedata(terminal, [Tallinn, Moscow, Vilnius, Grodno], string);

Tallinn

Moscow

Vilnius Grodno

> writedata(terminal, [[AVZ, 64, 2006/42, Gr_B], [AGN, 59, 2006/47, Gr_P], [VSV, 39,

2006/67, Gr_P]], [string, integer, float, string]);

AVZ 64 47.76190476 Gr_B AGN 59 42.68085106 Gr_P

VSV 39 29.94029851 Gr_P

> writedata(terminal, [64 + 42*I, 59 + 47*I, 39 - 67*I], float, proc(F, x) fprintf(F, `%G %a`, Re(x), Im(x)*I) end proc);

64 42 I 59 47 I 39 -67 I

> writedata(terminal, [[64 + 42*I, 59 - 47*I],[39 - 67*I, 10 + 17*I]], float, proc(F, z) local L; L:= cat(convert(Re(z), string), `if`(sign(Im(z)) = 1, `+`, NULL), convert(Im(z), string), `*`, `i`): fprintf(F, `%s`, L) end proc);

64+42 i 59-47 i

39-67 i 10+17 i

Рекомендуется обратить внимание на принципы организации пользовательских форматов выводимых структур данных на основе четвертого фактического Proc-аргумента writedata-функции доступа. В качестве значения первого СФ-аргумента writedata-функции можно указывать и default-значение, определяющее, как правило, консоль ПК.

Наконец, четвертый необязательный Proc-аргумент обеспечивает возможность вывода данных (заданного третьим фактическим аргументом формата) в файл, определяемый первым фактическим СФ-аргументом, в виде, определяемом Proc-процедурой от двух аргументов. Механизм такого подхода в общих чертах можно проиллюстрировать на функциональной конструкции следующего простого вида:

writedata(<СФ>, <Данные>, <Формат>, proc(F, x) y:= map(H, x); W(F, y) end proc)) В качестве четвертого фактического аргумента здесь выступает Proc(F,x)-процедура, получающая в качестве первого фактического F-аргумента переданное значение фактическому СФ-аргументу writedata-функции, а в качестве значений фактического x-аргумента выступают значения структуры данных, определяемой вторым фактическим аргументом writedata-функции. В общем случае тело процедуры включает определение H-функции преобразования значений, применяемой ко всем элементам х-структуры данных, и W-функции, обеспечивающей вывод структуры преобразованных данных в файл либо на печать. Последние два примера предыдущего фрагмента иллюстрируют использование Proc-аргумента writedata-функции для определения собственных форматов представления элементов структур данных, выводимых в файл или на печать. В частности, в последнем примере реализован формат вывода значений структур данных в общепринятой математической нотации. В качестве полезного упражнения читателю рекомендуется запрограммировать несколько процедур форматирования значений элементов структур данных, выводимых writedata-функцией. Особенности использования четвертого аргумента writedata-функции, также функции в целом довольно детально рассмотрены в наших книгах [12,32,41].

Обратной к рассмотренной writedata-функции является readdata-функция, имеющая следующий простой формат кодирования: readdata(<СФ>, {n|<Формат>|<Формат>, n})

и обеспечивающая чтение данных из файла, указанного ее первым фактическим СФ-аргументом (спецификатор файла либо номер приписанного ему логического канала в/в), в точку вызова функции (переменную). Если считываются числовые данные, то они должны быть {integer|float}-типа и упорядочены в форме матричной структуры, в которой столбцы разделяются символом пробела {hex(20)}. Текстовые файлы такой структуры легко создаются как средствами системы MS DОS, например, copy-командой непосредственно с консоли, так и в среде текстовых редакторов. В среде пакета для этих целей служит уже рассмотренная выше writedata-функция и ряд других средств.

Если вызов readdata-функции не определяет (n-аргумент) число считываемых столбцов данных, то по умолчанию считывается первый столбец и возвращается в виде списка значений. При считывании нескольких столбцов функция возвращает вложенный список, при этом элементы-списки представляют соответствующие строки возвращаемых столбцов данных. По умолчанию readdata-функция считывает числовые данные float-типа. Использование необязательного формат-аргумента, допускающего {integer|float|string}значение, позволяет определять формат считываемых функцией данных. При считывании нескольких столбцов данных для каждого из них можно определять свой формат из числа трех перечисленных. В этом случае формат-аргумент кодируется в виде списка, аналогично рассмотренному случаю для writedata-функции, но здесь имеется ряд особенностей, требующих повышенного внимания [12,32,41]. Нижеследующий пример иллюстрирует применение readdata-функции для считывания данных из файла.