Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang: Read ints from stdin until EOF while reporting format errors

Tags:

go

nums := make([]int, 0)
{
    var d int
    for {
        _, err := fmt.Scan(&d)
        if err != nil {
            break
        }

        nums = append(nums, d)
    }
}

This works to read in ints from stdin. But if stdin looks like 1 2 3 f4 5, nums will end up being [1 2 3] without reporting any error.

What's the best way of handling this? (Ie, I want EOF from fmt.Scan to silently exit the loop, but all other errors should be reported).

edit: io.EOF was all I needed -- I hadn't found that documented at http://golang.org/pkg/fmt/

nums := make([]int, 0)
{
    var d int
    for {
        _, err := fmt.Scan(&d)
        if err != nil {
            if err != io.EOF {
                log.Fatal(err)
            }
            break
        }

        nums = append(nums, d)
    }
}
like image 383
alecbz Avatar asked Oct 10 '13 18:10

alecbz


1 Answers

You could do it like this - when you get a bad number, read the next space separated thing. Set a flag or on an error or keep a list of the errors to report at the end.

(Playground link)

package main

import (
    "bytes"
    "fmt"
    "io"
)

func main() {
    in := bytes.NewBufferString("1 2 3 f4 5")
    nums := make([]int, 0)
    var d int
    for i := 0; i < 10; i++ {
        _, err := fmt.Fscan(in, &d)
        if err == io.EOF {
            break
        }
        if err != nil {
            var s string
            _, err := fmt.Fscan(in, &s)
            if err != nil {
                break
            }
            fmt.Printf("Skipping bad number: %q\n", s)
        } else {
            nums = append(nums, d)
        }
    }
    fmt.Printf("nums = %v\n", nums)
}

Which prints

Skipping bad number: "f4"
nums = [1 2 3 5]
like image 82
Nick Craig-Wood Avatar answered Jun 12 '23 19:06

Nick Craig-Wood