質問
私は)(scanf関数の囲碁同等を探しています。 私は、次のコードで試してみました。
1 package main
2
3 import (
4 "scanner"
5 "os"
6 "fmt"
7 )
8
9 func main() {
10 var s scanner.Scanner
11 s.Init(os.Stdin)
12 s.Mode = scanner.ScanInts
13 tok := s.Scan()
14 for tok != scanner.EOF {
15 fmt.Printf("%d ", tok)
16 tok = s.Scan()
17 }
18 fmt.Println()
19 }
私は、整数のラインとテキストからの入力でそれを実行します。 しかし、それは常に出力-3 -3 ...
そして、どのように文字列と、いくつかの整数で構成されるラインをスキャンするには? 新しいデータ型に遭遇するたびにモードを変更する?
パッケージのドキュメント:
パッケージスキャナ
UTF-8用の汎用スキャナ エンコードされたテキストます。
しかし、スキャナが一般的な使用のためではないと思われます。
更新されたコード:
func main() {
n := scanf()
fmt.Println(n)
fmt.Println(len(n))
}
func scanf() []int {
nums := new(vector.IntVector)
reader := bufio.NewReader(os.Stdin)
str, err := reader.ReadString('\n')
for err != os.EOF {
fields := strings.Fields(str)
for _, f := range fields {
i, _ := strconv.Atoi(f)
nums.Push(i)
}
str, err = reader.ReadString('\n')
}
r := make([]int, nums.Len())
for i := 0; i < nums.Len(); i++ {
r[i] = nums.At(i)
}
return r
}
改良ます:
package main
import (
"bufio"
"os"
"io"
"fmt"
"strings"
"strconv"
"container/vector"
)
func main() {
n := fscanf(os.Stdin)
fmt.Println(len(n), n)
}
func fscanf(in io.Reader) []int {
var nums vector.IntVector
reader := bufio.NewReader(in)
str, err := reader.ReadString('\n')
for err != os.EOF {
fields := strings.Fields(str)
for _, f := range fields {
if i, err := strconv.Atoi(f); err == nil {
nums.Push(i)
}
}
str, err = reader.ReadString('\n')
}
return nums
}
解決
あなたの更新されたコードは、行番号なしでコンパイルする方がはるかに簡単だったが、それは、パッケージおよびインポート文が欠落していました。
あなたのコードを見て、私はいくつかのことに気づきました。ここにあなたのコードの私の改訂版だ。
package main
import (
"bufio"
"fmt"
"io"
"os"
"strconv"
"strings"
"container/vector"
)
func main() {
n := scanf(os.Stdin)
fmt.Println()
fmt.Println(len(n), n)
}
func scanf(in io.Reader) []int {
var nums vector.IntVector
rd := bufio.NewReader(os.Stdin)
str, err := rd.ReadString('\n')
for err != os.EOF {
fields := strings.Fields(str)
for _, f := range fields {
if i, err := strconv.Atoi(f); err == nil {
nums.Push(i)
}
}
str, err = rd.ReadString('\n')
}
return nums
}
私はscanf()
のための任意の入力ファイルを使用する場合があります、だけでなくStdin
。 scanf()
は、パラメータとしてio.Reader
を取ります。
あなたは書きました:nums := new(vector.IntVector)
、type IntVector []int
。これはnums
名前整数スライスの参照を割り当て、ゼロに初期化し、その後new()
関数は、整数スライスの参照を割り当て、ゼロに初期化し、その後nums
に割り当てます。私が書いた:var nums vector.IntVector
を、単にnums
名前整数スライスの参照を割り当て、それをゼロに初期化することにより、冗長性を回避する
あなたはゼロ値に変換された無効な入力を意味err
、用strconv.Atoi()
値をチェックしませんでした。私はそれをスキップします。
新しいスライスにベクターからコピーして、スライスを返すには、あなたが書いた:
r := make([]int, nums.Len())
for i := 0; i < nums.Len(); i++ {
r[i] = nums.At(i)
}
return r
まず、私は単純に置き換えられている同等の、IntVector.Data()
方法で:return nums.Data()
。その後、私は実際にそのtype IntVector []int
を利用したと割り当てを回避し、それによって置換することによりコピーします。return nums
他のヒント
、スキャナパッケージは、囲碁プログラムテキストをスキャンするように設計されています。 INTS(-123)、文字数( 'C')、文字列( "STR")などのGo言語トークンタイプです。
package main
import (
"fmt"
"os"
"scanner"
"strconv"
)
func main() {
var s scanner.Scanner
s.Init(os.Stdin)
s.Error = func(s *scanner.Scanner, msg string) { fmt.Println("scan error", msg) }
s.Mode = scanner.ScanInts | scanner.ScanStrings | scanner.ScanRawStrings
for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
txt := s.TokenText()
fmt.Print("token:", tok, "text:", txt)
switch tok {
case scanner.Int:
si, err := strconv.Atoi64(txt)
if err == nil {
fmt.Print(" integer: ", si)
}
case scanner.String, scanner.RawString:
fmt.Print(" string: ", txt)
default:
if tok >= 0 {
fmt.Print(" unicode: ", "rune = ", tok)
} else {
fmt.Print(" ERROR")
}
}
fmt.Println()
}
}
この例では、常に時のラインを読み込み、文字列として行全体を返します。あなたはそれから特定の値を解析したい場合でします。
package main
import (
"fmt"
"bufio"
"os"
"strings"
)
func main() {
value := Input("Please enter a value: ")
trimmed := strings.TrimSpace(value)
fmt.Printf("Hello %s!\n", trimmed)
}
func Input(str string) string {
print(str)
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
return input
}
私の答えの一つにコメントでは、あなたが言っます:
言語仕様から:「とき メモリは、値を格納するために割り当てられ、 宣言を通して、または()のいずれかにします または新しい()の呼び出し、および明示的な 初期化は、メモリが設けられています。 「デフォルトの初期化を与えています。 その後)(新規のポイントは何ですか?
私たちが実行している場合:
package main
import ("fmt")
func main() {
var i int
var j *int
fmt.Println("i (a value) = ", i, "; j (a pointer) = ", j)
j = new(int)
fmt.Println("i (a value) = ", i, "; j (a pointer) = ", j, "; *j (a value) = ", *j)
}
宣言var i int
は、整数値を格納するメモリを割り当て、値をゼロに初期化します。宣言var j *int
は、整数値へのポインタを格納するためにメモリを割り当て、ゼロ(NULLポインタ)へのポインタを初期化します。いかなるメモリは、整数値を格納するために割り当てられません。
i (a value) = 0 ; j (a pointer) = <nil>
組み込み関数new
は型T
を取り、型*T
の値を返します。メモリはゼロ値に初期化されます。ステートメントj = new(int)
は、整数値を格納するメモリを割り当て、値をゼロに初期化し、それがjで、この整数値へのポインタを格納します。
i (a value) = 0 ; j (a pointer) = 0x7fcf913a90f0 ; *j (a value) = 0
ゴーの最新のリリース(2010-05-27)はfmt
パッケージに二つの機能を追加しました:<のhref = "http://golang.org/pkg/fmt/#Scan" のrel = "nofollowをnoreferrer" > Scan()
と Scanln()
に。彼らは、任意のパターン文字列を取ることはありません。 Cのように、代わりに、引数の型をチェックします。
package main
import (
"fmt"
"os"
"container/vector"
)
func main() {
numbers := new(vector.IntVector)
var number int
n, err := fmt.Scan(os.Stdin, &number)
for n == 1 && err == nil {
numbers.Push(number)
n, err = fmt.Scan(os.Stdin, &number)
}
fmt.Printf("%v\n", numbers.Data())
}