fmt.Sscanf 无法正确读取十六进制
fmt.Sscanf doesn't properly read hexadecimal
我在读回已序列化为十六进制格式的值时遇到问题。当我格式化一个整数时,下面的代码产生一个值 0x14。但是,当我尝试从字符串中读回该值时,我得到了无效结果。谁能帮我弄清楚我做错了什么?
我有预先存在的文本文件,我正在用包含这种格式的多行进行解析,因此序列化为不同的格式将不是一个可行的解决方案。我需要使用这种特定格式。
根据 go 文档,这应该有效:https://golang.org/pkg/fmt/
The verbs behave analogously to those of Printf. For example, %x will scan an integer as a hexadecimal number, and %v will scan the default representation format for the value. The Printf verbs %p and %T and the flags # and + are not implemented. For floating-point and complex values, all valid formatting verbs (%b %e %E %f %F %g %G %x %X and %v) are equivalent and accept both decimal and hexadecimal notation (for example: "2.3e+7", "0x4.5p-8") and digit-separating underscores (for example: "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
}
注意文档中的这句话:
The Printf verbs %p and %T and the flags # and + are not implemented.
所以:
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)
%x
动词将扫描十六进制整数,但不扫描 0x
前缀。您可以将该前缀添加到格式字符串中:
var decode int
numRead, err := fmt.Sscanf("0x14", "0x%x", &decode)
fmt.Println(decode, numRead, err)
这将正确扫描 0x14
输入为 20
的十进制整数值(在 Go Playground 上尝试):
20 1 <nil>
另一种选择是使用 %v
动词来处理前缀并检测它是一个十六进制数:
var decode int
numRead, err := fmt.Sscanf("0x14", "%v", &decode)
fmt.Println(decode, numRead, err) // Outputs: 20 <nil>
这输出相同。在 Go Playground 上试试这个。这具有灵活性,可以在多个碱基中指定输入,碱基将从前缀中检测(“%v 将扫描值的默认表示格式”),例如 0x
表示六进制,0
表示八进制,0b
表示二进制。
您也可以使用 strconv.ParseInt()
,其中您可以指定 base == 0
,在这种情况下 "the base is implied by the string's prefix: base 2 for "0b",以 8 为基数表示“0”或“0o” ","0x" 以 16 为底,否则以 10 为底"。
decode, err := strconv.ParseInt("0x14", 0, 64)
fmt.Println(decode, err)
在 Go Playground 上试试这个。
我在读回已序列化为十六进制格式的值时遇到问题。当我格式化一个整数时,下面的代码产生一个值 0x14。但是,当我尝试从字符串中读回该值时,我得到了无效结果。谁能帮我弄清楚我做错了什么?
我有预先存在的文本文件,我正在用包含这种格式的多行进行解析,因此序列化为不同的格式将不是一个可行的解决方案。我需要使用这种特定格式。
根据 go 文档,这应该有效:https://golang.org/pkg/fmt/
The verbs behave analogously to those of Printf. For example, %x will scan an integer as a hexadecimal number, and %v will scan the default representation format for the value. The Printf verbs %p and %T and the flags # and + are not implemented. For floating-point and complex values, all valid formatting verbs (%b %e %E %f %F %g %G %x %X and %v) are equivalent and accept both decimal and hexadecimal notation (for example: "2.3e+7", "0x4.5p-8") and digit-separating underscores (for example: "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
}
注意文档中的这句话:
The Printf verbs %p and %T and the flags # and + are not implemented.
所以:
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)
%x
动词将扫描十六进制整数,但不扫描 0x
前缀。您可以将该前缀添加到格式字符串中:
var decode int
numRead, err := fmt.Sscanf("0x14", "0x%x", &decode)
fmt.Println(decode, numRead, err)
这将正确扫描 0x14
输入为 20
的十进制整数值(在 Go Playground 上尝试):
20 1 <nil>
另一种选择是使用 %v
动词来处理前缀并检测它是一个十六进制数:
var decode int
numRead, err := fmt.Sscanf("0x14", "%v", &decode)
fmt.Println(decode, numRead, err) // Outputs: 20 <nil>
这输出相同。在 Go Playground 上试试这个。这具有灵活性,可以在多个碱基中指定输入,碱基将从前缀中检测(“%v 将扫描值的默认表示格式”),例如 0x
表示六进制,0
表示八进制,0b
表示二进制。
您也可以使用 strconv.ParseInt()
,其中您可以指定 base == 0
,在这种情况下 "the base is implied by the string's prefix: base 2 for "0b",以 8 为基数表示“0”或“0o” ","0x" 以 16 为底,否则以 10 为底"。
decode, err := strconv.ParseInt("0x14", 0, 64)
fmt.Println(decode, err)
在 Go Playground 上试试这个。