小白初游Go---猜数字课后作业 | 青训营

103 阅读2分钟

一 题目要求

修改第一个例子猜谜游戏里面的最终代码,使用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的原型,我们发现可以这样修改输入语句:

image.png

_, 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
}

三 总结

永远不要小看一个简单的问题。同时求更加优美的解决方案