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, но я предполагаю, что он тоже должен работать там.

Другие вопросы по тегам