Работа с переменными, константами и массивами
Активная работа с nnCron зачастую требует хранения различных значений в течение продолжительного времени. Для этого используются переменные, константы и массивы. nnCron предоставляет пользователям все средства работы с переменными, константами и массивами, которыми обладает язык программирования Форт (SP-Forth) и добавляет несколько собственных удобных инструментов.
Переменные для хранения числовых значений создаются с помощью слова VARIABLE:
VARIABLE <var_name>
Определить переменную можно в самом начале задания, до раздела Action:, а заносить и извлекать из нее значение можно внутри раздела Action:. При создании переменной в нее заносится значение 0.
Пример:
#( test_variable NoActive
VARIABLE my_var Time: * * * * * * Action: \ ... работаем со значением переменной my_var )#
Значение заносится в переменную с помощью слова ! (восклицательный знак):
<var_value> <var_name> !
Пример:
\ теперь переменная my_var содержит число '12'
12 my_var !
Чтобы "извлечь" значение переменной используется слово @:
<var_name> @
Пример:
\ прибавляем '10' к значению переменной my_var ('12') \ результат - '22'
my_var @ 10 +
Обратите внимание, что слова @ и ! фактически работают с адресом переменной, который остается на стеке после указания (выполнения) ее имени: простое употребление имени переменной оставляет на стеке ее адрес в оперативной памяти компьютера.
Пример:
#( test_variable1 NoActive \ будем запускать задание вручную \ создаем две переменные VARIABLE first_var VARIABLE second_var Action: \ заносим число '18' в переменную 'first_var' 18 first_var ! \ прибавляем '4' к значению переменной 'first_var' \ и заносим результат в переменную 'second_var' \ (4 + 18 = 22) 4 first_var @ + second_var ! \ выводим значение переменной 'second_var' на экран MSG: "second_var = %second_var @%" )#
Существуют также специальные слова ON и OFF, которые облегчают использование переменных с условным оператором IF ... ELSE ... THEN. Слово ON присваивает указанной переменной значение -1, а OFF - значение 0:
\ устанавливаем переменной first_var значение -1 first_var ON \ устанавливаем переменной first_var значение 0 first_var OFF
Пример:
#( test_variable2 NoActive \ создаем переменную is_it_true? VARIABLE is_it_true? Action: \ присваиваем переменной значение '-1' is_it_true? ON \ извлекаем значение переменной \ и проверяем с помощью условного оператора is_it_true? @ IF MSG: "TRUE!" ELSE MSG: "FALSE!" THEN \ присваиваем переменной значение '0' is_it_true? OFF \ извлекаем значение переменной \ и проверяем с помощью условного оператора is_it_true? @ IF MSG: "TRUE!" ELSE MSG: "FALSE!" THEN )#
Многие слова Форта и nnCron возвращают числа двойной длины. Для создания переменной, которая может хранить числа двойной длины, используется слово 2VARIABLE. Чтобы занести значение в такую переменную, используйте слово 2!. Чтобы "извлечь" значение, используйте слово 2@.
Примеры:
#( test_file_size1 NoActive \ создаем переменную fsize, которая \ может хранить числа двойной длины 2VARIABLE fsize Action: \ сохраняем размер файла mkisofs.exe в переменной fsize FILE-SIZE: "c:\temp\mkisofs.exe" fsize 2! \ выводим значение переменной fsize в сообщении MSG: "mkisofs.exe size = %fsize 2@ <# #S #>%" )# #( test_file_size2 NoActive \ создаем переменную fsize2, которая \ может хранить числа двойной длины 2VARIABLE fsize2 Action: \ присваиваем переменной fsize2 значение двойной длины 10240 10240. fsize2 2! \ сравниваем содержимое переменной fsize2 \ с размером файла mkisofs.exe fsize2 2@ FILE-SIZE: "c:\temp\mkisofs.exe" D< IF MSG: "<" ELSE MSG: ">" THEN )#
См. также раздел Зона видимости переменных, констант и массивов.
Числовые переменные можно создавать и с помощью слова VALUE:
<initial_value> VALUE <var_name>
Как видите, при использовании VALUE значение переменной записывается в нее прямо при создании:
10 VALUE first_var 100 VALUE second_var
Удобство VALUE-переменной заключается в том, что вам не надо использовать специальное слово для извлечения содержащегося в ней значения. Чтобы поместить значение VALUE-переменной на стек достаточно указать (выполнить) в программе ее имя:
#( test_value_var NoActive
\ создаем переменную bingo, присваеваем ей значение '21' 21 VALUE bingo Action: \ выводим на экран значение переменной
MSG: "You are a winnner - %bingo%!" )#
Для записи нового значения в VALUE-переменную служит специальное слово TO. Вот как оно применяется:
<new_var_value> TO <var_name>
Пример:
#( test_value_var1 NoActive
\ создаем переменную counter_var, присваеваем ей значение '0' 0 VALUE counter_var Action:
\ выводим на экран значение переменной
MSG: "Initial value = %counter_var%"
\ присваиваем переменной новое значение '5' 5 TO counter_var \ выводим на экран новое значение переменной
MSG: "New value = %counter_var%" )#
См. также раздел Зона видимости переменных, констант и массивов.
Иногда бывает необходимо создать переменную, чье числовое значение не должно меняться в процессе дальнейшей работы. Такие переменные называются константами.
Для создания константы используйте специальное слово CONSTANT:
<const_value> CONSTANT <const_name>
Чтобы поместить значение константы на стек достаточно указать (выполнить) в программе ее имя:
#( test_constant NoActive
\ создаем константу one_o_one и присваиваем ей значение '101' 101 CONSTANT one_o_one Action: \ выводим значение константы на экран MSG: "One-O-One = %one_o_one%" \ используем константу в арифметическом действии MSG: "One-O-One - 1 = %one_o_one 1 -%" \ выводим значение константы снова, \ чтобы убедиться, что оно не изменилось MSG: "One-O-One = %one_o_one%" )#
См. также раздел Зона видимости переменных, констант и массивов.
Массив - это специальная структура, которая позволяет хранить множество значений под одним именем. Одно из традиционных применений массивов в nnCron - это промежуточное хранение символьных строк. Способы работы со строками подробно изложены в "Неотложной помощи по Форту".
Для создания массива используется слово CREATE:
CREATE <array_name>
А для того, чтобы выделить под только что созданный массив нужное количество памяти используется слово ALLOT.
Пример:
#( test_array
NoActive
\ создаем массив test_arr, размером в 256 байт CREATE test_arr 256 ALLOT
Action:
\ помещаем строку в массив
S" this is our string" test_arr PLACE
\ считываем строку из массива \ и выводим ее на экран
MSG: "Array contents: %test_arr COUNT%"
)#
Разумеется, в массивах можно хранить не только строки, но любые другие значения. Массивы даже можно инициализировать прямо при создании, например:
\ создаем массив, содержащий пять чисел CREATE numbers 1 , 2 , 3 , 4 , 5 ,
Детальное описание способов работы с массивами выходит за рамки документации nnCron. За дополнительной информацией обратитесь к документации языка программирования Форт.
См. также раздел Зона видимости переменных, констант и массивов.
Файловые и реестровые переменные
Главный недостаток вышеописанных переменных, констант и массивов заключается в том, что они хранят свои значения в оперативной памяти компьютера, а значит, при выключении компьютера или выгрузке nnCron из памяти эти значения будут утеряны. Как же быть, если хочется сохранить значение переменной, константы или массива между перезагрузками компьютера и nnCron?
Специально для этой цели nnCron предоставляет набор слов для создания строковых переменных, которые никак не зависят от перезагрузок компьютера и nnCron. Речь идет о т. н. файловых и реестровых переменных, т. е. переменных, которые хранят свои значения не в оперативной памяти компьютера, а в специальных файлах или ключах registry.
fVAR <var_name> (file variable)
regVAR <var_name> (registry variable)
При создании, файловая или реестровая переменная инициализируется пустой строкой. Чтобы поместить строковое значение в переменную используйте слово TO. Чтобы получить текущее значение переменной, просто укажите в программе ее имя:
#( test_persistent_var NoActive \ создаем одну файловую и одну реестровую переменную fVAR file_var regVAR reg_var Action: \ присваиваем переменным строковые значения S" first string" TO file_var S" second string" TO reg_var \ выводим оба значения на экран MSG: "There are %file_var% and %reg_var%" )#
Изначально файловые и реестровые переменные работают со строками, но если нужно сохранить в них не строки, а числа, то можно воспользоваться словами, которые преобразуют число в строку и наоборот (вопрос преобразования строк в числа и чисел в строки рассмотрен подробнее в "Неотложной помощи по Форту"):
\ преобразуем число в строку и записываем ее в файловую переменную
N>S TO file_var
\ считываем строку из файловой переменной и преобразуем ее в число file_var S>NUM
Для получения полной картины о работе файловых и реестровых переменных осталось разобраться - где же они хранятся. Каждая из файловых переменных хранится в одноименном файле в подкаталоге var того каталога, куда установлен nnCron. Реестровые переменные хранят свои значения в одноименных ключах registry в ветке HKEY_LOCAL_MACHINE\SOFTWARE\nnSoft\var\.
Существуют специальные слова, которые (в случае необходимости) позволят вам поменять место хранения файловых и реестровых переменных:
FileVarPath! ( a u
-- )
RegVarPath! ( a u -- )
Задает путь к каталогу (ветку registry), где должны храниться файловые/реестровые переменные. Не забудьте поставить обратный слеш (\) в конце указанного пути.
S" c:\temp\var\" FileVarPath!
S" HKEY_LOCAL_MACHINE\SOFTWARE\var\" RegVarPath!
Обратите внимание, это слово предназначено для использования в nncron.ini. Его нельзя применять в тексте задач.
uFileVarPath! ( a u
-- )
uRegVarPath! ( a u -- )
Задает путь к каталогу (ветку registry), где должны храниться файловые/реестровые переменные в пределах потока. Не забудьте поставить обратный слеш (\) в конце указанного пути.
S" c:\temp\var\" uFileVarPath!
S" HKEY_LOCAL_MACHINE\SOFTWARE\var\" uRegVarPath!
Слово предназначено для применения в тексте задач.
В случае необходимости вы можете программно удалить неиспользуемые файловые и реестровые переменные с помощью слов FILE-DELETE:/REG-DELETE-KEY:.
См. также раздел Зона видимости переменных, констант и массивов.
Зона видимости переменных, констант и массивов
Все пеpеменные (VARIABLE, VALUE), константы (CONSTANT) и массивы (CREATE ... ALLOT) являются глобальными, видны из дpугих задач и разделяются всеми экземплярами задач. Поэтому имеет смысл с особой тщательностью следить за уникальностью имени любой пеpеменной - во избежание дополнительной путаницы.
Вот кое-какие подpобности для особо любопытных: в пpинципе, хотя пеpеменные глобальны, каждая уникальная задача будет pаботать со своей пеpеменной. Дpугое дело констpукции вида: %VAR-NAME @% - они будут выводить только пеpеменную, использовавшуюся последней, вне зависимости от задания.
Пpимеp:
#( t1 VARIABLE V1 Action: 1 V1 ! MSG: "%V1 @%" )# #( t2 VARIABLE V1 Action: 2 V1 ! MSG: "%V1 @%" )#
Вопpос: угадайте, что выведет пеpвая задача?
Ответ: это зависит от того, выполнялась втоpая или нет. Если да, то пеpвая выведет 2, а если нет, то 0 (начальное значение всех пеpеменных).
Можно создавать переменные и массивы, которые будут уникальными для каждого экземпляра задачи (сколько экземпляров задачи работает, столько и переменных). Для этого надо создавать переменные при помощи следующих слов:
USER var1 USER-CREATE var2 256 USER-ALLOT USER-VALUE var3
Еще можно выделять память по ALLOCATE. В этом случае у каждой задачи тоже будет свой буфер:
#( vars NoActive USER buf Action: 256 ALLOCATE THROW buf ! ACTIVE-WINDOW buf @ PLACE 5000 PAUSE MSG: "%buf @ COUNT%" )#