2013-04-05 136 views
4

我希望在用sscanf处理字符串时忽略特定字段。对于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 { 

编译OK,但在运行时ERR为:

bad verb %* for integer

Golang DOCO没有具体提及%*转换规范,但它说,

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

这并不表明%*不落实,所以...我是不是做错了?或者它刚刚被安静地省略了? ...但是,为什么要编译?

回答

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 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) 

这可能是比传统的拆分/微调/ 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地址分配给所有值除第一而第二个,因此 通过覆盖有效地忽略它们。

+0

感谢您的回复。 我还没有完全遵循。要清楚说明我的意图 - 我希望放弃输入的第三个字段。 即,禁止转换为参数。 您的代码行似乎提供了将该字段转换为参数的宽度精度。 – maxfacta 2013-04-05 03:52:37

+0

哦,似乎我误解了你的问题,我会更新我的答案。 – nemo 2013-04-05 04:01:12

+0

干杯......“不能做”不是我想听到的答案,但它仍然是一个答案! 我在这里的例子被修剪以便于查看 - 我实际上是解析/ proc/net/dev的输出,并且只对字段1,2和10感兴趣。我不打算声明7个不需要的int ...我有一个使用字符串的多线解决方案。 Split,Fields,Trim和strconv.Atoi - 在C中,我会使用单个sscanf。 – maxfacta 2013-04-05 04:54:28