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\nage: %d\n", 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\nage: %d\n", 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\nage: %d\n", 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('\n') if err == nil { fmt.Printf("The input was: %s\n", input) } }
其中NewReader()创建一个bufio.Reader实例,表示创建一个从给定文件中读取数据的读取器对象。然后调用读取器对象(Reader实例)的ReadString()方法,这个方法以
\n作为分隔符,它的分隔符必须只能是单字符,且必须使用单引号包围,因为它会作为byte读取。ReadString()读取来自os.Stdin的内容后将其保存到input变量中,同时返回是否出错的信息。ReadString()只有一种情况会返回err:没有遇到分隔符。
ReadString会将读取的内容包括分隔符都一起放进缓冲中,如果读取文件时读到了结尾,则会将整个文件内容放进缓冲,并将文件终止标识符io.EOF放进设置为err。
通常无需单独定义这些变量,下面是更常见的用法。
inputReader := bufio.NewReader(os.Stdin) input, err := inputReader.ReadString('\n')
- awk 系列:awk 怎么读取标准输入(STDIN)
- Linux下统计文件行数 语法:wc [选项] 文件… 说明:该命令统计给定文件中的字节数、字数、行数。如果没有给出文件名,则从标准输入读取。wc同时也给出所有 指定文件的总统计数。字是由空格字符
- 从标准输入读取
- Linux基础之标准输入和输出
- Linux基础(6)标准输入输出与重定向
- 【Perl读书笔记】读取标准输入
- C#从文件或标准输入设备读取指定行的方法
- 编写一个程序从标准输入读取字符,并把它们写到标准输出。除了大写字母转化成小写字母之外,其他的原样输出。
- 笔记1-3: 从标准输入读取命令并执行
- 标准输入读取字符,并标准输出。大写字母转换成小写字母,其他的原样输出
- java--IO流-LineNumberReader,读取键盘录入,字符字节流转换,改变标准输入输出设备,异常的日志信息,系统信息
- C++ 从标准输入设备读取字符的函数
- 标准C++基础系列(22) 好东西多看看
- 【C语言】编写一个程序从标准输入读取字符,并把他们写到标准输出。除了大写字母转换成小写字母之外,其他的原样输出。
- go语言的标准输入-scan 和bufio
- Go基础系列:Go slice详解
- Go基础系列:defer、panic和recover
- Go基础系列:接口类型断言和type-switch
- C++语言基础之标准输入cin
- Java基础知识强化之IO流笔记61:标准输入输出流的本质