Being a newcomer to Adobe Director 11 and it's implementation of lingo, I went in search of a printf() function to assist the formating of numerical data. The only version I found had little in common with the ansi C printf, so I wrote my own.
on printf formatStr, varList
outStr = ""
vi = 1 -- set for first in varList
repeat with i = 1 to formatStr.length
c1 = formatStr.char[i]
n1 = charToNum(c1)
case n1 of
37 -- %
if vi > count(varList) then
alert "ERROR No enough variables to match format" & formatStr
end if
v = varList[vi]
--put "Var #" & string(vi) & "= " & string(v)
vi = vi + 1
p = 0 -- places before decimal point
n = 0 -- number accumulator
decimal_found = False
leading_zeros = False
left_justify = False
repeat with j = i + 1 to formatStr.length
c2 = formatStr.char[j]
n2 = charToNum(c2)
-- convert uppercase to lowercase
if n2 >= 65 and n2 <= 90 then
n2 = n2 + 32
c2 = numtoChar(n2)
end if
--put "Next format letter" & c2
-- is this a numeral
if n2 >= 48 and n2 <= 57 then
if n2 = 48 and n = 0 and not decimal_found then
leading_zeros = True
--put "Leading zeros"
end if
n = n*10 + n2 - 48
else
case c2 of
"%"
outStr = outStr & "%"
"." -- decimal point
decimal_found = True
p = n
n = 0
"-"
left_justify = True
"*"
-- use next variable as format number
if not integerP(v) then
alert "ERROR Variable type does not match integer format" & formatStr
end if
n = v
vi = vi + 1
"c"
--put "Character type places" & n
if not stringP(v) then
alert "ERROR Variable type does not match string format" & formatStr
end if
vStr = v
i = j
exit repeat
"s"
--put "String type places" & n
if not stringP(v) then
alert "ERROR Variable type does not match string format" & formatStr
end if
vStr = v
i = j
exit repeat
"d"
--put "Decimal type Places" & n
if not integerP(v) then
alert "ERROR Variable type does not match integer format" & formatStr
end if
vStr = string(v)
i = j
exit repeat
"f"
--put "Float type Places" & p & " Decimals" & n
if not integerP(v) and not floatP(v) then
alert "ERROR Variable type does not match float format" & formatStr
end if
vStr = string(v)
if decimal_found then
--put "Raw",vStr
dn = offset(".",vStr)
dp = vStr.length - dn
--put "Decimal places" & dp
if dp > n then
--put "remove excess decimal places"
vStr = vStr.char[1..vStr.length - (dp-n)]
else
if dp < n then
--put "add extra decimal places"
repeat with pi = 1 to dp-n
vStr = vStr & "0"
end repeat
end if
end if
end if
i = j
exit repeat
otherwise
alert "ERROR Format not recognised" & formatStr
end case
end if
end repeat
if not decimal_found then
p = n
end if
--put "Raw variable" & vStr
-- left justify puts vStr first
if left_justify then
outStr = outStr & vStr
end if
-- pad the output if necessary
if vStr.length < p then
repeat with pi = 1 to p - vStr.length
if leading_zeros then
outStr = outStr & "0"
else
outStr = outStr & " "
end if
end repeat
end if
-- normal right justify
if not left_justify then
outStr = outStr & vStr
end if
-- put string(i)
-- put string(formatStr.length)
otherwise
-- put "Non format" & c1
outStr = outStr & c1
end case
-- ready to look for the next problem
end repeat
return outStr
end
string = printf(format_string,list_of_variables)
Format_string currently supports %[-][0][# or *][.# or .*][d, f or s] where # is an integer. For an explanation of printf() format consult any C text book, but basically:
Naturally some of these work in combination and others don't.
In use this lingo printf() is really more like sprintf(str,...) from C, printf() from Matlab or format % tuple from python, in that the function returns a string rather than printing directly to the stdout path and that the arguments are passed to it in a list.
As an example consider the following code:
member("CountDown").text = printf("%02d:%02d:%02d",[h,m,s])
where h, m and s are integers representing hours, minutes and seconds. This might be printed out as 00:00:00.
I can't see any reason why it would be usefull to add the %u (unsigned) or %p (pointer) formats.
Please contact me with any improvements you would care to offer.