为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
慕标5832272 2022-01-10 16:24:18
下面的代码从此文件中读取其值:2 3\n1.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 mainimport (    "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)
查看完整描述

1 回答

?
繁星coding

TA贡献1797条经验 获得超4个赞

当您在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)

但是你仍然会有更多的问题,在这里:


    if scanner.Scan() {

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

        if err != nil {

            return result, err

        }

    }

由于该行包含1.0 2.0 3.0,因此strconf.Atoi将失败。我不明白这个片段的目的,也许你可以删除它(或注释掉)。


修复了上述问题后,您仍然会在这一行遇到另一个问题:


          attributes = append(attributes, attribute)

由于attributes永远不会重置,因此它会不断增长。也就是说,在第一行之后,它将包含1 2 3,在第二行之后,它将包含1 2 3 -1 -2 -3。您可以通过移动attributes不带外循环的声明来纠正此问题,如下所示:


    var attributes []float64

    for i := 0; i < attributeNum; i++ {

        var attribute float64

        if scanner.Scan() {

            attribute, err = strconv.ParseFloat(scanner.Text(), 64)

            if err != nil {

                return result, err

            }

            attributes = append(attributes, attribute)

            fmt.Println("attribute=" + strconv.FormatFloat(attribute, 'f', -1, 64))

        }

    }


查看完整回答
反对 回复 2022-01-10
  • 1 回答
  • 0 关注
  • 150 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信