Handling numbers with leading zeros in Tcl
I am having trouble in Tcl using numbers with leading zeros. I am parsing some numbers that can have leading ze开发者_StackOverflow社区ros, 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?
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
}
This is the cleanest solution:
% expr [ scan "08" %d ] - 1
7
Furthermore:
% expr [ scan "09" %d ]
9
% expr [ scan 09 %d ]
9
% set nine 09
09
% expr [ scan $nine %d ]
9
% set success [ scan $nine %d number ]
1
% puts $number
9
scan : This is probably what you care about. Converts the "09"
(even as a string) into a decimal number 9
.
Note:
1. If this value cannot be converted into a decimal value, thenscan
will return an empty string ({}
).
2. If a variable name is provided to thescan
command (like thenumber
variable in the example above), then the return value indicates status,0
: failed to parse decimal, and1
: success.
expr : Used here to demonstrate that expr
interprets the value as a number, and addresses the original question. It evaluates an expression (e.g. expr {2*3}
returns 6
).
I have all these Tcl/Tk version 8.1 programs that have become broken because Tcl/Tk 8.5.10 is not handling string/numeric conversions correctly.
Here, shell into Tcl, and type:
% expr {01}
1
(and so on..)
% expr {06}
6
% expr {07}
7
and then we get to 8...
% expr {08}
missing operator at "_@_"
looks like invalid octal number
But it gets worse. Still in Tcl shell, try this:
In my Tcl8.1 shell:
% format "%.0f" {08}
8
But in my new and improved Tcl8.5 shell, I get an error:
% format "%.0f" {08}
expected floating-point number but got "08" (looks like invalid octal number)
This is just goofy! I have all this code that works ok in Tcl7.6 and Tcl8.1, but which started giving weird, random results in Tcl8.5. Only when the number 08 happened to get generated or be used! I have spent hours trying to figure out the problem. But it turns out it is just a nasty sack of code that I am using!
So, I am posting this rant as a warning.
Tcl/Tk Version 8.5.10 handles the number eight incorrectly. If you are
expecting sane behavior from your format statements, this will not happen.
Your code will fly along, until it encounters a string valued at {08}, and
the Tcl 8.5.10 interpreter will generate an error, because it will assume
that {08} is a special-case octal number, regardless of the fact that all the
other little numbers you have used will have worked just fine!
One possible solution to the problem mentioned above is to downgrade back to a Tcl 8.1 shell. I have confirmed that that version does at least handle format statements for the number 08 correctly. Tcl 8.5.10 shell simply does not.
set $clean_number [regsub {^0*(.+)} $troublesome_number {\1}] this doesnt work
set clean_number ""
set $troublesome_number 08
% set $clean_number [regsub {^0*(.+)} $troublesome_number {\1}]
wrong # args: should be "regsub ?switches? exp string subSpec varName"
an easier solution is:
set x 08
regsub {^[0]} $x {\1} x
puts $x
=>8
This link should help you
Valid octal numbers can only contain the digits 0-7 and must start with 0
Personally I've always used:
set $clean_number [regsub {^0*(.+)} $troublesome_number {\1}]
to sanitize $troublesome_number
s.
#!/bin/tclsh
#Regsub TCL script to remove the leading zeros from number.
#Author : Shoeb Masood , Bagalore
puts "Enter the number"
set num [gets stdin]
regsub {^0*} $num {\1} num
puts $num
精彩评论