Какое сканирование использовать для чтения чисел с плавающей точкой? - PullRequest
1 голос
/ 03 марта 2012

Это кажется почти правильным, но оно задыхается от новой строки. Какой лучший способ сделать это?

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 ]

5 голосов
/ 03 марта 2012

Если вы анализируете только числа с плавающей точкой, вы можете использовать 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.Fscan и fmt.Fscanf заключается в том, что в случае fmt.Fscan переводы строки считаются пробелом. Последняя функция (со строкой формата) не обрабатывает символы новой строки как пробелы и требует, чтобы символы новой строки во входных данных соответствовали символам новой строки в строке формата.

Функции со строкой форматирования дают больший контроль над формой ввода, например, когда вам нужно сканировать %5f или %10s. В этом случае, если ввод содержит символы новой строки и реализует интерфейс io.RuneScanner, вы можете использовать метод ReadRune, чтобы просмотреть следующий символ и, при необходимости, прочитать его с помощью UnreadRune, если он пробел или перевод строки.

2 голосов
/ 03 марта 2012

Если ваши входные данные представляют собой просто набор строк с поплавками, разделенными пробелами в каждой строке, может быть проще просто прочитать по одной строке за раз из файла, запустите 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)
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...