我希望在使用 sscanf 处理字符串时忽略特定字段。
sscanf 的手册页说
An optional '*' assignment-suppression character: scanf() reads input as directed by the conversion specification, but discards the input. No corresponding pointer argument is required, and this specification is not included in the count of successful assignments returned by scanf().
尝试在 Golang 中使用它,忽略第三个字段:
if c, err := fmt.Sscanf(str, " %s %d %*d %d ", &iface.Name, &iface.BTx, &iface.BytesRx); err != nil || c != 3 {
Run Code Online (Sandbox Code Playgroud)
编译正常,但在运行时 err 设置为:
bad verb %* for integer
Golang doco 没有特别提到 %* 转换规范,但它确实说,
Package fmt implements formatted I/O with functions analogous to C's printf and scanf.
这并不表示 %* 没有实现,所以......我做错了吗?或者它只是被悄悄地省略了?...但是,它为什么要编译?
据我所知,没有这样的动词(因为格式说明符在fmt包中被称为)用于此任务。然而,您可以做的是指定一些动词并忽略它的值。不过,这对内存来说并不是特别友好。理想情况下,这会起作用:
fmt.Scan(&a, _, &b)
Run Code Online (Sandbox Code Playgroud)
遗憾的是,事实并非如此。因此,您的下一个最佳选择是声明变量并忽略您不想要的变量:
var a,b,c int
fmt.Scanf("%d %v %d", &a, &b, &c)
fmt.Println(a,c)
Run Code Online (Sandbox Code Playgroud)
%v将读取空格分隔的标记。根据您要扫描的内容,您可以将流快进到需要扫描的位置。
有关在缓冲区中查找的详细信息,请参阅此答案。如果您使用的是 stdio 或者您不知道输入的长度,那么您似乎不太走运。
它并不表明 %* 没有实现,所以......我做错了吗?或者它只是被悄悄地忽略了?...但是,为什么它会编译呢?
它可以编译,因为对于编译器来说,格式字符串只是一个与其他字符串一样的字符串。该字符串的内容在运行时由fmt包的函数进行评估。一些 C 编译器可能会检查格式字符串的正确性,但这是一个功能,而不是规范。使用 go,go vet命令将尝试警告您有关参数不匹配的格式字符串错误。
编辑:
对于需要解析一行整数并只关心其中一些整数的特殊情况,您可以fmt.Scan与整数切片结合使用。以下示例从 stdin 读取 3 个整数并将它们存储在名为 的切片中vals:
ints := make([]interface{}, 3)
vals := make([]int, len(ints))
for i, _ := range ints {
ints[i] = interface{}(&vals[i])
}
fmt.Scan(ints...)
fmt.Println(vals)
Run Code Online (Sandbox Code Playgroud)
这可能比传统的 split/trim/strconv 链更短。它创建一个指针切片,每个指针都指向 中的一个值vals。fmt.Scan然后填充这些指针。有了这个,您甚至可以通过一遍又一遍地为您不需要的值分配相同的指针来忽略大多数值:
ignored := 0
for i, _ := range ints {
if(i == 0 || i == 2) {
ints[i] = interface{}(&vals[i])
} else {
ints[i] = interface{}(&ignored)
}
}
Run Code Online (Sandbox Code Playgroud)
上面的示例会将 的地址分配ignore给除第一个和第二个之外的所有值,从而通过覆盖有效地忽略它们。
| 归档时间: |
|
| 查看次数: |
5667 次 |
| 最近记录: |