使用Golang从标准输入中扫描一行数字

4

我正在尝试从标准输入读取输入,就像这样:

3 2 1<ENTER>

并将其保存在一个整数列表中。目前我的代码如下:
nums = make([]int, 0)
var i int
for {
    _, err := fmt.Scan(&i)
    if err != nil {
        if err==io.EOF { break }
        log.Fatal(err)
    }
    nums = append(nums, i)
}

目前程序始终停留在for循环中。我在文档中找不到检查换行符的简单方法。我该怎么做?

编辑:

由于我知道几乎肯定会有四个数字,所以我尝试了以下操作:

var i0,i1,i2,i3 int
fmt.Scanf("%d %d %d %d\n", &i0, &i1, &i2, &i3)

但是这个程序只扫描了第一个数字然后就退出了。我不确定这是否是因为我使用的z-shell导致的。
编辑:
为了澄清,该程序会暂停并要求用户输入由空格分隔并以换行符终止的n个数字列表。这些数字应存储在一个数组中。

1
Ctrl+D 会向您的程序发送 EOF。 - kostya
如果您不知道有多少数字,为什么不一次性扫描整行呢? - JimB
1
在我看来,你的问题不太清楚。你是想要 1. 读取文件中的 所有 数字(看起来像是你问题中的第一个代码),2. 读取一行中的 所有 数字(你回答中的代码),还是 3. 从一行中 精确地 读取 n 个数字(看起来像是你问题中的第二个代码块),或者 4. 其他什么?如果你能 明确地 告诉我们你想要什么,我相信社区可以帮助你。 - gbulmer
3个回答

5

好的,我决定动用大型的bufio解决它:

in := bufio.NewReader(os.Stdin)
line, err := in.ReadString('\n')
if err != nil {
    log.Fatal(err)
}
strs := strings.Split(line[0:len(line)-1], " ")
nums := make([]int, len(strs))
for i, str := range strs {
    if nums[i], err = strconv.Atoi(str); err != nil {
        log.Fatal(err)
    }
}

看起来代码确实很多,但它能运行。


1
我觉得你粘贴的代码不完整。应该在末尾再加一个'}'来关闭for循环。最好也将if nums[] ... {...}缩进。看起来这似乎是在一行中读取所有数字。这是你想要的吗? - gbulmer
是的,这正是我想要的 :) 我本以为有一种方法可以使用类似于 var args []interface{}; fmt.Scanln(args...) 的方式来读取它,但我无法让它工作。 - ehrt1974
你刚刚传递了一个空接口切片吗?文档(顾名思义)指出:“所有要扫描的参数都必须是基本类型的指针或 Scanner 接口的实现。” - nes1983
是的,那正是我所做的 :) 它不喜欢var args []string; fmt.Scanln(args...)。我会找出错误信息。 - ehrt1974
那是因为[]string与[]interface{}是不同的类型。再次强调,文档中说必须传递基本类型的指针。你没有传递任何指针,所以你没有得到任何结果。如果你传递这个:var i, j, k int; fmt.Scanln([]interface{&i, &j, &k}...}你会得到更好的结果。你会在变量i、j、k中找到这些结果。我认为混淆的根源在于你试图让一行中有多少数字成为一个开放性问题。fmt.Scanln并不是这样构建的。你必须传递n个指针来读取n个数字。 - nes1983

2

看起来您想要https://golang.org/pkg/fmt/#Fscanln

类似这样的东西

ok := func(err error) { if err != nil { panic(err) } }

for {
  var i, j, k int
  _, err := fmt.Fscanln(io.Stdin, &i, &j, &k)
  ok(err)
  fmt.Println(i, j, k)
}

1
我建议使用“bufio”包和“scan()”方法。以下是读取两行来自“stdin”的代码,并将这些行存储到数组中。希望这能帮到你。
package main

import (

    "fmt"
    "bufio"
    "os"
    "strconv"
    "strings"
)

func ReadInput() []string{

    var lines []string
    scanner := bufio.NewScanner(os.Stdin)

    for scanner.Scan() {
        lines = append(lines, scanner.Text())
        //count, _ := strconv.Atoi(lines[0])
        if len(lines) == 2 { break }
    }
    if err := scanner.Err(); err != nil {
    fmt.Fprintln(os.Stderr, err)
    }
    return lines
}

func main(){

    lines   := ReadInput()
    count ,_ := strconv.Atoi(lines[0])
    num := strings.Fields(lines[1])
    if count != len(num) { os.Exit(0) }
 // Do whatever you want here
}

将接受两行文本。第一行将包含计数,第二行将包含所有数字。您可以根据需要修改相同的代码。

示例:

3
1 5 10 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接