英文:
Why does fmt.Scan() behave in a weird way?
问题
我正在尝试验证用户输入。如果用户输入一个整数,它会按预期工作。然而,如果用户输入一个非整数的字符串,变量userTickets
会被赋值为0
,但会打印出多次Try again! It must be more than zero:
。确切地说,它会打印len(input)
次,我不明白为什么会这样。
我还尝试使用fmt.Scanf("%d", &usertickets)
来实现期望的结果,但得到了相同的结果。
为什么会出现这种行为,我该如何编写一个解决方法?
package main
import "fmt"
func main() {
var remainingTickets uint = 50
var userTickets uint
fmt.Print("Enter the number of tickets you want to purchase: ")
fmt.Scan(&userTickets)
for userTickets > remainingTickets {
fmt.Printf("We only have %v tickets available!\n", remainingTickets)
fmt.Print("Try again! Enter the number of tickets: ")
fmt.Scan(&userTickets)
}
for userTickets == 0 {
fmt.Print("Try again! It must be more than zero: ")
fmt.Scan(&userTickets)
}
fmt.Printf("Remaining tickets: %v\n", remainingTickets-userTickets)
}
英文:
I'm trying to validate the user input. If the user inputs an integer number it works like expected. However, if the user inputs a non-integer string, the variable userTickets
gets assigned value 0
, but prints Try again! It must be more than zero:
many times. To be exact, it prints len(input)
times and I don't understand why.
Also tried achieving desired result using fmt.Scanf("%d", &usertickets)
but got an identical result.
Why does it behave this way and how can I write a workaround for it?
package main
import "fmt"
func main() {
var remainingTickets uint = 50
var userTickets uint
fmt.Print("Enter the number of tickets you want to purchase: ")
fmt.Scan(&userTickets)
for userTickets > remainingTickets {
fmt.Printf("We only have %v tickets available!\n", remainingTickets)
fmt.Print("Try again! Enter the number of tickets: ")
fmt.Scan(&userTickets)
}
for userTickets == 0 {
fmt.Print("Try again! It must be more than zero: ")
fmt.Scan(&userTickets)
}
fmt.Printf("Remaining tickets: %v\n", remainingTickets-userTickets)
}
答案1
得分: 1
Scan能够在不读取stdin的全部内容的情况下确定输入不是数字。这就是为什么当输入非数字时,验证逻辑会循环len(input)次的原因。虽然你也可以使用Scanner(人们确实推荐这种方法),但下面是一个类似于你的方法的实现。请注意,所有的验证检查都在一个单独的"for"循环中完成:
package main
import (
"fmt"
"strconv"
)
func main() {
var remainingTickets uint64 = 50
fmt.Print("请输入您想购买的票数:")
for {
var userTickets string
fmt.Scanln(&userTickets)
// 解析以确保我们得到一个正(无符号)整数
u64, err := strconv.ParseUint(userTickets,10,64)
// 确保它是一个正整数且不等于零
if err != nil || u64==0{
fmt.Print("请重试!您必须输入一个大于零的数字:")
continue
}
// 检查剩余票数是否足够
if u64 > remainingTickets {
fmt.Printf("我们只剩下 %v 张票!\n", remainingTickets)
fmt.Print("请重试!请输入票数:")
continue
}
// 更新剩余票数
remainingTickets -= u64
break
}
fmt.Printf("剩余票数:%d\n", remainingTickets)
}
希望对你有帮助!
英文:
Scan is able to determine that the input isn't numeric without reading the entire contents of stdin. This is why you validation logic loops for len(input) when non-numeric. While you can use a Scanner as well (and people do recommend that approach), below is an approach similar to yours. Note that all validation checking is done within a single "for" loop as well:
package main
import (
"fmt"
"strconv"
)
func main() {
var remainingTickets uint64 = 50
fmt.Print("Enter the number of tickets you want to purchase: ")
for {
var userTickets string
fmt.Scanln(&userTickets)
// parse to make sure we get a positive (unsigned) integer
u64, err := strconv.ParseUint(userTickets,10,64)
// make sure it's a postive integer and not equal to zero
if err != nil || u64==0{
fmt.Print("Try again! You must enter a number greater than zero: ")
continue
}
// check to make sure we have enough tickets left
if u64 > remainingTickets {
fmt.Printf("We only have %v tickets available!\n", remainingTickets)
fmt.Print("Try again! Enter the number of tickets: ")
continue
}
// update remaining tickets
remainingTickets -= u64
break
}
fmt.Printf("Remaining tickets: %d\n", remainingTickets)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论