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('
    ')
    
  • 相关阅读:
    新概念第二册(1)--英语口语听力课1
    外企面试课程(一)---熟悉常见的缩略词
    公司 邮件 翻译 培训 长难句 结课
    workflow
    公司 邮件 翻译 培训 长难句 20
    公司 邮件 翻译 培训 长难句 19
    Engineering Management
    公司 邮件 翻译 培训 长难句 18
    公司 邮件 翻译 培训 长难句 17
    第14.5节 利用浏览器获取的http信息构造Python网页访问的http请求头
  • 原文地址:https://www.cnblogs.com/f-ck-need-u/p/9944229.html
Copyright © 2011-2022 走看看