二进制扫描格式TCL中的8位字符码(c)



我对类型"c"的二进制扫描感到困惑,因为据说"c"指的是8位字符代码。我有以下代码要维护

   puts ""
     set b_val2 "0000021002020a042845245d868a8d9900081b000315aef0010c105d39b4f7c9a083a65e7d000306140508063024"
    set msg2 [binary format H* $b_val2]
    set msg2 [string range $msg2 1 end]  

   while {[binary scan $msg2 cc id2 len2] == 2} {
     puts ""
     #puts "SECOND ID is $id2 and SECOND LENGTH is $len2"
     set id2 [expr {$id2 & 0xff}]        
     set len2 [expr {$len2 & 0xff}]
     set val2 [string range $msg2 2 [expr {1+$len2}]]
     switch -exact -- $id2 {
                0 {
                  puts ""
                   if {$val2 == "x10x04"} {   
                     puts "val is found for 04 "
                   } elseif {$val2 == "x10x02"} {
                     puts "ID is found for 02! CORRECT "
                   } else {
                     puts "not supported"
                   }
                }
     }
   }

的想法是从给定的十六进制中取值"10 02"。这段代码工作得很好,直到我将b_val的给定输入更改为

00021002020903e845245ca0d29858081c00031ef7c001106d3931e7d3414e6d3df26831030614051608045c22

对于第一个给定的十六进制代码"len"是"3",它正确地解析了二进制,但对于第二个十六进制输入,"len2"是16,因此解析了错误的字节。

我读到二进制扫描cc将返回类型为8位字符代码的两个变量,但上述失败对我来说根本没有任何意义,因为我所理解的是,之前的作者试图以上述代码为目标(特别是set val2,它试图取范围),以及为什么它失败了第二个输入

对于初学者:您的代码片段从未在while循环中修改msg2,因此scan每次循环返回相同的结果,并且您有一个无限循环。我扔了一个break只循环一次,但这让我不确定我是否有正确的行为。

也就是说,明显的问题是,当您从原始消息转到替换消息时,您丢失了第一个字节(值为00)。从第2行开始(忽略空行),其中设置

set b_val2 "0000021002020a..."

让我们手工解析。第3行将其转换为十六进制,第4行删除第一个字节,以便我们从十六进制值为x00 x02 x10 x02 x02 x0a ...的字节字符串开始。第5行的binary scan将id2设置为第一个字节,将len2设置为第二个字节;第10行将val2设置为值为x10 x02的字符串,它符合您的标准。成功。

现在重新解析输入

set b_val2 "00021002020903e84..."
从第二行输入

。同样,第一个字节在第4行被丢弃,只剩下x02 x10 x02 x02 x09 x03...。第5行将id2设置为2,将len2设置为x10,即十进制16,如您所见。这意味着val2与您期望的非常不同,但这是由于您从输入中删除了一个字节。

字节解析器对字符串的初始位置非常敏感。一旦你搞砸了,你最好有一个健壮的再同步机制,否则一切都完了。这是有线协议困难的一个主要原因。:)

最新更新