GO language input functions-some pitfalls in the use of scanf, scan, and scanln functions

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):

Insert picture description here

The second input method (input the name and age in two):

Insert picture description here

You can see that in the second case, age is not assigned

Why is this?

Let's look at the function prototype of scanf

Insert picture description here

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
Insert picture description here

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

Insert picture description here
Insert picture description here

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

Insert picture description here

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)
	
}

Guess you like

Origin blog.csdn.net/qq_52698632/article/details/113747479