英文:
fmt.Scanln expected newline error
问题
我正在尝试学习Go语言,但在这个问题上遇到了困难:http://ideone.com/hbCamr 或 http://ideone.com/OvRw7t
package main
import "fmt"
func main(){
var i int
var f float64
var s string
_, err := fmt.Scan(&i)
if err == nil {
fmt.Println("读取到一个整数:", i)
} else {
fmt.Println("错误:", err)
}
_, err = fmt.Scan(&f)
if err == nil {
fmt.Println("读取到一个浮点数:", f)
} else {
fmt.Println("错误:", err)
}
_, err = fmt.Scan(&s)
if err == nil {
fmt.Println("读取到一个字符串:", s)
} else {
fmt.Println("错误:", err)
}
_, err = fmt.Scanln(&s)
if err == nil {
fmt.Println("读取到一行:", s)
} else {
fmt.Println("错误:", err)
}
}
对于以下输入:
123
123.456
everybody loves ice cream
输出结果为:
读取到一个整数: 123
读取到一个浮点数: 123.456
读取到一个字符串: everybody
错误: Scan: expected newline
这是预期的行为吗?为什么它不像C++的getline函数那样工作?http://ideone.com/Wx8z5o
英文:
I'm trying to learn Go, but stuck with this one: http://ideone.com/hbCamr or http://ideone.com/OvRw7t
package main
import "fmt"
func main(){
var i int
var f float64
var s string
_, err := fmt.Scan(&i)
if err == nil {
fmt.Println("read 1 integer: ",i)
} else {
fmt.Println("Error: ",err)
}
_, err = fmt.Scan(&f)
if err == nil {
fmt.Println("read 1 float64: ",f)
} else {
fmt.Println("Error: ",err)
}
_, err = fmt.Scan(&s)
if err == nil {
fmt.Println("read 1 string: ",s)
} else {
fmt.Println("Error: ",err)
}
_, err = fmt.Scanln(&s)
if err == nil {
fmt.Println("read 1 line: ",s)
} else {
fmt.Println("Error: ",err)
}
}
for this input:
123
123.456
everybody loves ice cream
the output was:
read 1 integer: 123
read 1 float64: 123.456
read 1 string: everybody
Error: Scan: expected newline
is this the expected behavior? why doesn't it work like C++ getline? http://ideone.com/Wx8z5o
答案1
得分: 11
答案在Scanln
的文档中:
> Scanln与Scan类似,但在换行符处停止扫描,并且在最后一项之后必须有一个换行符或EOF。
Scan
的行为也与文档中描述的一样:
> Scan从标准输入中扫描文本,将连续的以空格分隔的值存储到连续的参数中。换行符被视为空格。它返回成功扫描的项目数。如果成功扫描的项目数少于参数数目,err将报告原因。
总之:Scan
将每个单词(由空格分隔的字符串)放入相应的参数中,将换行符视为空格。Scanln
也是如此,但在换行符处停止解析,不再继续解析。
如果你想读取一行(以\n
结尾),可以使用bufio.Reader
及其ReadString
方法:
line, err := buffer.ReadString('\n')
英文:
The answer is in the documentation of Scanln
:
> Scanln is similar to Scan, but stops scanning at a newline and after the final item there must be a newline or EOF.
Scan
behaves as documented as well:
> Scan scans text read from standard input, storing successive space-separated values into successive arguments. Newlines count as space. It returns the number of items successfully scanned. If that is less than the number of arguments, err will report why.
To conclude: Scan
puts each word (a string separated by space) into a corresponding argument, treating newlines as space. Scanln
does the same but treats newlines as a stop character, not parsing any further after that.
In case you want to read a line (\n
at the end) use bufio.Reader
and its ReadString
method:
line, err := buffer.ReadString('\n')
答案2
得分: 1
作为解决方法,您可以实现自己的fmt.Scanner
:
package main
import "fmt"
type newline struct { tok string }
func (n *newline) Scan(state fmt.ScanState, verb rune) error {
tok, err := state.Token(false, func(r rune) bool {
return r != '\n'
})
if err != nil {
return err
}
if _, _, err := state.ReadRune(); err != nil {
if len(tok) == 0 {
panic(err)
}
}
n.tok = string(tok)
return nil
}
func main() {
var n newline
fmt.Scan(&n)
fmt.Println(n.tok)
}
https://golang.org/pkg/fmt#Scanner
英文:
As a workaround, you can implement your own fmt.Scanner
:
package main
import "fmt"
type newline struct { tok string }
func (n *newline) Scan(state fmt.ScanState, verb rune) error {
tok, err := state.Token(false, func(r rune) bool {
return r != '\n'
})
if err != nil {
return err
}
if _, _, err := state.ReadRune(); err != nil {
if len(tok) == 0 {
panic(err)
}
}
n.tok = string(tok)
return nil
}
func main() {
var n newline
fmt.Scan(&n)
fmt.Println(n.tok)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论