2010-01-21 37 views
6

Tôi gặp sự cố trong Tcl khi sử dụng các số có số 0 đứng đầu. Tôi đang phân tích cú pháp một số số có thể có số 0 đứng đầu, chẳng hạn như "0012", số này sẽ được hiểu là số nguyên "mười hai".Xử lý các số có số 0 đứng đầu trong Tcl

$ 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) 

Cách tốt nhất để xử lý các số có thể có số 0 đứng đầu trong Tcl là gì?

Trên ghi chú bên, những gì sẽ cấu thành một số bát phân hợp lệ trong Tcl, nếu "08" là số không hợp lệ?

Trả lời

7

Bạn sẽ muốn đọc Tcl and Octal Numbers tại wiki Tcl. Cách kinh điển là xử lý đầu vào của bạn dưới dạng chuỗi và sử dụng lệnh scan để trích xuất các số. Điều đó dẫn đến này, có nhiều dòng, 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 
} 
+1

Multiline, vâng, nhưng đề xuất "quét" là nhỏ gọn nhất và dễ hiểu mà tôi đã thấy. "set b [scan b% d]" đáp ứng nhu cầu của tôi. Phần còn lại của proc forceInteger được dành cho việc xác thực đầu vào phòng thủ. –

1

This link sẽ giúp bạn

số bát phân hợp lệ chỉ có thể chứa các chữ số 0-7 và phải bắt đầu với 0

+0

Liên kết đó đề xuất viết một proc nhiều dòng để xóa số không. Tôi đã hy vọng có thể có một cái gì đó đơn giản hơn. –

+0

Đúng trên các chữ số bát phân. Tôi ngớ ngẩn quá. Tất nhiên "8" không phải là chữ số bát phân hợp lệ. Nội bộ tắt bởi một lỗi ... –

1

Cá nhân tôi đã luôn luôn được sử dụng:

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

để khử trùng $troublesome_number s .

+0

Phương pháp regsub này là chính xác nhưng rất giống với một trong các giải pháp trong liên kết Mick Sharpe mở ra với. –

2
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" 

một giải pháp dễ dàng hơn là:

set x 08 
regsub {^[0]} $x {\1} x 
puts $x 
=>8 
2

tôi có tất cả những 8.1 chương trình phiên bản Tcl/Tk đã trở thành bị hỏng vì Tcl/Tk 8.5.10 không xử lý đúng các chuyển đổi chuỗi/số.

Ở đây, shell vào Tcl, và gõ:

% expr {01} 
1 

(và vân vân ..)

% expr {06} 
6 

% expr {07}  
7 

và sau đó chúng tôi nhận tới 8 ...

% expr {08} 
missing operator at "[email protected]_" 

trông giống như số bát phân không hợp lệ

Nhưng tôi t tồi tệ hơn. Vẫn trong Tcl vỏ, hãy thử này:

Trong vỏ Tcl8.1 tôi:

% format "%.0f" {08} 
8 

Nhưng mới và cải tiến Tcl8.5 vỏ của tôi, tôi nhận được một lỗi:

% format "%.0f" {08} 
expected floating-point number but got "08" (looks like invalid octal number) 

này chỉ là ngốc nghếch! Tôi có tất cả các mã này hoạt động tốt trong Tcl7.6 và Tcl8.1, nhưng bắt đầu cho ra kết quả ngẫu nhiên, ngẫu nhiên trong Tcl8.5 . Chỉ khi số 08 xảy ra với được tạo hoặc sử dụng! Tôi đã dành hàng giờ cố gắng tìm ra vấn đề. Nhưng hóa ra đó chỉ là một mã số khó chịu khó chịu mà tôi đang sử dụng!

Vì vậy, tôi đăng bài rant này như một cảnh báo.
Phiên bản Tcl/Tk 8.5.10 xử lý số tám không chính xác. Nếu bạn đang mong đợi hành vi lành mạnh từ các tuyên bố định dạng của mình, thì này sẽ không xảy ra. Mã của bạn sẽ bay dọc theo, cho đến khi gặp chuỗi có giá trị là {08} và trình thông dịch Tcl 8.5.10 sẽ phát sinh lỗi, vì nó giả định rằng {08} là số đặc biệt số bát phân, bất kể thực tế là tất cả các số ít khác bạn đã sử dụng sẽ chỉ hoạt động tốt!

Một giải pháp khả thi cho vấn đề nêu trên là hạ cấp xuống vỏ Tcl 8.1 . Tôi đã xác nhận rằng phiên bản đó ít nhất xử lý các định dạng báo cáo cho số 08 một cách chính xác. Tcl 8.5.10 shell đơn giản là không.

+0

Bạn nên sử dụng [scan "08"% d] thay vì [format "% .0f" "08"]. quét chuyển đổi chuỗi "08" thành số (8). định dạng chuyển đổi số "08" thành chuỗi nhưng "08" là số không hợp lệ trong tcl vì vậy không sử dụng định dạng trong trường hợp này – Hazem

2

Đây là giải pháp sạch:

% expr [ scan "08" %d ] - 1 
7 

Hơn nữa:

% 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 

quét: Đây có lẽ là những gì bạn quan tâm. Chuyển đổi "09" (thậm chí dưới dạng chuỗi) thành số thập phân 9.

Note:
1. If this value cannot be converted into a decimal value, then scan will return an empty string ({}).
2. If a variable name is provided to the scan command (like the number variable in the example above), then the return value indicates status, 0 : failed to parse decimal, and 1 : success.

expr: Được sử dụng ở đây để chứng minh rằng expr giải thích giá trị như một số, và giải quyết các câu hỏi ban đầu. Nó đánh giá một biểu thức (ví dụ: expr {2*3} trả về 6).

+0

Nếu bạn đang làm việc với số lượng cực lớn, tức là không phải ngày hoặc thời gian, thì hãy sử dụng cú pháp này: '' 'quét $ chín% 11d chín''' – nikc

-1
#!/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 
Các vấn đề liên quan