zoukankan      html  css  js  c++  java
  • Go基础系列:读取标准输入

    fmt包中提供了3类读取输入的函数:

    • Scan家族:从标准输入os.Stdin中读取数据,包括Scan()、Scanf()、Scanln()
    • SScan家族:从字符串中读取数据,包括Sscan()、Sscanf()、Sscanln()
    • Fscan家族:从io.Reader中读取数据,包括Fscan()、Fscanf()、Fscanln()

    其中:

    • Scanln、Sscanln、Fscanln在遇到换行符的时候停止
    • Scan、Sscan、Fscan将换行符当作空格处理
    • Scanf、Sscanf、Fscanf根据给定的format格式读取,就像Printf一样

    这3家族的函数都返回读取的记录数量,并会设置报错信息,例如读取的记录数量不足、超出或者类型转换失败等。

    以下是它们的定义方式:

    $ go doc fmt | grep -Ei "func [FS]*Scan"
    func Fscan(r io.Reader, a ...interface{}) (n int, err error)
    func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error)
    func Fscanln(r io.Reader, a ...interface{}) (n int, err error)
    func Scan(a ...interface{}) (n int, err error)
    func Scanf(format string, a ...interface{}) (n int, err error)
    func Scanln(a ...interface{}) (n int, err error)
    func Sscan(str string, a ...interface{}) (n int, err error)
    func Sscanf(str string, format string, a ...interface{}) (n int, err error)
    func Sscanln(str string, a ...interface{}) (n int, err error)
    

    因为还没介绍io.Reader,所以Fscan家族的函数暂且略过,但用法和另外两家族的scan类函数是一样的。

    Scan、Scanf和Scanln

    Scan家族函数从标准输入读取数据时,将以空格为分隔符分隔标准输入中的内容,并将分隔后的各个记录保存到给定的变量中。其中Scanf()可以指定分隔符。

    例如,使用Scanln函数等待用户输入数据,或从管道中读取数据。下面的代码将等待用户输入,且将读取的内容分别保存到name变量和age变量中:

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	var (
    		name string
    		age  int
    	)
    	fmt.Print("输入姓名和年龄,使用空格分隔:")
    	fmt.Scanln(&name, &age)
    	fmt.Printf("name: %s
    age: %d
    ", name, age)
    }
    

    因为Scanln()遇到换行符或EOF的时候终止读取,所以在输入的时候只要按下回车键就会结束读取。

    运行它,将提示输入姓名:

    请输入姓名和年龄,空格分隔:
    周伯通 69
    name: 周伯通
    age: 69
    

    同理Scanf()也在遇到换行符或EOF的时候终止读取行为。使用Scanf()的时候,需要给定格式化字符串形式:
    例如:

    fmt.Scanf("%s %d",&name,&age)
    

    输入时,第一个字段会转换成字符串格式保存到name变量中,第二个记录会转换成整数保存到age中,如果转换失败,将不会进行保存。例如输入malongshuai aaa,由于aaa无法转换成int,所以age变量的值仍然为初始化的数值0。

    Scanf可指定分隔符,其中上面的是%s %d中间的空格就是分隔符。例如下面指定:作为分隔符:

    fmt.Scanf("%s : %d",&name,&age)
    

    在输入时,必须按照以下格式进行输入:首先至少一个空格,然后一个冒号,再至少一个空格:

    周伯通 : 23    // 或者连续多个空格  "周伯通     :   23"
    name: 周伯通
    age: 23
    

    如果使用的是fmt.Scan(),则输入数据时可以换行输入,Scan()会将换行符作为空格进行处理,直到读取到了2个记录之后自动终止读取操作:

    fmt.Scan(&name, &age)
    
    请输入姓名和年龄,空格分隔:周伯通
    87
    name: 周伯通
    age: 87
    

    一般来说,只使用Scanf类函数比较好。

    返回值

    这些函数都有返回值:读取的记录数量和err信息。

    以Scanln()为例:

    func main() {
    	var (
    		name string
    		age  int
    	)
    	fmt.Print("输入姓名和年龄,使用空格分隔:")
    	n, err := fmt.Scanln(&name, &age)
    
    	fmt.Printf("name: %s
    age: %d
    ", name, age)
    
    	fmt.Println("records count:",n)
    	fmt.Println("err or not:",err)
    }
    

    输入:

    malongshuai 23     // n = 2, err = nil
    malongshuai        // n = 1, err != nil
    malongshuai long   // n = 2, err != nil
    malongshuai 23 23  // n = 2, err != nil
    

    Sscan、Sscanf和Scanln

    Sscan家族的函数用于从给定字符串中读取数据,用法和Scan家族类似。

    func Sscan(str string, a ...interface{}) (n int, err error)
    func Sscanln(str string, a ...interface{}) (n int, err error)
    func Sscanf(str string, format string, a ...interface{}) (n int, err error)
    

    例如:

    package main
    
    import (
    	"fmt"
    )
    
    func main() {
    	var (
    		name string
    		age  int
    	)
    	input := "malongshuai 23"
    
    	fmt.Sscan(input, &name, &age)
    	fmt.Printf("name: %s
    age: %d
    ", name, age)
    }
    

    使用Sscanf()可以指定分隔符:

    input := "malongshuai : 23"
    
    fmt.Sscanf(input, "%s : %d", &name, &age)
    

    使用bufio中读取标准输入

    除了fmt包的Scan类函数,bufio包也可以读取标准输入。当然,读取标准输入只是它的一个功能示例,它的作用是操作缓冲IO。

    package main
    
    import (
    	"bufio"
    	"fmt"
    	"os"
    )
    
    var inputReader *bufio.Reader
    var input string
    var err error
    
    func main() {
    	inputReader = bufio.NewReader(os.Stdin)
    	fmt.Println("输入姓名:")
    	input, err = inputReader.ReadString('
    ')
    	if err == nil {
    		fmt.Printf("The input was: %s
    ", input)
    	}
    }
    

    其中NewReader()创建一个bufio.Reader实例,表示创建一个从给定文件中读取数据的读取器对象。然后调用读取器对象(Reader实例)的ReadString()方法,这个方法以 作为分隔符,它的分隔符必须只能是单字符,且必须使用单引号包围,因为它会作为byte读取。ReadString()读取来自os.Stdin的内容后将其保存到input变量中,同时返回是否出错的信息。ReadString()只有一种情况会返回err:没有遇到分隔符。

    ReadString会将读取的内容包括分隔符都一起放进缓冲中,如果读取文件时读到了结尾,则会将整个文件内容放进缓冲,并将文件终止标识符io.EOF放进设置为err。

    通常无需单独定义这些变量,下面是更常见的用法。

    inputReader := bufio.NewReader(os.Stdin)
    input, err := inputReader.ReadString('
    ')
    
  • 相关阅读:
    各种工具的使用 tricks
    各种工具的使用 tricks
    全栈工程师之路(二)—— JavaScript(网页前端脚本语言)
    全栈工程师之路(二)—— JavaScript(网页前端脚本语言)
    CSS(网页样式语言)基础
    CSS(网页样式语言)基础
    辨异 —— 机器学习概念辨异、模型理解
    辨异 —— 机器学习概念辨异、模型理解
    程序猿/媛段子
    tabhost中activity跳转动画不显示的解决办法
  • 原文地址:https://www.cnblogs.com/f-ck-need-u/p/9944229.html
Copyright © 2011-2022 走看看