Joe*_*oel 1 string hex scanf go
我在读回已序列化为十六进制格式的值时遇到问题。当我格式化一个整数时,下面的代码产生一个 0x14 的值。但是,当我尝试从字符串中读取该值时,得到的结果无效。有人可以帮我弄清楚我做错了什么吗?
我有预先存在的文本文件,我正在用包含这种格式的多行进行解析,因此序列化为不同的格式将不是一个可行的解决方案。我需要使用这种特定格式。
根据 go 文档,这应该有效:https : //golang.org/pkg/fmt/
动词的行为类似于 Printf 的动词。例如,%x 将扫描一个整数作为十六进制数,而 %v 将扫描该值的默认表示格式。Printf 动词 %p 和 %T 以及标志 # 和 + 未实现。对于浮点和复数值,所有有效的格式化动词(%b %e %E %f %F %g %G %x %X 和 %v)都是等价的,并且接受十进制和十六进制表示法(例如:“2.3 e+7", "0x4.5p-8") 和数字分隔下划线(例如:“3.14159_26535_89793”)。
package main
import (
"fmt"
)
func main() {
encode := 20
fmt.Println(fmt.Sprintf("%#x", encode)) // 0x14
var decode int
numRead, err := fmt.Sscanf("0x14", "%#x", &decode)
fmt.Println(decode, numRead, err) // 0 1 bad verb '%#' for integer
numRead, err = fmt.Sscanf("0x14", "%x", &decode)
fmt.Println(decode, numRead, err) // 0 1 nil
}
Run Code Online (Sandbox Code Playgroud)
请注意文档中的这句话:
Printf 动词 %p 和 %T 以及标志 # 和 + 未实现。
所以:
var decode int
numRead, err := fmt.Sscanf("0x14", "0x%x", &decode)
fmt.Println(decode, numRead, err)
numRead, err = fmt.Sscanf("14", "%x", &decode)
fmt.Println(decode, numRead, err)
Run Code Online (Sandbox Code Playgroud)
该%x动词将扫描一个十六进制整数,但不是0x前缀。您可以将该前缀添加到格式字符串中:
var decode int
numRead, err := fmt.Sscanf("0x14", "0x%x", &decode)
fmt.Println(decode, numRead, err)
Run Code Online (Sandbox Code Playgroud)
这将正确地将0x14输入扫描为十进制整数值20(在Go Playground上尝试):
20 1 <nil>
Run Code Online (Sandbox Code Playgroud)
另一种选择是使用%v处理前缀并检测它是十六进制数的动词:
var decode int
numRead, err := fmt.Sscanf("0x14", "%v", &decode)
fmt.Println(decode, numRead, err) // Outputs: 20 <nil>
Run Code Online (Sandbox Code Playgroud)
这输出相同。在Go Playground上试试这个。这具有可以在多个基数中指定输入的灵活性,将从前缀中检测基数(“ %v 将扫描值的默认表示格式”),例如0x对于六0进制,0b对于八进制,对于二进制.
您还可以使用strconv.ParseInt()可以指定 a 的地方base == 0,在这种情况下,“字符串的前缀隐含了基数:基数 2 表示“0b”,基数 8 表示“0”或“0o”,基数 16 表示“0x”,以及基数10 否则”。
decode, err := strconv.ParseInt("0x14", 0, 64)
fmt.Println(decode, err)
Run Code Online (Sandbox Code Playgroud)
在Go Playground上试试这个。