英文:
Golang reading multiple fields from stdin line
问题
$ echo "A 1 2 3 4" | go run test.go
整行内容: A
下一个字段: A
我需要从标准输入中读取几行内容,格式类似于"A 1 2 3 4"(目前代码只处理一行),但是出现了一些问题。Scanln
应该读取整行内容,而Fields
应该按空格分割字符串?为什么Scanln
只读取了一个单词?
package main
import (
"fmt"
"strings"
)
func main() {
var line string
fmt.Scanln(&line)
fmt.Println("整行内容: ", line)
for _, x := range strings.Fields(line) {
fmt.Println("下一个字段: ", x)
}
}
$ echo "A 1 2 3 4" | go run test.go
整行内容: A
下一个字段: A
英文:
$ echo "A 1 2 3 4" | go run test.go
entire: A
next field: A
I need to read several lines from standard input that are like "A 1 2 3 4" (code does one line for now) and something goes wrong. Scanln
should read the entire line and Fields
should split it by newlines? Why does Scanln read only one word?
package main
import (
"fmt"
"strings"
)
func main() {
var line string
fmt.Scanln(&line)
fmt.Println("entire: ",line)
for _,x := range strings.Fields(line) {
fmt.Println("next field: ",x)
}
}
$ echo "A 1 2 3 4" | go run test.go
entire: A
next field: A
答案1
得分: 6
你试过这样吗:
package main
import (
"fmt"
"os"
"bufio"
"strings"
)
func main() {
var line string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
line = scanner.Text()
fmt.Println("Got line:", line)
for _, x := range strings.Fields(line) {
fmt.Println("next field:",x)
}
}
}
然后:
$ printf "aa bb \n cc dd " | go run 1.go
Got line: aa bb
next field: aa
next field: bb
Got line: cc dd
next field: cc
next field: dd
英文:
Have you tried:
package main
import (
"fmt"
"os"
"bufio"
"strings"
)
func main() {
var line string
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
line = scanner.Text()
fmt.Println("Got line:", line)
for _, x := range strings.Fields(line) {
fmt.Println("next field: ",x)
}
}
}
Then:
$ printf "aa bb \n cc dd " | go run 1.go
Got line: aa bb
next field: aa
next field: bb
Got line: cc dd
next field: cc
next field: dd
答案2
得分: 2
如果你想将每个输入存储到单独的变量中,你可以尝试以下代码:
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
var a, b string
var c int
var r = bufio.NewReader(os.Stdin)
fmt.Fscanf(r, "%s %s %d", &a, &b, &c)
fmt.Printf("%s %s %d", a, b, c)
}
它将输出以下结果:
//给定输入
w r 4
//输出
w r 4
英文:
In case you want to store each input to a seperate variable you can try this:
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
var a, b string
var c int
var r = bufio.NewReader(os.Stdin)
fmt.Fscanf(r, "%s %s %d", &a, &b, &c)
fmt.Printf("%s %s %d", a, b, c)
}
It will give the following output:
//given input
w r 4
//output
w r 4
</details>
# 答案3
**得分**: 1
我被另一个问题的答案误导了,它说`Scanln`会读取整行。不,`Scanln`只是一个读取单词(以空格分隔的字符串)的`Scan`函数,并且只会读取与实际变量数量相匹配的单词,遇到换行符就停止解析。在Go语言中,相当于`readline`的等效函数让人感到非常困惑。
<details>
<summary>英文:</summary>
I got mislead by another question's answer that said `Scanln` reads an entire line. No, Scanln is only a Scan that reads words (space separated strings) and as many as actual variables specified, but quits parsing on a newline. Its totally confusing what the readline equivalent would be in Go.
</details>
# 答案4
**得分**: 0
我意识到这是一个旧问题,但我正在寻找相同的内容,并意识到我们可以对解释进行改进。
实际上,原帖作者@ArekBulski的评论给了我线索,他说:
> Scanln只是一个读取单词(以空格分隔的字符串)并且与参数中指定的实际变量数量相同的扫描器
Scanln()会读取整行内容,但它只会保存与参数中变量数量相等的字符串数量。因此,对于"A 1 2 3 4",`fmt.Scanln(&var1)`只会保存"A",`fmt.Scanln(&var1, &var2)`只会分别保存"A"和"1"到var1和var2中。
因此,当你知道要输入的变量数量时,`fmt.Scanln(a ...interface{})`是一个很好的选择,否则`bufio.NewScanner(os.Stdin)`可能更适合。
<details>
<summary>英文:</summary>
I realize this is an old question, but I was searching for the same thing and realized that we could improve to the explanation.
It was actually the comment from original poster @ArekBulskithat gave me the clue when he said
> Scanln is only a Scan that reads words (space separated strings) and as many as actual variables specified
Scanln() will read the entire line, but it only saves the number of strings equal to the number of variables in the parameters so for "A 1 2 3 4" `fmt.Scanln(&var1)` will only store "A" and `fmt.Scanln(&var1, &var2)` will only store "A" and "1" in var1 and var2 respectively.
Hence `fmt.Scanln(a ...interface{})` is a good fit when you know the number of variables coming in, otherwise `bufio.NewScanner(os.Stdin)` might be a better fit.
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论