> `Результат форматирования`:= sprintf(`%s: %c|% 4.3s|%4X|%+12.8E|%08.6f|%+ 6.2G|`, `Проверка функции`, `G`, `AVZ`, 10, evalf(Pi*Catalan), 17, 350.65):
> `Результат форматирования`;
"Проверка функции: G| AVZ| A|+2.87759078E+00|17.000000|+3.51E+02|"
> fprintf("C:/ARM_Book/Academy/Report..99", "%s: %c|% 4.3s|% .7a|\n Перенос: %m| %A|%%120|", `Проверка функции`, `G`, `AVZ64` ,sqrt(x), evalf(Pi), e^x); ⇒ 65
При записи в файл (указанный своим спецификатором) по функции fprintf отформатированных выражений следует иметь в виду, что новый файл открывается на запись в режиме дописывания (append-режим записи) как файл TEXT-формата, а при записи в уже существующий его содержимое полностью обновляется. При этом, файл не закрывается и последующая попытка загрузить его по read-предложению инициирует ошибочную информацию, не отражающую суть особой ситуации "конец файла". Поэтому в данной ситуации требуется предварительное закрытие файла, как это иллюстрирует следующий фрагмент записи по fprintf-функции в файл определения Kr-процедуры с последующей загрузкой его в память и автоматическим вычислением.
> F:="C:/ARM/Academy/Books2006": fprintf(F, "%A", "Kr:= proc() [args] end proc;"); ⇒ 28
> read(F): Kr(64, 59, 39, 44, 10, 17, 2006, 65); ⇒ Kr(64, 59, 39, 44, 10, 17, 2006, 65) Error, "C:/ARM/Academy/Books2006" is an empty file
> close(F); read(F): Kr(64, 59, 39, 44, 10, 17, 2006, 65); ⇒ [64, 59, 39, 44, 10, 17, 2006, 65]
Данное обстоятельство следует иметь в виду при использовании fprintf-функции.
Ввиду наличия достаточно развитых средств по конвертации одного типа выражений в другой (convert-функция) и функциональных средств printf-группы пользователь имеет вполне приемлемые возможности (при наличии соответствующего навыка) для обеспечения вполне удовлетворительного форматирования результатов своих работ, прежде всего, математического характера, в среде Maple-языка, включая подготовку их к публикации. В этом отношении может быть предложен один практически полезный прием, упрощающий процедуру подготовки Maple-документа к публикации, неоднократно нами используемый ранее.
Для обеспечения возможности оформления в документе формульных конструкций, содержащих функции Maple-языка, можно использовать следующий искусственный прием. Любую английскую букву идентификатора такой функции следует заменить на одинаковую по написанию букву русского алфавита, определяя такой идентификатор неизвестным для языка пакета. Например, заменив в именах процедуры solve и функции nops английскую букву “о” на русскую, получаем формульную конструкцию требуемого вида. Во втором примере в имени evalf-функции английская "a" заменена на русскую "а". В качестве такого типа замен могут быть успешно использованы русские буквы {а, е, к, о, р, с, у, х}, например:
> R:= sum((x - sоlve(P, x))[k], k=1 .. nоps([sоlve(P, x)])); nоps [( sоlve(P x, )]) R := ∑ (x − sоlve(P x, )) k k = 1 > sqrt(evаlf(Pi*Art^2 + gamma*Kr^2)); ⇒ evàlf(π Art2 + γ Kr2 ) |
Между тем, следует отметить, что искушенный пользователь в рамках средств Maple-языка может обнаружить массу подобных искусственных приемов, весьма полезных в оформительских целях. Ниже вопросы форматирования будут детализироваться в прикладных аспектах.
Являясь встроенным языком программирования в среде пакета, ориентированного, в первую очередь, на символьные вычисления (компьютерная алгебра) и обработку, Mapleязык располагает относительно ограниченными возможностями по работе с данными, находящимися во внешней памяти ЭВМ. И в этом отношении Maple-язык существенно уступает традиционным языкам программирования C, Basic, Fortran, Cobol, PL/1, ADA, Pascal и др. Вместе с тем, ориентируясь, в первую очередь, на решение задач математического характера, Maple-язык предоставляет набор средств для доступа к файлам данных, который вполне может удовлетворить достаточно широкий круг пользователей физико-математических приложений пакета. В предлагаемой главе средства доступа к файлам будут рассмотрены довольно детально, по полноте изложения в значительной степени перекрывая поставляемую с пакетом документацию [79-85], а также [54-62]. С целью развития системы доступа к файловой системе компьютера нами был разработан целый ряд эффективных средств, представленных в нашей Библиотеке [41,103,108,109]. Начиная с Maple 9, пользователю предоставляются дополнительные средства работы с файлами данных, поддерживаемые процедурами модуля FileTools, однако они существенно уступают средствам, предоставляемым нашей Библиотекой [41,103,108,109].
Средства Maple-языка обеспечивают доступ пользователя к файлам нескольких типов, которые можно условно разделить на две большие группы: внутренние и внешние. При обычной работе пакет имеет дело с 3-4 различными типами внутренних файлов, из которых отметим лишь наиболее важные на первых этапах работы с пакетом.
Однако, перед дальнейшим рассмотрением целесообразно детализировать понятие спецификатора файла (СФ), кратко упоминавшегося выше. Как уже отмечалось СФ определяет полный путь к искомому файлу в файловой системе ЭВМ. Как правило, он кодируется в виде значения {string, symbol}-типа и для платформы {DOS|Windows} имеет следующий формат кодирования:
<УВВ>:{\|/}<Подкаталог_1>{\|/}<Подкаталог_2>…{\|/}<Подкаталог_n>{\|/}<Файл> где: УВВ определяет логическое имя устройства (например, жесткий диск, CD и т.д.), Подкаталог_к – подкаталог файловой системы ЭВМ и Файл – имя искомого файла в формате <Основное имя>{.<Расширение имени>}. Символ {\|/} служит в качестве разделителя в определении пути и по dirsep-параметру функции kernelopts, обеспечивающей механизм связи между пользователем и ядром Maple, можно получать его значение по умолчанию: > kernelopts(dirsep); ⇒ "\". Данное значение не переопределяемо.
Под текущей понимается цепочка подкаталогов, с которой работают средства доступа пакета по умолчанию, т.е. в случае указания в качестве СФ только имени файла. По функции currentdir() возвращается значение текущей цепочки, тогда как по вызову функции currentdir(<Цепочка>) устанавливается указанная цепочка в качестве текущей:
> currentdir(), currentdir(`D:/Software/Academy`), currentdir();
"C:\Program Files\Maple 10", "C:\Program Files\Maple 10", "D:\Software\Academy"
Как иллюстрирует пример, при установке новой текущей цепочки подкаталогов функция currentdir возвращает предыдущее значение для текущей цепочки, что позволяет при необходимости легко возвращаться к предыдущему значению. При этом, следует иметь в виду, что установка текущей цепочки отменяется только перезагрузкой пакета либо ее переопределением (т.е. на нее не действуют предложения restart, done, quit, stop). Более того, установленный по currentdir-функции каталог становится текущим только для внешних файлов пакета, т.е. данная функция используется с рассматриваемыми ниже функциями доступа к внешним файлам данных пакета.
Между тем, при попытке определить текущим несуществующий каталог вызов функции currentdir вызывает ошибочную ситуацию, например:
> currentdir(`C:/Tallinn/Academy/Grodno`);
Error, (in currentdir) file or directory, C:/Tallinn/Academy/Grodno, does not exist Поэтому, с целью расширения функциональных возможностей стандартного средства нами была создана процедура Currentdir, исходный текст которой приведен ниже.
Currentdir := proc() local a b c, , ; assign67(Release(a), c = currentdir( )), `if`(nargs = 0, RETURN(Currentdir(a)), `if`(map(type, {args} {, 'string', 'symbol'}) = {true}, assign(b = CF cat(( "" args[1], ))), ERROR("arguments %1 should be strings or symbols", [args]))), `if`(1 < nargs, ERROR("%1 quantity of actual arguments more than 1"[args], ), `if`( type(b, 'dir'), op [( currentdir(b), c][-1]), `if` type( ,( b 'file'), Currentdir clsd(( CFF(b)[1 .. -2], "\")), op([MkDir(b), currentdir(b), c][-1])))) end proc > Currentdir(), Currentdir(`C:/Tallinn/Academy/Grodno`), Currentdir(), Currentdir(); "c:\program files\maple 8", "c:\program files\maple 8", "c:\tallinn\academy\grodno", "c:\program files\maple 8" |
Вызов Currentdir(F) делает текущим каталог, определенный полным путем к нему F; при этом, если путь F не существует, он создается. В любом случае вызов процедуры с аргументом возвращает предыдущий текущий каталог, тогда как вызов процедуры без аргументов восстанавливает в качестве текущего каталог, который был определен текущим при инсталляции пакета Maple. Во многих случаях работы с файловой системой компьютера данная процедура предпочтительнее стандартной. Процедура, в свою очередь, существенно использует нашу процедурe MkDir [41,103,108,109], которая существенно расширяет стандартную функцию mkdir, предназначенную для создания каталогов.
MkDir := proc(F::{string, symbol}) local cd r k h z K L, , , , , , , Λ, , ,t d ω, , , , , ;u f s g v s := "Path element <%1> has been found, it has been renamed on <%2>"; if Empty(F) then return NULL elif type(F, 'dir') and nargs = 1 then return CF(F) elif type(F, 'file') and nargs = 2 then return CF(F) else cd := currentdir( ) end if; u K, := interface(warnlevel), CF(F); assign(Λ = (x → close open( ,( x 'WRITE')))), assign(L = CFF(K), ω = 0); |
assign(r = cat(L[1], "\")), `if`(nargs = 2 and args 2[ ] = 1, assign(' 'L = L[1 .. -2], ' 'ω = L[-1], t = 1), 1); if L = [ ] then assign(g = cat(r, r[1]), v = cat(r, "_", r[1])); if t ≠ 1 then return r elif type(g, 'dir') then return null(Λ(v)), v elif type(g, 'file') then return g else return null(Λ(g)), g end if end if; for k from 2 to nops(L) do currentdir( )r , assign(' 'g = cat(r, L k[ ])); if type(g, 'dir') then try mkdir(g) catch : NULL end try elif type(g, 'file') then assign(' 'L k[ ] = cat "_",( L k[ ]), ' 'd = 9); try mkdir(cat(r, L[k])) catch "file I/O error": d := 9 catch "directory exists and is not empty" := : d 9 end try ; assign(' 'd = 9), WARNING( ,s L k[ ][2 .. -1], L k[ ]) else mkdir(cat(r, L[k])) end if; assign(' 'r = cat(r, L k[ ], "\")) end do; if t = 1 then if type(cat(r, ω), 'dir') then op [( Λ(cat(r, "_", ω)), WARNING(s, ω, cat "_",( ω))]) else return `if`(d = 9, cat( ,r ω), CF(F)), Λ(cat(r, ω)), null currentdir(( cd)) end if; cat(r, "_", ω), null currentdir(( cd)) else null(currentdir(cd)), `if`(d = 9, r[1 .. -2], CF(F)) end if end proc > MkDir(Tallinn), MkDir(Tallinn, 1); Warning, Path element <tallinn> has been found, it has been renamed on <_tallinn> "c:\program files\maple 8\tallinn", "c:\program files\maple 8\_tallinn" > type(%[1], 'dir'), type(%[2], 'file'); ⇒ true, true |
В случае кодирования несуществующего каталога он создается. Если вызов процедуры использует в качестве второго необязательного аргумента 1, то создается по указанному пути пустой закрытый файл. В любом из указанных случаев вызов процедуры MkDir возвращает созданный полный путь к каталогу или файлу. Процедура имеет и другие полезные особенности, например, позволяя создавать в каталогах файлы при наличии в них одноименных подкаталогов. В целом, процедура MkDir расширяет не только стандартную функцию mkdir, но и одноименную команду MS DOS [41,103,108,109]. Нами в дополнение к базовой процедуре MkDir был создан еще ряд ее полезных модификаций, включая обобщение на случай, когда делается попытка создания каталога или файла на устройстве или в каталоге, защищенном от записи. Вызов процедуры MkDir4 обеспечивает создания нужного каталога или файла на дисковом устройстве с возвратом полного пути к нему. Если устройство либо какой-либо элемент создаваемого пути защищен от записи, то процедура выбирает первое доступное устройство (по выбору может быть и устройство «А»). При отсутствии доступных устройств инициируется ошибочная ситуация с диагностикой «Error, in (MkDir4) accessible disk drives do not exist» [108,109]. Ниже представлен исходный текст процедуры и примеры ее применения.