GO language-some pitfalls in the use of scanf, scan and scanln functions
Some time ago, I have been unable to figure out the differences in the usage scenarios and usage details of the three functions scanf, scan, and scanln. Here I have sorted it out.
Regarding scanf, I have encountered this situation first. When using multiple scanf, unlike the C language, you can enter multiple lines and press enter multiple times.
package main
import "fmt"
//假如我们要输入一个人的年龄和名字
func main() {
var name string
var age int8
fmt.Scanf("%s", &name)
fmt.Scanf("%d", &age)
//fmt.Scanf("%s %d", &name, &age) 对于scanf,这句话等价于上面两句话
fmt.Println(name, " ", age)
}
The two writing methods are the same. If I want to enter the name and age in two lines, it will not work. The result is like this:
The first input method (one-time input):
The second input method (input the name and age in two):
You can see that in the second case, age is not assigned
Why is this?
Let's look at the function prototype of scanf
In fact, scanf has two return values n and err, n is the number of successfully input data in the specified format, err is the error encountered during the reading process, if there is no error, the value of err is nil
package main
import "fmt"
//假如我们要输入一个人的年龄和名字
func main() {
var name string
var age int8
n, err := fmt.Scanf("%s %d", &name, &age) //用n,err分别接受scanf扫描成功的个数和错误返回值
if err == nil{
//如果没有错误就输出name和age的值
fmt.Println(name, " ", age)
}else{
fmt.Println("读取成功",n, "个","错误:",err)
}
}
Let’s try the second unsuccessful input method just now to see what is wrong
It can be seen that we only successfully entered the data of bob. There is an error called unexpected newline. This error is actually the carriage return we entered, because the scanf function ends when it encounters scanf, and reads the data separated by spaces from the buffer. Data; for our program, first press %s to read bob, and then press %d to read the next data (Enter), but the Enter key is not decimal integer data, how can it be read by %d Go in, so there is only one piece of data successfully read, and the error is "Unexpected new line"
Now that you understand the scanf function, let’s take a look at scan and scanln.
First, their function prototypes
Similar to scanf, there are two return values, one is the number of successful reads, and the other is the error value
But what happens if you use it like just now
package main
import "fmt"
//假如我们要输入一个人的年龄和名字
func main() {
var name string
var age int8
n, err := fmt.Scan(&name, &age) //用n,err分别接受scanf扫描成功的个数和错误返回值
/*n, err := fmt.Scan(&name)
n, err = fmt.Scan(&age)*/ //对于scan这种写法也等价于上面那种写法
if err == nil{
//如果没有错误就输出name和age的值
fmt.Println("输出:", name, " ", age)
}else{
fmt.Println("读取成功",n, "个","错误:",err)
}
}
For scan, we can input multiple data in multiple lines
For scanln, it is a little different
package main
import "fmt"
//假如我们要输入一个人的年龄和名字
func main() {
var name string
var age int8
n, err := fmt.Scanln(&name, &age) //这种写法的话必须把name和age一行输入,因为scanln是以回车为标志结束
n, err := fmt.Scanln(&name) //这样写就可以分两行输入name和age
n, err = fmt.Scanln(&age)
if err == nil{
//如果没有错误就输出name和age的值
fmt.Println("输出:", name, " ", age)
}else{
fmt.Println("读取成功",n, "个","错误:",err)
}
}
In fact, scanln will also take away the carriage return in the buffer when it wraps, but scan and scanf will not, so scanf cannot input data in multiple lines. But scan can. Although it does not take the carriage return in the buffer, it will not read the carriage return. When it encounters a carriage return, it will continue to read the next data, and scanf will follow the format we gave (such as %d to read the data), but it must not be read, so the read failed
in conclusion
scanf: read data in sequence according to the given format (including illegal data), and input cannot be entered in a new line (if you want to change a line, you need to add a scanln in front to absorb the carriage return, just like getchar in c language)
scan: higher than scanf, read data sequentially, it will be ignored when encountering a carriage return, and you can enter in a new line (if you want to use scan input first, and then use scanf input, you need to add a scanln in the middle)
scanln: similar to scan, but immediately ends the input when it encounters a line feed (carriage return). If you want to input a line feed, you must use multiple scanlns
Here are a few examples:
package main
import "fmt"
//假如我们要输入一个人的年龄和名字
func main() {
var name string
var age int8
fmt.Scan(&name)// 把Scan换成Scanln就可以了
n, err := fmt.Scanf("%d", &age)
//原因:scan没有把第一行输入结束后的回车收走,导致scanf按%d的格式去读取回车符,那肯定读取失败啊
//而scanln会把第一行输入结束的回车符读走,scanf会按%的格式去读取我们后面输入的数据
if err == nil{
fmt.Println("输出:", name, " ", age)
}else{
fmt.Println("读取成功",n, "个","错误:",err)
}
}
package main
import "fmt"
//假如我们要输入一个人的年龄和名字
func main() {
var name string
var age int8
fmt.Scan(&name)
fmt.Scanln()
fmt.Scanf("%d", &age)
}
}
}
```go
package main
import "fmt"
//假如我们要输入一个人的年龄和名字
func main() {
var name string
var age int8
fmt.Scan(&name)
fmt.Scanln()
fmt.Scanf("%d", &age)
}