Обработка чисел с ведущими нулями в Tcl - PullRequest
6 голосов
/ 21 января 2010

У меня проблемы с Tcl, используя числа с ведущими нулями. Я анализирую некоторые числа, которые могут иметь начальные нули, такие как «0012», которые следует интерпретировать как целое число «двенадцать».

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

Каков наилучший способ обработки чисел, которые могут иметь лидирующие нули в Tcl?

В дополнение к этому, что будет означать действительное восьмеричное число в Tcl, если "08" является недействительным?

Ответы [ 7 ]

7 голосов
/ 21 января 2010

Вы захотите прочитать Tcl и октальные числа в вики Tcl. Канонический способ состоит в том, чтобы рассматривать ваш ввод как строку и использовать команду scan, чтобы извлечь числа. Это приводит к этому, да многострочный, 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
}
2 голосов
/ 10 февраля 2014

Это самое чистое решение:

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

Кроме того:

% 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 : Возможно, это то, что вас волнует. Преобразует "09" (даже в виде строки) в десятичное число 9.

Примечание:
1. Если это значение не может быть преобразовано в десятичное значение, то scan вернет пустую строку ({}).
2. Если в команде scan указано имя переменной (например, переменная number в приведенном выше примере), возвращаемое значение указывает status , 0: не удалось проанализировать десятичное число, и 1: успех.

expr : используется здесь для демонстрации того, что expr интерпретирует значение как число и обращается к исходному вопросу. Он вычисляет выражение (например, expr {2*3} возвращает 6).

2 голосов
/ 15 октября 2011

У меня есть все эти программы Tcl / Tk версии 8.1, которые сломались из-за того, что Tcl / Tk 8.5.10 неправильно обрабатывает строковые / числовые преобразования.

Здесь перейдите в Tcl и введите:

 %  expr {01}
 1

(и т. Д.)

 %  expr {06}
 6

 %  expr {07}    
 7

и тогда мы получим 8 ...

 %  expr {08}
 missing operator at "_@_"

выглядит как неверное восьмеричное число

Но становится хуже. Все еще в оболочке Tcl, попробуйте это:

В моей оболочке Tcl8.1:

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

Но в моей новой улучшенной оболочке Tcl8.5 я получаю сообщение об ошибке:

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

Это просто глупо! У меня есть весь этот код, который работает нормально в Tcl7.6 и Tcl8.1, но который начал давать странные, случайные результаты в Tcl8.5. Только когда число 08 случилось с получить или быть использованы! Я часами пытался выяснить проблему. Но оказывается, что это просто противный мешок с кодом , который я использую!

Итак, я выкладываю эту напыщенную речь как предупреждение.
Версия 8.5.10 Tcl / Tk неправильно обрабатывает число восемь. Если ты ожидая вменяемого поведения от ваших утверждений формата, это не произойдет . Ваш код будет развиваться, пока не встретит строку со значением {08}, и интерпретатор Tcl 8.5.10 выдаст ошибку, потому что он будет предполагать что {08} представляет собой особый случай восьмеричное число , независимо от того, что все другие маленькие цифры, которые вы использовали, сработали бы просто отлично!

Одним из возможных решений упомянутой выше проблемы является переход на Tcl 8.1. ракушка. Я подтвердил, что эта версия по крайней мере обрабатывает формат Заявления на номер 08 правильно. Оболочки Tcl 8.5.10 просто нет.

2 голосов
/ 17 декабря 2010
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"

более простое решение:

set x 08
regsub {^[0]} $x {\1} x
puts $x
=>8
1 голос
/ 21 января 2010

Лично я всегда использовал:

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

для дезинфекции $troublesome_number с.

1 голос
/ 21 января 2010

Эта ссылка должна вам помочь

Действительные восьмеричные числа могут содержать только цифры 0-7 и должны начинаться с 0

0 голосов
/ 16 июня 2015
#!/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
...