Lapis Lazuli

technical blog for web developer

【Go】Goで競技プログラミング(bufio.Scannerを使って入力を取得)

bufioを使う理由

前回はScanを使って入力の取得を行いましたが、今回はbufioを使う方法を書きたいと思います。
bufioは一言で言うと、一行ずつ入力を取得する関数です。
Scanと似ていますが、こちらのほうが負荷が低いので早く実行出来ます。
少ない桁数ならScanでもいいのですが、大量の文字を読取る場合や、行数が多い場合はこっちのほうが効率的に読み込めます。

では早速使い方を紹介します。

bufio.Scannerの使い方

import (
    "bufio"
)

まずはbufioをインポートして、

scn := bufio.NewScanner(os.Stdin)

NewScannerでScannerを生成し、読み取る準備をします。os.StdinはGoの標準入力です。
特に何もしなくても1行ずつ読み取る形になっています。

これで準備は完了しました。あとは実際に読み取るところまでやってみましょう。

scn.Scan()
scn.Text()

ScanとText。この2つの関数を使います。それぞれ見てみましょう。
まずScanはトークンを読み取る感じです。そしてその後のTextで実際に文字列を読み取ってます。なので、

a := scn.Text()

のように変数にいれてあげれば文字列として使用することが出来ます。
複数行読み取りたい場合は、このScanとTextを繰り返せば読み取れます。for文の中で読み取ってsliceに入れるとかする事が多いですかね。

スペース区切りでScanしたい

競技プログラミングでは、1行の中にスペース区切りで複数の文字が与えられる事が多いです。
それもbufioを使えばいい感じに取得出来ます。
まずSplitでScanの挙動を定義できます。その名の通り、Splitの引数に渡したScannerで区切ってくれます。
更にスペースで区切りたい場合はScanWordsという便利なものが用意されているので、これを渡せばOKです。

scn.Split(bufio.ScanWords)

これであとはScanして〜という上で書いた流れで大丈夫です。

Scanと比べると少し冗長な感じはしますが、関数を定義して用意しておけばすぐに使えますし、単にScan使うよりは応用も効きやすいかなと思います。