常见获取输入的方式

1.获取同一行的n个数据

1
2
var a, b, c, d int
fmt.Scanln(&a, &b, &c, &d)

2.获取n行数据

从键盘获取n,然后获取n行数据。

1
2
3
4
5
6
7
8
9
var n int
var arr []int
fmt.Scanln(&n)
for n > 0 {
    var temp int
    fmt.Scanln(&temp)
    arr = append(arr, temp)
    n--
}

3.获取未知行数的数据

从键盘获取多行文本,直到用户输入一个空行为止。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
func main() {
    var lines []string
    scanner := bufio.NewScanner(os.Stdin) // 创建一个新的Scanner,它将从键盘读取数据
    for scanner.Scan() { // 循环读取输入,直到没有更多的输入数据或遇到错误
       text := scanner.Text() // 从Scanner读取当前行并作为字符串存储在text变量中
       if text == "" {        // 检查读取的行是否为空字符串(即用户输入了一个空行)
          break
       }
       lines = append(lines, text)
    }
    fmt.Println(lines)
}

这种方式是最通用的,无论输入什么数据类型,输入多少行,程序都可以正常接收,接收到数据的都是 string 类型。

但这种方式也存在弊端,那就是我们在输入数据时,数据类型不一定是字符串类型,上面这种方式还需要进一步的数据类型转换。

在已经明确输入数据类型时,我们可以采用下面的方式:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
func main() {
	var a, b int
	for {
		_, err := fmt.Scanln(&a, &b)
		if err != nil { // 通过判断err是否为空,决定是否继续获取输入
			fmt.Println(err) // 如果输入数据为空,则报错:unexpected newline
			break
		}
		fmt.Println(a + b)
	}
}

在上面的例子中,我们也可以获取位置行数的数据,当输入结束时(键入回车符),err 不为空,那么我们就可以结束 for 循环了。

4.fmt.Scan与fmt.Scanln

相同点

  1. 读取标准输入:两者都用于从标准输入(stdin)读取用户输入的数据。

  2. 接收多个参数:两者都可以接收多个参数,用于读取多个值。

    当接收多个参数时,多个空格或制表符都会被视为 1 个空格。

    比如:

    1
    2
    
    fmt.Scanln(&a, &b, &c)
    fmt.Println(a, c, b)

    输入:

    1
    
    1       3          4

    输出:

    1
    
    1 4 3
  3. 返回读取的项数和错误:两者都返回读取的项数(成功读取并赋值的参数个数)以及可能发生的错误(例如输入/输出错误)。

不同点

fmt.Scan 会把换行符当做空格来分隔多个输入的值;但fmt.Scanln 只读取换行符之前的数据。

也就是说:fmt.Scan 可以一次读取多行的数据,而fmt.Scanln 只能读取一行的数据。

fmt.Scan 示例:

1
fmt.Scan(&a, &b, &c)

输入:

1
2
3
4
5
1

2

3

输出:

1
1 3 2

fmt.Scanln 示例:

1
fmt.Scanln(&a, &b, &c)

输入:

1
1

输出:

1
1 0 0

只会读取回车符前面的值,后面没有读取成功的值会被赋值为 0。

5.获取n行的字符串

现在已知 n,需要获取 n 行的字符串,但每行的字符串中间可能存在空格(空格数未知)。

如:hello world

如果使用下面的代码来获取:

1
2
var str string
fmt.Scanln(&str)

这样只会读取空格前的字符串。

为了解决这一问题,我们可以使用下面的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
reader := bufio.NewReader(os.Stdin)
for n > 0 {
    var err error
    str, _, err = reader.ReadLine()  // 使用reader读取1行的数据
    if err != nil {
       return
    }
    fmt.Println(string(str))
    n--
}

reader.ReadLine() 的 3 个返回值;

  • line []byte: 读取到的一行数据(不包含换行符),如果读取的数据超过了缓冲区的大小,可能会返回部分行,并且 isPrefix 会被设置为 true
  • isPrefix bool: 如果读取的数据太大以至于无法放入缓冲区中,并且返回的数据只是行的一部分,则此值为 true。否则为 false
  • err error: 读取过程中遇到的错误,如果到达文件末尾(EOF),则 err 会是 io.EOF
0%