猿问

reader.ReadLine() 在scanner.Scan() 调用后不前进

下面的代码从此文件中读取其值:


2 3\n

1.0 2.0 3.0\n

-1.0 -2.0 -3.0\n

并且应该打印: [ {1 2 3}, {-1 -2 -3} ]


但相反,我得到了这个:


[{2 [31 2 3]} {0 []}] strconv.ParseFloat: parsing "3.0-1.0": invalid syntax


似乎它们reader.ReadLine()停留在同一个位置。有没有一种更简单的方法来扫描行,然后是每行内的值?


package main


import (

    "bufio"

    "bytes"

    "fmt"

    "os"

    "strconv"

    "strings"

)


type Example struct {

    classLabel int

    attributes []float64

}


func NewExample(classLabel int, attributes []float64) *Example {

    return &Example{classLabel, attributes}

}


func readFile(path string) ([]Example, error) {


    var (

        result       []Example

        err          error

        file         *os.File

        part         []byte

        size         int

        attributeNum int

    )


    if file, err = os.Open(path); err != nil {

        return result, err

    }

    defer file.Close()


    reader := bufio.NewReader(file)

    buffer := bytes.NewBuffer(make([]byte, 0))


    if part, _, err = reader.ReadLine(); err != nil {

        return result, err

    }

    buffer.Write(part)

    newLine := buffer.String()

    fmt.Println("newLine=" + newLine)


    r := strings.NewReader(newLine)

    scanner := bufio.NewScanner(r)

    scanner.Split(bufio.ScanWords)


    if scanner.Scan() {

        size, err = strconv.Atoi(scanner.Text())

        if err != nil {

            return result, err

        }

    }

    fmt.Println("size=" + strconv.Itoa(size))


    if scanner.Scan() {

        attributeNum, err = strconv.Atoi(scanner.Text())

        if err != nil {

            return result, err

        }

    }

    fmt.Println("attributeNum=" + strconv.Itoa(attributeNum))


    result = make([]Example, size)


    var classLabel int

    var attributes []float64


    for k := 0; k < size; k++ {

        if part, _, err = reader.ReadLine(); err != nil {

            return result, err

        }

        buffer.Write(part)

        newLine := buffer.String()

        fmt.Println("newLine=" + newLine)


        r := strings.NewReader(newLine)

        scanner := bufio.NewScanner(r)

        scanner.Split(bufio.ScanWords)


慕标5832272
浏览 151回答 1
1回答

繁星coding

当您在for循环内执行此操作时:buffer.Write(part)newLine := buffer.String()fmt.Println("newLine=" + newLine)下一行被附加到buffer. 也就是说,在循环开始之前,buffercontains 2 3,然后在读取 之后1.0 2.0 3.0,它被附加到缓冲区,因此内容变为2 31.0 2.0 3.0,您将其存储在newLine. 这就是事情开始横向发展的地方。您可能想buffer在阅读每一行之前清除:buffer.Reset()buffer.Write(part)newLine := buffer.String()fmt.Println("newLine=" + newLine)但是你仍然会有更多的问题,在这里:&nbsp; &nbsp; if scanner.Scan() {&nbsp; &nbsp; &nbsp; &nbsp; classLabel, err = strconv.Atoi(scanner.Text())&nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return result, err&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }由于该行包含1.0 2.0 3.0,因此strconf.Atoi将失败。我不明白这个片段的目的,也许你可以删除它(或注释掉)。修复了上述问题后,您仍然会在这一行遇到另一个问题:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; attributes = append(attributes, attribute)由于attributes永远不会重置,因此它会不断增长。也就是说,在第一行之后,它将包含1 2 3,在第二行之后,它将包含1 2 3 -1 -2 -3。您可以通过移动attributes不带外循环的声明来纠正此问题,如下所示:&nbsp; &nbsp; var attributes []float64&nbsp; &nbsp; for i := 0; i < attributeNum; i++ {&nbsp; &nbsp; &nbsp; &nbsp; var attribute float64&nbsp; &nbsp; &nbsp; &nbsp; if scanner.Scan() {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; attribute, err = strconv.ParseFloat(scanner.Text(), 64)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return result, err&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; attributes = append(attributes, attribute)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Println("attribute=" + strconv.FormatFloat(attribute, 'f', -1, 64))&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }
随时随地看视频慕课网APP

相关分类

Go
我要回答