使用哪种扫描方式从字符串中读取浮点数?

huangapple go评论84阅读模式
英文:

Which scan to use to read floats from a string?

问题

这似乎几乎正确,但它在换行符上出现问题。
最好的方法是什么?

package main

import (
	"fmt"
	"strings"
)

func main() {
	var z float64
	var a []float64
	// \n给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,则中断,否则只需忽略它。我知道这只是一个hack,但我控制源代码。

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

This seems almost right but it chokes on the newline.
What's the best way to do this?

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

Output:

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

Update:

See the answer from @Atom below. I found another way which is to break if the error is EOF, and otherwise just ignore it. It's just a hack, I know, but I control the source.

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

答案1

得分: 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方法将其取消读取,如果它不是空格或换行符。

英文:

If you are parsing floats only, you can use fmt.Fscan(r io.Reader, a ...interface{}) instead of fmt.Fscanf(r io.Reader, format string, a ...interface{}):

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

The difference between fmt.Fscan and fmt.Fscanf is that in the case of fmt.Fscan newlines count as space. The latter function (with a format string) does not treat newlines as spaces and requires newlines in the input to match newlines in the format string.

The functions with a format string give more control over the form of input, such as when you need to scan %5f or %10s. In this case, if the input contains newlines and it implements the interface io.RuneScanner you can use the method ReadRune to peek the next character and optionally unread it with UnreadRune if it isn't a space or a newline.

答案2

得分: 2

如果您的输入只是一堆由空格分隔的浮点数组成的行,那么从文件中一次读取一行,然后在该行上运行Sscanf可能更容易(假设每行上的浮点数数量是固定的)。但是这里有一个在您的示例中有效的方法---可能有一种方法可以使其更高效。

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)
}
英文:

If your input is just a bunch of lines with floats separated by white space on each line, it might be easier to just read one line at a time from the file, run Sscanf on that line (assuming the number of floats on each line is fixed). But here's something that works in your example---there may be a way to make it more efficient.

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

huangapple
  • 本文由 发表于 2012年3月4日 01:21:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/9548114.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定