定型のデータを読み込んで、型変換をしてくれる関数があると便利だ。
fmt
パッケージの Scan
と Fscan
は空白文字で区切られたテキストデータを読み込み、可変長引数で渡されたデータ形式の変数(のポインタ)に変換して格納してくれる。Scan
は標準入力から、Fscan
は io.Reader
から読み込む。
まずは Scan
の例。
package main import ( "fmt" "os" "io" ) func main() { sumi := 0 sumf := 0.0 suma := make([]string, 0) for { var n int var m float64 var s string i, err := fmt.Scan(&n, &m, &s) if i == 3 { sumi += n sumf += m suma = append(suma, s) } else if i == 0 && err == io.EOF { break } else { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } fmt.Println(sumi, sumf, suma) }
^o^ > go run scan.go 1 1.5 1 2 2.3 2 3 3.8 3 6 7.6 [1 2 3]
go run scan.go
コマンドに続く3行が入力で、1行ごとに整数、実数、文字列に変換される。ctrl + c
で入力を終了すると、結果が表示される。最後の行が結果だ。
次は Fscan
の例。io.Reader
から(つまりファイルから)読み込む。
package main import ( "fmt" "os" "io" ) func main() { sumi := 0 sumf := 0.0 suma := make([]string, 0) filename := os.Args[1] file, err := os.Open(filename) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } for { var n int var m float64 var s string i, err := fmt.Fscan(file, &n, &m, &s) if i == 3 { sumi += n sumf += m suma = append(suma, s) } else if i == 0 && err == io.EOF { break } else { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } file.Close() fmt.Println(sumi, sumf, suma) }
^o^ > cat fscan_sample.txt 10 1.234 foo 20 5.678 bar 30 9.876 baz ^o^ > go run fscan.go fscan_sample.txt 60 16.788 [foo bar baz]
Scanf
と Fscanf
は書式付き入力だ。引数で指定された書式で入力を解釈して読み込んでくれる。Scanf
は標準入力から、Fscanf
は io.Reader
(つまりファイル)から読み込む。
Scanf
の例。
package main import ( "fmt" "os" ) func main() { sumi := 0 sumf := 0.0 suma := make([]string, 0) for { var n int var m float64 var s string i, err := fmt.Scanf("%d,%f,%q\n", &n, &m, &s) if i == 3 { sumi += n sumf += m suma = append(suma, s) } else if i == 0 { break } else { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } fmt.Println(sumi, sumf, suma) }
この例では整数、実数、クォートされた文字列をカンマ区切りしたものを入力として期待している。
^o^ > go run scanf.go 10,1.234,"foo" 20,5.678,"bar" 30,9.876,"baz" 60 16.788 [foo bar baz]
最後に Fscanf
。これはファイルから読み込むことのほかは Scanf
と同じだ。
package main import ( "fmt" "os" ) func main() { sumi := 0 sumf := 0.0 suma := make([]string, 0) filename := os.Args[1] file, err := os.Open(filename) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } for { var n int var m float64 var s string i, err := fmt.Fscanf(file, "%d,%f,%q\n", &n, &m, &s) if i == 3 { sumi += n sumf += m suma = append(suma, s) } else if i == 0 { break } else { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } file.Close() fmt.Println(sumi, sumf, suma) }
^o^ > cat fscanf_sample.txt 10,1.234,"foo" 20,5.678,"bar" 30,9.876,"baz" ^o^ > go run fscanf.go fscanf_sample.txt 60 16.788 [foo bar baz]