我正在寻找与scanf()等效的Go。 我尝试使用以下代码:
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
}
答案 0 :(得分:4)
您更新的代码在没有行号的情况下编译起来要容易得多,但它缺少包和import语句。
看着你的代码,我注意到了一些事情。这是我修改后的代码版本。
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
的{{1}}值,这意味着无效输入被转换为零值;我跳过了。
要从矢量复制到新切片并返回切片,您写道:
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
。
答案 1 :(得分:0)
虽然它可以用于其他事情,但扫描仪包用于扫描Go程序文本。 Ints(-123),Chars('c'),Strings(“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()
}
}
答案 2 :(得分:0)
此示例始终一次读取一行,并将整行作为字符串返回。如果你想从中解析出特定的值,你可以。
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
}
答案 3 :(得分:0)
在对我的一个答案的评论中,你说:
从语言规范:“何时 内存被分配来存储一个值, 通过声明或make() 或者new()调用,没有明确的 初始化提供了内存 给出一个默认的初始化“。 那么new()有什么意义呢?
如果我们跑:
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
分配内存以存储指向整数值的指针并将指针初始化为零(nil指针);没有分配内存来存储整数值。我们看到程序输出类似于:
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
答案 4 :(得分:0)
Go的最新版本(2010-05-27)为fmt
包添加了两个功能: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())
}