Purpose: discuss the common pitfall of Tcl and octal numbers
Since Tcl does many things in an obvious manner, non-unix/c people are frequently surprised when they try this kind of code:
# somehow get today's date and time into MMM DDD YYY HH MM SS variables set newtime [expr $HH + 1]
and get an error at 8am. The problem - Tcl tries to do
expr 08 + 1
and complains. 08, you see, isn't really the string of the decimal number that comes after 7. Instead, it is an error. Tcl sees the leading 0 and treats the digits after it as representing a base 8 number. But there are no 8s (or 9s) in a base 8 number. So it generates an error.
The fix is to use:
scan $HH %d HH
which strips hazardous leading zeros. This is also safer than [string trimleft $HH 0] which can fail if $HH ever ends up containing "00" for example.
IDG There appears to be an octal related bug in string is. string is double 098 returns 1. (8.4.1 on windoze)
glennj: one potential pitfall of [scan] is that it might mask potential errors:
set n 09blah42 incr n
fails as expected with the error message:
expected integer but got "09blah42" while evaluating {incr n}
However:
set n 09blah42 scan $n %d n incr n ;# ==> n is now 10
Application writers might actually want to trap an invalid entry like that.
[2003-03-12] I see Kevin Kenny contributed the following to c.l.t
proc forceInteger { x } { set count [scan $x %d%s n rest] if { $count <= 0 || ( $count == 2 && ![string is space $rest] ) } { return -code error "not an integer: \"$x\"" } return $n } % forceInteger x not an integer: "x" % forceInteger 123 123 % forceInteger 08 8
This also covers my preceding concern:
% forceInteger 09blah42 not an integer: "09blah42"
Better than an explicit test of
[string is space $rest]
is to just skip (optional) spaces in the scan pattern:
proc forceInteger { x } { set count [scan $x {%d %c} n c] if { $count != 1 } { return -code error "not an integer: \"$x\"" } return $n }
[Refer to http://phaseit.net/claird/comp.lang.tcl/fmm.html#zero ]
[Explain improved diagnostic in 8.3.]
The question recently came up how do I display the octal value of a character in Tcl? and RS replied:
'the complete sequence is "format 0%o [scan a %c]"'
(but only with Tcl more recent than 8.2 or so; older scan works slightly differently).
http://www.tcl.tk/cgi-bin/tct/tip/114.html proposes modifying Tcl in a future release so that numbers beginning with 0 will not be interpreted by default as being expressed in octal. The proposer believes that far more users stumble upon this feature by accident than use it intentionally.