golang 標準入力から空白区切りの数列を読み込む

投稿者: | 2019-09-23

golangで標準入力から空白区切りの数列を読み込み、スライスに格納する。

fmt.Scanln()は使わない。これやfmt.Scanf()は空白を見つけた時点で読み込みをやめてしまう。

Scanlnは固定長なら変数を並べることで、格納できる:

func main() {
    slice := make([]int, 3)
    fmt.Scanln(&slice[0], &slice[1], &slice[2])
    fmt.Println(slice)
}

// もちろんfmt.Scanfでもできる
func main() {
    slice := make([]int, 3)
    fmt.Scanf("%d %d %d", &slice[0], &slice[1], &slice[2])
    fmt.Println(slice)
}

echo "13 2 3" | go run main.goなどで確認できる。変数にスライスを使ってもうまくいかない。

可変長でも読み込みたい

事前に数列の長さがわかっているなら、可変長の場合はforを使って、Scanfを繰り返すのが手っ取り早い。Scanfは、空白や改行の次の文字から読み込んでくれる。

func main() {
    var n int
    // 数列の長さ入力
    fmt.Scanf("%d", &n)

    // 長さに合わせてスライス用意
    A := make([]int, n)
    // 数列の長さの分だけScanfを繰り返す
    for i := 0; i < n; i++ {
        fmt.Scanf("%d", &A[i])
    }
    fmt.Println(A)
}

echo -e "3\n13 2 3" | go run main.goなどで確認できる。

長さが事前にわからないときは、Scannerを利用するしかないと思う。1行分を文字列として読み込み、intに変換する。

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    for scanner.Scan() {
        // 1行ずつ読み込む
        line := scanner.Text()
        chars := strings.Split(line, " ")
        A := make([]int, len(chars))
        for i, ch := range chars {
            num, err := strconv.Atoi(ch)
            if err != nil {
                fmt.Println(err)
                break
            }
            A[i] = num
        }
        fmt.Println(A)
    }
    if err := scanner.Err(); err != nil {
        fmt.Fprintln(os.Stderr, "reading standard input:", err)
    }
}

echo "313 2 3" | go run main.goなどで確認できる。

参考