Visual Works smalltalk, как преобразовать значения Ascii в символы
Используя visualworks, в светской беседе я получаю строку типа "31323334" из сетевого подключения.
Мне нужна строка, которая читает "1234", поэтому мне нужен способ извлечения двух символов за раз, преобразования их в то, что они представляют в ascii, а затем построения их строки...
Есть ли способ сделать это?
РЕДАКТИРОВАТЬ (7/24): по какой-то причине многие из вас предполагают, что я буду работать только с числами и мог бы просто обрезать 3 или читать любой другой символ. Это не так, примеры считываемых строк могут включать любые клавиши на стандартной клавиатуре США (az, AZ,0-9, знаки препинания / аннотации, такие как {}*&^%$...)
3 ответа
Следуя тому, что Макс начал предлагать:
x := '31323334'.
in := ReadStream on: x.
out := WriteStream on: String new.
[ in atEnd ] whileFalse: [ out nextPut: (in next digitValue * 16 + (in next digitValue)) asCharacter ].
newX := out contents.
newX
будет иметь результат '1234'
, Или, если вы начнете с:
x := '454647'
Вы получите результат 'EFG'
,
Обратите внимание, что digitValue
может распознавать только шестнадцатеричные цифры в верхнем регистре, поэтому asUppercase
может потребоваться в строке перед обработкой.
Обычно есть #fold:
или же #reduce:
метод, который позволит вам сделать это. В Pharo также есть сообщение #allPairsDo:
а также #groupsOf:atATimeCollect:
, Используя один из этих методов, вы можете сделать:
| collectionOfBytes |
collectionOfBytes := '9798'
groupsOf: 2
atATimeCollect: [ :group |
(group first digitValue * 10) + (group second digitValue) ].
collectionOfBytes asByteArray asString "--> 'ab'"
#digitValue
сообщение в Pharo просто возвращает значение цифры для числовых символов.
Если вы получаете данные в потоке, вы можете заменить #groupsOf:atATime:
с петлей (result
может быть любой коллекцией, которую вы затем преобразуете в строку, как указано выше):
...
[ stream atEnd ] whileFalse: [
result add: (stream next digitValue * 10) + (stream next digitValue) ]
...
В Smalltalk/X есть метод, который называетсяfromHexBytes:
"который понимает класс ByteArray. Я не уверен, но думаю, что нечто подобное существует в других диалектах ST.
Если есть, вы можете решить это с помощью:
(ByteArray fromHexString:'68656C6C6F31323334') asString
и наоборот будет:
'hello1234' asByteArray hexPrintString
Другое возможное решение - прочитать строку в виде шестнадцатеричного числа, извлечь digitBytes (который должен дать вам байтовый массив), а затем преобразовать его в строку. Т.е.
(Integer readFrom:'68656C6C6F31323334' radix:16)
digitBytes asString
Одна из проблем заключается в том, что я не уверен в том, какой порядок байтов вы получите digitBytes (LSB или MSB), и определен ли он как одинаковый для разных архитектур или преобразованный во время загрузки изображения для использования собственного порядка. Таким образом, может потребоваться перевернуть строку в конце (чтобы быть переносной, может даже потребоваться перевернуть ее условно, в зависимости от порядкового номера системы.
Я не могу проверить это на VisualWorks, но я предполагаю, что он тоже должен работать там.