我的输入数据是十六进制格式的字符串,没有长度限制。我需要单独处理字节。例如,对于“AABBCCDDEEFF”,我想处理 AA,然后是 BB、CC、DD、EE、FF。
使用 Common Lisp,我们可以使用 LOOP:
(loop for (a b) on list do [processing])
在 Racket Scheme 中,我写了这个解决方案:
(define (split-string str)
(let ((bit #t)
(char-1 null)
(char-2 null)
(result '()))
(for ((char str))
(if bit
(begin
(set! bit #f)
(set! char-1 char))
(begin
(set! bit #t)
(set! char-2 char)
(set! result (cons (~a char-1 char-2) result)))))
;; return
(reverse result)))
(split-string "AABBCCDDEEFF")
;; '("AA" "BB" "CC" "DD" "EE" "FF")
我觉得这不是惯用的 Racket 或 Scheme 代码。我写了第二个解决方案:
(define (split-string2 str)
(bytes->list (integer->integer-bytes (string->number str 16) 8 false)))
(split-string2 "AABBCCDDEEFF")
;; '(255 238 221 204 187 170 0 0)
在 Racket Scheme 和更普遍的 Lisp 中执行这种操作的惯用方式是什么?
最佳答案
在 Racket 中有很多方法可以做到这一点(与更普遍的方案相反):你想要的概念是 sequences, streams and generators .
首先是一个从字符中计算十六进制数字的函数(这可能存在于 Racket 中,但我懒得找到它,而且它有效):
(define (char->hex-digit c)
;; Turn a character into a hex digit
(cond [(char<=? #\0 c #\9)
(- (char->integer c) (char->integer #\0))]
[(char<=? #\A c #\F)
(+ 10 (- (char->integer c) (char->integer #\A)))]
[(char<=? #\a c #\f)
(+ 10 (- (char->integer c) (char->integer #\a)))]
[else
(error 'char->hex-digit "~A is not a hex character" c)]))
现在这是一种将十六进制字符串转换为字节列表的简单方法,该方法通过从字符串中创建两个序列来工作,其中一个挑选出每对中的高位数字和另一个低位数字:
(define (hex-string->byte-list hs)
(for/list ([h (in-string hs 0 #f 2)]
[l (in-string hs 1 #f 2)])
(+ (* (char->hex-digit h) 16) (char->hex-digit l))))
显然,根据您使用的 for
的哪个变体,您可以构造不同的结果。
例子:
> (hex-string->byte-list "F00D")
'(240 13)
> (hex-string->byte-list "0102030405060708090a0b0C0D0F")
'(1 2 3 4 5 6 7 8 9 10 11 12 13 15)
> (hex-string->byte-list "01xa")
; char->hex-digit: x is not a hex character [,bt for context]
另一种方法是使用in-slice
:
(define (hex-string->byte-list hs)
(for/list ([hl (in-slice 2 (in-string hs))])
(+ (* (char->hex-digit (first hl)) 16) (char->hex-digit (second hl)))))
还有很多其他方法可以做到这一点,包括创建自己的序列或流类型,因此您可以编写 (for/list ([b (in-hex-stream-bytes ...)] ) b)
.
关于scheme - 在 Racket 方案或其他方案中解码十六进制格式字符串的惯用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58950635/