|
Navigation
Related Links
No changes found Who is online
· 4 online users
|
Изменение и дополнение механизма форматного преобразования строкИзменение и дополнение механизма форматного преобразования строк. Устройство механизма форматного преобразования чисел в форте сделан очень удобно, но оно не всегда достаточно. Так, например, когда сталкиваешься с необходимостью распечатать число в фиксированной системе исчисления, приходится делать так: К списку недостатков(или неудобностей) стандартного механизма можно добавить невозможность вывести "постороннее" число во время работы внутри <# #>, а так же отсутствие стандартного механизма для преобразования чисел после десятичной точки. Конечно, из-за этого не обязательно что-то менять в устройстве форматного преобразования чисел. Более того, делать систему несовместимой со старой. Собственно говоря, то бы хотелось получить? В первом случае: : name !FixedBase <# #S #> TYPE ; это сделать просто: User !CurrentBase \ текущая система исчисления \ начать форматное преобразование строки : <# ( D BASE -- D ) !CurrentBase ! ... ; : # ( D -- D ) тут нет ничего сложного, за исключением того факта, что старые программы не получится откомпилировать без коррекции исходных текстов, что не очень желательно. Эту проблему можно обойти так: \ начать форматное преобразование строки: новый вариант.
Примеры:
: name ( N --> ) 10 {# #S #> TYPE ;
Теперь перейдем ко второму примеру: по-моему, текст стал прозрачнее и чище. К тому же появляется возможность делать что-то наподобие следующего примера: Едем дальше. Преобразование чисел после десятичной точки(или запятой). Сначала о формате чисел, с которыми я хотел бы работать: HIGH(CELL).LOW(CELL) <-- TOS то есть число с фиксированной точкой упаковывается в стандартное двойное число, и ряд операций для работы с двойными числами становится сразу доступен для нас(D+ D- D2/ D2*).
\ получить очередную цифру
: $ ( n --> n*base C) !CurrentBase @ UM* >digit ;
и
USER places \ число отображаемых чисел.
\ получить все цифры после запятой
\ Возможен вариант и без рекурсии, но он не так красив.
теперь для вывода таких чисел достаточно написать: \ колличество отображаемых знаков после десятичной точки
10 CONSTANT PRECISION
\ преобразовать число в строку (формат с фиксированной точкой) \ с R знаками после "." : (Pr) ( P R --> Asc # )
places !
TUCK DABS SWAP
<# $S [CHAR . HOLD 0 #S ROT SIGN #> ;
: (P) ( P -- ASC # ) PRECISION (pr) ; : P. ( P -- ) (P) TYPE ; Слова же >DIGIT в СПФе к сожалению нет в явном виде (хотя оно не помешало бы) можно определить так:
: >DIGIT ( N --> Char ) DUP 10 > IF 7 + THEN 48 + ;
Остается нерешенной проблема с использованием "вложенных" друг в друга <# .. #>. Она на мой взгляд не так важна для форта, но все-же не является на мой взгляд лишней. Пример(как хотелось бы):
: name ( N -- ASC # )
конечно, немножечко дутый, но, тем не менее, что-то подобное запросто может возникнуть. Решить эту часть задачи легко, создав стек строк. Реализацию см. в spf_print.f.release и примеры в PAD replacement idea - в примерах заменить <# на {# и #> на #}. DmitryZyryanov А вот мне случайно понадобилось - и я нашёл выход. Можно относительно портабельно сохранять и восстанавливать состояние разбора формирования строки: : Save-# ( -- addr )
0. #>
OVER 0= OVER 0= OR IF 2DROP 0 EXIT THEN
DUP CELL+ ALLOCATE THROW >R
DUP R@ !
R@ CELL+ SWAP MOVE
R>
; : Restore-# ( addr -- )
?DUP 0= IF <# EXIT THEN
>R
<# R@ CELL+ R@ @ HOLDS
R> FREE THROW
; Oleg А чем не понравилось мое решение? DmitryZyryanov Просто не вспомнил про него, когда оно мне внезапно понадобилось :) Подумал - а вот тут бы сохранить состояние #-разбора. Кроме того у меня нет предположений, что строка лежит в PAD или ещё где-то. Мне нужно было портабельное решение. |
| Page Execution took real: 1.467 seconds |