哪个扫描用于从字符串中读取浮点数?

时间:2012-03-03 17:21:56

标签: go

这看起来几乎是正确的,但它在换行线上窒息。 最好的方法是什么?

package main

import (
    "fmt"
    "strings"
)

func main() {
    var z float64
    var a []float64
    // \n gives an error for Fscanf
    s := "3.25 -12.6 33.7 \n 3.47"
    in := strings.NewReader(s)
    for {
        n, err := fmt.Fscanf(in, "%f", &z)
        fmt.Println("n", n)
        if err != nil {
            break
        }
        a = append(a, z)
    }
    fmt.Println(a)
}

输出:

n 1
n 1
n 1
n 0
[3.25 -12.6 33.7]

更新

请参阅下面@Atom的答案。我找到了另一种方法,如果错误是EOF就会中断,否则只是忽略它。我知道,这只是一个黑客,但我控制了源。

    _, err := fmt.Fscanf(in, "%f", &z)
    if err == os.EOF { break }
    if err != nil { continue }

2 个答案:

答案 0 :(得分:5)

如果您只解析花车,可以使用fmt.Fscan(r io.Reader, a ...interface{})代替fmt.Fscanf(r io.Reader, format string, a ...interface{})

var z float64
...
n, err := fmt.Fscan(in, &z)

fmt.Fscanfmt.Fscanf之间的区别在于fmt.Fscan新行计为空格。后一个函数(带有格式字符串)不会将换行视为空格,并且需要输入中的换行符以匹配格式字符串中的换行符。

带有格式字符串的函数可以更好地控制输入形式,例如当您需要扫描%5f%10s时。在这种情况下,如果输入包含换行符并且它实现了接口io.RuneScanner,则可以使用方法ReadRune查看下一个字符,如果不是,则可以选择将其与UnreadRune一起读取空格或换行符。

答案 1 :(得分:2)

如果你的输入只是一串行,每行都有一个由空格分隔的浮点数,那么从文件中一次读取一行可能更容易,在该行上运行Sscanf(假设浮点数为on)每条线都是固定的)。但是这里有一些适用于你的例子 - 可能有一种方法可以提高效率。

package main

import (
    "fmt"
    "strings"
)

func main() {
    var z float64
    var a []float64
    // \n gives an error for Fscanf
    s := "3.25 -12.6 33.7 \n 3.47"
    for _, line := range strings.Split(s, "\n") {
        in := strings.NewReader(line)
        for {
            n, err := fmt.Fscanf(in, "%f", &z)
            fmt.Println("n", n)
            if err != nil {
                fmt.Printf("ERROR: %v\n", err)
                break
            }
            a = append(a, z)
        }
    }
    fmt.Println(a)
}