Обработка чисел с ведущими нулями в Tcl

У меня проблемы с 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 ответов


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

у меня есть все эти программы 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 shell, попробуйте следующее:

в моем Tcl8.1 оболочка:

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

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

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

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

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

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


set $clean_number [regsub {^0*(.+)} $troublesome_number {}] this doesnt work 
set clean_number "" 
set $troublesome_number 08
% set $clean_number [regsub {^0*(.+)} $troublesome_number {}]
wrong # args: should be "regsub ?switches? exp string subSpec varName"

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

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

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

% 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

сканирование : это, вероятно, то, о чем вы заботитесь. преобразование "09" (даже в виде строки) в десятичное число 9.

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

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


этой ссылке должно помочь вам

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


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

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

санировать $troublesome_numbers.


#!/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 {} num
puts $num