2010-01-21 17 views
6

Ho problemi in Tcl utilizzando i numeri con zeri iniziali. Sto analizzando alcuni numeri che possono avere zeri iniziali, come "0012", che dovrebbe essere interpretato come l'intero "dodici".Gestione dei numeri con zeri iniziali in 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) 

Qual è il modo migliore per gestire i numeri che potrebbero avere uno zeri iniziali in Tcl?

Su un lato nota, ciò che costituirebbe un numero ottale valida in Tcl, se "08" è un uno valido?

risposta

7

Ti consigliamo di leggere Tcl and Octal Numbers al wiki Tcl. Il modo canonico consiste nel considerare l'input come una stringa e utilizzare il comando scan per estrarre i numeri. Che porta a questo, sì multilinea, 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

Multilinea, sì, ma la raccomandazione "scansione" è la più compatta e facile da capire che ho visto. "set b [scan b% d]" soddisfa le mie esigenze. Il resto del forceInteger proc è dedicato alla convalida dell'input difensivo. –

1

This link dovrebbe aiutare a

numeri ottali valido può contenere solo le cifre 0-7 e deve iniziare con 0

+0

Questo collegamento suggerisce di scrivere un proc multilinea per eliminare gli zeri. Speravo che potesse esserci qualcosa di più semplice. –

+0

Correggere sulle cifre ottali. Silly me. Ovviamente "8" non è una cifra ottale valida. Internal off by one error ... –

1

Personalmente ho sempre usato:

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

per igienizzare $troublesome_number s .

+0

Questo metodo regsub è corretto ma molto simile a una delle soluzioni nel link aperto da Mick Sharpe. –

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" 

una soluzione più semplice è:

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

ho tutti questi versione di Tcl/Tk 8.1 programmi che sono diventato rotto perché Tcl/Tk 8.5.10 non sta gestendo correttamente conversioni stringa/numeriche.

Qui, guscio in Tcl, e digitare:

% expr {01} 
1 

(e così via ..)

% expr {06} 
6 

% expr {07}  
7 

e poi si arriva a 8 ...

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

sembra un numero ottale non valido

Ma io t peggiora. Ancora in guscio Tcl, provate questo:

nel mio guscio Tcl8.1:

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

Ma nel mio nuovo e migliorato Tcl8.5 shell, ottengo un errore:

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

Questo è solo stupido! Ho tutto questo codice che funziona bene in Tcl7.6 e Tcl8.1, ma che ha iniziato a dare risultati strani, casuali in Tcl8.5. Solo quando il numero 08 è successo a generato o utilizzato! Ho passato ore a cercare di capire il problema. Ma si scopre che è solo uno sgradevole sacco del codice che sto usando!

Quindi, sto inviando questo sproloquio come un avvertimento.
Tcl/Tk versione 8.5.10 gestisce il numero otto in modo errato. Se si è in attesa di un comportamento corretto dalle istruzioni di formato, questo non si verificherà. Il codice volerà lungo, finché non incontra una stringa del valore di {08}, e l'interprete Tcl 8.5.10 genererà un errore, perché si assume che {08} è una speciale-caso ottale numero, indipendentemente dal fatto che tutti gli altri piccoli numeri abbiano funzionato bene!

Una possibile soluzione al problema sopra menzionato è il downgrade a una shell Tcl 8.1 . Ho confermato che tale versione gestisce almeno le istruzioni del formato per il numero 08 in modo corretto. La shell Tcl 8.5.10 semplicemente no.

+0

È necessario utilizzare [scansione "08"% d] invece di [formato "% .0f" "08"]. scansione convertire la stringa "08" in numero (8). format converte il numero "08" in stringa ma "08" è un numero non valido in tcl quindi non utilizzare il formato in questo caso – Hazem

2

Questa è la soluzione più pulita:

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

Inoltre:

% 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 

scansione: Questo è probabilmente ciò che ti interessa. Converte lo "09" (anche come stringa) in un numero decimale 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.

espr: Macchine qui per dimostrare che expr interpreta il valore come un numero, e affronta la domanda iniziale. Valuta un'espressione (ad esempio expr {2*3} restituisce 6).

+0

Se stai lavorando con numeri estremamente grandi, cioè non date o orari, usa questa sintassi: '' 'scansione $ nove% 11d nove''' – 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 
Problemi correlati