kurumi-bioの雑記帳

プログラミング、パソコン、ペット、 犬、お出かけ

初心者のGo言語 その12 <fmt.SscanとSscanf、Sscanln>

こんにちは、kurumi-bioです。15回目のブログです。
前回に引き続きGo言語について発信します。

環境

OSバージョン:Windows11 Home 22H2
Go言語のバージョン:go version go1.19.4 windows/amd64

fmt.Sscan

func Sscan(str string, a ...any) (n int, err error)

Sscan は引数文字列をスキャンし、連続するスペース区切りの値を連続する引数に格納します。改行はスペースとしてカウントされます。正常にスキャンされたアイテムの数を返します。それが引数の数よりも少ない場合、err はその理由を報告します。

<サンプルコード>SscanSample.go

package main

import "fmt"
import "os"

func main() {
    var s string
    var i int
    var b bool

    n, e := fmt.Sscan("123 abc 0", &i, &s, &b)
    if e != nil {
        fmt.Fprintf(os.Stderr, "Sscan Error: %v / n=%d\n", e, n)
    } else {
        fmt.Printf("n= %d / i=[%d] / s=[%s] / b=[%v]\n", n, i, s, b)
    }
}

数値(123)文字列(abc)真偽値(0)を半角空白で区切った文字列を
int型、string型、bool型に格納するサンプルプログラムです。

<実行結果>

各変数に値が入っていることが確認できました。

<サンプルコード>SscanSampleK1.go

package main

import "fmt"
import "os"

func main() {
    var s string
    var i, i2 int
    var b bool

    n, e := fmt.Sscan("123 abc 0", &i, &i2, &b)
    if e != nil {
        fmt.Fprintf(os.Stderr, "Sscan Error: %v / n=%d\n", e, n)
    } else {
        fmt.Printf("n= %d / i=[%d] / s=[%s] / b=[%v]\n", n, i, s, b)
    }
}

試しに二つ目の引数をint型にしてみました。

<実行結果>

int型の変数に文字列を代入したので、expected integerのエラーが発生しました。
また、一つ目の引数は正常に代入できているので、nに1が代入されています。

<サンプルコード>SscanSampleK2.go

package main

import "fmt"
import "os"

func main() {
    var s string
    var i int
    var b bool

    n, e := fmt.Sscan("123 abc", &i, &s, &b)
    if e != nil {
        fmt.Fprintf(os.Stderr, "Sscan Error: %v / n=%d\n", e, n)
    } else {
        fmt.Printf("n= %d / i=[%d] / s=[%s] / b=[%v]\n", n, i, s, b)
    }
}

では、分割数よりも引数の方が多い場合を試してみます。

<実行結果>

今度は、'EOF'というエラーが発生しました。
EOFは、もう読み込むものが無い場合に発生します。
EOF is the error returned by Read when no more input is available.

fmt.Sscanf

func Sscanf(str string, format string, a ...any) (n int, err error)

Sscanf は、引数文字列をスキャンし、スペースで区切られた連続する値を、形式によって決定される連続する引数に格納します。正常に解析されたアイテムの数を返します。入力の改行は、形式の改行と一致する必要があります。

<サンプルコード>SscanfSample.go

package main

import "fmt"
import "os"

func main() {
    var s string
    var i int

    n, e := fmt.Sscanf("Kim is 22 years old", "%s is %d years old", &s, &i)
    if e != nil {
        fmt.Fprintf(os.Stderr, "Sscanf Error: %v / n=%d\n", e, n)
    } else {
        fmt.Printf("n= %d / s=[%s] / i=[%d]\n", n, s, i)
    }
}

<実行結果>

各変数に値が入っていることが確認できました。

<サンプルコード>SscanfSampleK1.go

package main

import "fmt"
import "os"

func main() {
    var s string
    var i int

    n, e := fmt.Sscanf("Kim ii 22 years old", "%s is %d years old", &s, &i)
    if e != nil {
        fmt.Fprintf(os.Stderr, "Sscanf Error: %v / n=%d\n", e, n)
    } else {
        fmt.Printf("n= %d / s=[%s] / i=[%d]\n", n, s, i)
    }
}

書式指定以外の部分で、一つ目と二つ目の引数が異なった場合にどうなるか試してみました。

<実行結果>

input does not match formatのエラーが発生しました。
変数に代入しない文字列(書式指定外の文字列)は、同じ文字にする必要がありそうです。

fmt.Sscanln

func Sscanln(str string, a ...any) (n int, err error)

Sscanln は Sscan に似ていますが、改行でスキャンを停止し、最後の項目の後には改行または EOF が必要です。

<サンプルコード>SscanlnSample.go

package main

import "fmt"
import "os"

func main() {
    var s string
    var i int

    n, e := fmt.Sscanln("123 abc\n 123", &i, &s)
    if e != nil {
        fmt.Fprintf(os.Stderr, "Sscanln Error: %v / n=%d\n", e, n)
    } else {
        fmt.Printf("n= %d i1=[%d] / s=[%s]\n", n, i, s)
    }
}

<実行結果>

"abc"の後に改行(\n)まで読込んで、変数iと変数sに値が入っていることが確認できました。