views:

307

answers:

3

I am having trouble in Tcl using numbers with leading zeros. I am parsing some numbers that can have leading zeros, such as "0012", which should be interpreted as the integer "twelve".

$ tclsh
% set a 8 
8
% set b 08
08
% expr $a - 1
7
% expr $b - 1
expected integer but got "08" (looks like invalid octal number)

What is the best way to handle numbers that might have a leading zeros in Tcl?

On a side note, what would constitute a valid octal number in Tcl, if "08" is an invalid one?

+1  A: 

This link should help you

Valid octal numbers can only contain the digits 0-7 and must start with 0

Mick Sharpe
That link suggest writing a multiline proc to strip zeros off. I had hoped there might be something simpler.
Christopher Bruns
Correct on the octal digits. Silly me. Of course "8" is not a valid octal digit. Internal off by one error...
Christopher Bruns
+1  A: 

Personally I've always used:

set $clean_number [regsub {^0*(.+)} $troublesome_number {\1}]

to sanitize $troublesome_numbers.

slebetman
This regsub method is correct but very similar to one of the solutions in the link Mick Sharpe opened with.
Christopher Bruns
+4  A: 

You'll want to read Tcl and Octal Numbers at the Tcl wiki. The canonical way is to treat your input as a string and use the scan command to extract the numbers. That leads to this, yes multiline, proc:

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
}
glenn jackman
Multiline, yes, but the "scan" recommendation is the most compact and easy to understand that I have seen. "set b [scan b %d]" meets my needs. The remainder of the forceInteger proc is devoted to defensive input validation.
Christopher Bruns