douweiduo7526 2013-04-05 02:40
浏览 363
已采纳

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

I wish to ignore a particular field whilst processing a string with sscanf.

Man page for sscanf says

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

Attempting to use this in Golang, to ignore the 3rd field:

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

compiles OK, but at runtime err is set to:

bad verb %* for integer

Golang doco doesn't specifically mention the %* conversion specification, but it does say,

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

It doesn't indicate that %* is not implemented, so... Am I doing it wrong? Or has it just been quietly omitted? ...but then, why does it compile?

  • 写回答

1条回答 默认 最新

  • dongwenhui8900 2013-04-05 02:57
    关注

    To the best of my knowledge there is no such verb (as the format specifiers are called in the fmt package) for this task. What you can do however, is specifying some verb and ignoring its value. This is not particularly memory friendly, though. Ideally this would work:

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

    Sadly, it doesn't. So your next best option would be to declare the variables and ignore the one you don't want:

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

    %v would read a space separated token. Depending on what you're scanning on, you may fast forward the stream to the position you need to scan on. See this answer for details on seeking in buffers. If you're using stdio or you don't know which length your input may have, you seem to be out of luck here.

    It doesn't indicate that %* is not implemented, so... Am I doing it wrong? Or has it just been quietly omitted? ...but then, why does it compile?

    It compiles because for the compiler a format string is just a string like any other. The content of that string is evaluated at run time by functions of the fmt package. Some C compilers may check format strings for correctness, but this is a feature, not the norm. With go, the go vet command will try to warn you about format string errors with mismatched arguments.

    Edit:

    For the special case of needing to parse a row of integers and just caring for some of them, you can use fmt.Scan in combination with a slice of integers. The following example reads 3 integers from stdin and stores them in the slice named 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)
    

    This is probably shorter than the conventional split/trim/strconv chain. It makes a slice of pointers which each points to a value in vals. fmt.Scan then fills these pointers. With this you can even ignore most of the values by assigning the same pointer over and over for the values you don't want:

    ignored := 0
    
    for i, _ := range ints {
        if(i == 0 || i == 2) {
            ints[i] = interface{}(&vals[i])
        } else {
            ints[i] = interface{}(&ignored)
        }
    }
    

    The example above would assign the address of ignore to all values except the first and the second, thus effectively ignoring them by overwriting.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 请问这个是什么意思?
  • ¥15 STM32驱动继电器
  • ¥15 Windows server update services
  • ¥15 关于#c语言#的问题:我现在在做一个墨水屏设计,2.9英寸的小屏怎么换4.2英寸大屏
  • ¥15 模糊pid与pid仿真结果几乎一样
  • ¥15 java的GUI的运用
  • ¥15 我想付费需要AKM公司DSP开发资料及相关开发。
  • ¥15 怎么配置广告联盟瀑布流
  • ¥15 Rstudio 保存代码闪退
  • ¥20 win系统的PYQT程序生成的数据如何放入云服务器阿里云window版?