如何在Go中的fmt.Scanf()之后刷新Stdin?
现在有一个问题困扰着我。当从用户处获取输入时,我希望使用一个循环,要求用户重试,直到输入有效的输入:如何在Go中的fmt.Scanf()之后刷新Stdin?,go,user-input,stdin,Go,User Input,Stdin,现在有一个问题困扰着我。当从用户处获取输入时,我希望使用一个循环,要求用户重试,直到输入有效的输入: // user_input.go package main import ( "fmt" ) func main() { fmt.Println("Please enter an integer: ") var userI int for { _, err := fmt.Scanf("%d", &userI) if
// user_input.go
package main
import (
"fmt"
)
func main() {
fmt.Println("Please enter an integer: ")
var userI int
for {
_, err := fmt.Scanf("%d", &userI)
if err == nil {
break
}
fmt.Println("Sorry, invalid input. Please enter an integer: ")
}
fmt.Println(userI)
}
运行上述操作,如果用户输入有效输入,则没有问题:
请输入一个整数:
3
3
退出代码0,进程正常退出。 但是试着输入一个字符串 请输入一个整数: 什么?
抱歉,输入无效。请输入一个整数:
抱歉,输入无效。请输入一个整数:
对不起 等等,它会一个字符一个字符地循环,直到字符串用完为止。 即使输入一个字符循环两次,我假设它解析换行符 不管怎么说,一定有办法在围棋中冲掉Stdin
另外,如果没有这样的功能,您将如何解决它以提供同等的功能?我甚至失败了…每次失败后,我都会通过阅读直到行尾来解决这个问题。这将清除文本的其余部分
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
stdin := bufio.NewReader(os.Stdin)
fmt.Println("Please enter an integer: ")
var userI int
for {
_, err := fmt.Fscan(stdin, &userI)
if err == nil {
break
}
stdin.ReadString('\n')
fmt.Println("Sorry, invalid input. Please enter an integer: ")
}
fmt.Println(userI)
}
我知道这已经得到了回答,但这是我的实施:
func刷新(读卡器*bufio.reader){
变量i int
对于i=0;i
这应该适用于任何情况,包括不能使用“stdin.ReadString('\n')”的情况。唤醒一个旧问题是否不好 我更喜欢使用
fmt.Scanln
,因为A)它不需要导入另一个库(例如读卡器)和B)它不涉及显式for循环
func someFunc() {
fmt.Printf("Please enter an integer: ")
// Read in an integer
var i int
_, err := fmt.Scanln(&i)
if err != nil {
fmt.Printf("Error: %s", err.Error())
// If int read fails, read as string and forget
var discard string
fmt.Scanln(&discard)
return
}
fmt.Printf("Input contained %d", i)
}
然而,似乎应该有一个更优雅的解决方案。特别是在fmt.Scanln的情况下,读取在第一个非数字字节之后停止,而不是“扫描行”,这似乎很奇怪 我在获取用户输入时遇到了类似的问题,但解决方法略有不同。添加到线程以防其他人发现此功能有用:
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
// Get first word from stdin
func getFirstWord() (string) {
input := bufio.NewScanner(os.Stdin)
input.Scan()
ans := strings.Fields(input.Text())
if len(ans) == 0 {
return ""
} else {
return ans[0]
}
}
func main() {
fmt.Printf("Would you like to play a game?\n> ")
ans := getFirstWord()
fmt.Printf("Your answer: %s\n", ans)
}
很抱歉,我今天遇到了这个问题,我想通过使用新的标准库功能来改进现有的答案
import (
"bufio"
"fmt"
"os"
)
func discardBuffer(r *bufio.Reader) {
r.Discard(r.Buffered())
}
stdin := bufio.NewReader(os.Stdin)
var i int
for true {
if _, err := fmt.Fscanln(stdin, &i); err != nil {
discardBuffer(stdin)
// Handle error, display message, etc.
continue
}
// Do your other value checks and validations
break
}
基本思想是始终缓冲从stdin读取的数据。当扫描时遇到错误时,只需丢弃缓冲区内容即可。这样,您就可以从一个空缓冲区开始下一次扫描
或者,您可以在扫描之前丢弃缓冲区,这样用户在此之前的任何杂散输入都不会被拾取
func fscanln(r *bufio.Reader, a ...interface{}) error {
r.Discard(r.Buffered())
_, err := fmt.Fscanln(r, a...)
return err
}
stdin := bufio.NewReader(os.Stdin)
var i int
if err := fscanln(stdin, &i); err != nil {
// Handle error
}
我使用此代码段过滤不必要的前导空格/新行
in := bufio.NewReader(os.Stdin)
result, err = in.ReadString('\n')
for len(strings.TrimSpace(result)) == 0 {
result, err = in.ReadString('\n')
}
当然,只需使用
Scanln
,它被记录为占用空白并一直读到新行。