如何使用sscanf忽略字段(%*被拒绝)

时间:2013-04-05 02:40:45

标签: go

我希望在使用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中使用它,忽略第3个字段:

if c, err := fmt.Sscanf(str, " %s %d %*d %d ", &iface.Name, &iface.BTx, &iface.BytesRx); err != nil || c != 3 {

编译好,但在运行时错误设置为:

bad verb %* for integer

Golang doco没有特别提到%*转换规范,但确实如此,

Package fmt implements formatted I/O with functions analogous to C's printf and scanf.

它并不表示%*未实现,所以......我做错了吗?还是只是被悄悄地省略了? ......但是,为什么要编译?

1 个答案:

答案 0 :(得分:3)

据我所知,此任务中没有这样的动词(如fmt包中调用的格式说明符)。然而,你可以做的是指定一些动词并忽略它的值。但是,这并不是特别友好的。理想情况下这可行:

fmt.Scan(&a, _, &b)

可悲的是,事实并非如此。因此,您的下一个最佳选择是声明变量并忽略变量 你不想要:

var a,b,c int
fmt.Scanf("%d %v %d", &a, &b, &c)
fmt.Println(a,c)

%v将读取空格分隔的标记。根据您正在扫描的内容,您可以快进 流到您需要扫描的位置。见this answer 有关在缓冲区中寻找的详细信息如果您使用的是stdio,或者您不知道输入的长度 你似乎在运气不好。

  

它并不表示%*未实现,所以......我在做什么   错误?还是只是被悄悄地省略了? ......但是,为什么呢   编译?

它编译,因为对于编译器,格式字符串只是一个像任何其他字符串一样的字符串。该字符串的内容在运行时通过fmt包的函数进行评估。某些C编译器可能会检查格式字符串 为了正确,但这是a feature,而不是常态。使用go,go vet命令将尝试警告您参数不匹配的格式字符串错误。

修改

对于需要解析一行整数并且只关心其中一些整数的特殊情况,你 可以将fmt.Scan与整数切片结合使用。以下示例读取3个整数 从stdin中将它们存储在名为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)

这可能比传统的分割/修剪/ 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)
    }
}

上面的示例会将ignore的地址分配给除第一个和第二个之外的所有值 通过覆盖有效地忽略它们。