一 题目要求
修改第一个例子猜谜游戏里面的最终代码,使用fmt.Scanf来简化代码实现
二 具体实现
很简单的一个练习题,但是对Go不了解的我还是踩坑了qwq。
例子:我要使用fmt.Scanf输入一个人的名字和年龄,我可以写出下面的代码:
package main
import "fmt"
func main() {
var name string
var age int8
fmt.Scanf("%s", &name)
fmt.Scanf("%d", &age)
fmt.Println(name, " ", age)
}
如果在运行程序时我们把名字和年龄一起输入,可以正常运行;但是如果在输入完名字以后按回车想要再输入年龄,这个时候程序会直接结束并把年龄赋值为0.
通过查看Scanf的原型,我们发现可以这样修改输入语句:
_, err := fmt.Scanf("%s %d", &name, &age)
这样可以在输入后判断输入是否正确。
因此,我将课程代码修改如下:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
maxNum := 100
rand.Seed(time.Now().UnixNano())
secretNumber := rand.Intn(maxNum)
// fmt.Println("the secret number is ", secretNumber)
fmt.Println("please input your guess")
// reader := bufio.NewReader(os.Stdin)
for {
// input, err := reader.ReadString('\n')
// if err != nil {
// fmt.Println("an error occured while reading input. try again", err)
// continue
// }
// input = strings.TrimSuffix(input, "\r\n")
// guess, err := strconv.Atoi(input)
// if err != nil {
// fmt.Println("Invalid input. please enter an integer value")
// continue
// }
var guess int
_, err := fmt.Scanf("%d \n", &guess)
if err != nil {
fmt.Println("Invalid input. please enter an integer value")
continue
}
fmt.Println("you guess is ", guess)
if guess > secretNumber {
fmt.Println("your guess is bigger. try again")
} else if guess < secretNumber {
fmt.Println("your guess is smaller. try again")
} else {
fmt.Println("you are right!")
break
}
}
}
但是,这样运行以后虽然不合法的输入(例如9.9)会引发err,但是由于.后面的内容还留在输入缓冲区里,导致下一轮循环会把9.9小数点后的9重新读入,导致与我们的预期背离,我的解决方案是在判断输入不合法后将输入缓冲区中的内容读取到string temp中,修改后的部分代码片段如下所示:
var guess int
var temp string
_, err := fmt.Scanf("%d \n", &guess)
if err != nil {
fmt.Println("Invalid input. please enter an integer value")
fmt.Scanf(%s \n", &temp)
continue
}
三 总结
永远不要小看一个简单的问题。同时求更加优美的解决方案。