英文:
Why doesn't fmt.Scanf in Go wait for user input?
问题
我正在阅读Caleb Doxsey的Go语言书籍,并且有两个关于fmt.Scanf
的问题。我想知道为什么程序在第二个Scanf之后不停下来等待用户输入?还有,我如何测试用户是否输入了一个整数和/或没有留空?
package main
import (
"fmt"
//"math"
)
// 使用牛顿法计算平方根
func main() {
var x float64 //要求平方根的数字
var y float64 //猜测值
var q float64 //商
var a float64 //平均值
// 如何检查用户是否输入了一个数字
fmt.Print("输入一个数字以求其平方根:")
var inputSquare float64
fmt.Scanf("%f", &inputSquare)
// 为什么程序在Print语句之后不停下来等待用户输入?
fmt.Print("输入第一个猜测值:")
var inputGuess float64
fmt.Scanf("%f", &inputGuess)
//x = 2
x = inputSquare
y = inputGuess
for i := 0; i < 10; i++ { //设置循环迭代次数
q = x/y //计算商;x和y是已知的
a = (q + y) / x //计算平均值
y = a //将猜测值设置为平均值
} //为下一次循环做准备
fmt.Println("y --> ", y)
//fmt.Println("Sqrt(2)", math.Sqrt(2))
}
英文:
I am working through Caleb Doxsey's Go book and I have two questions about fmt.Scanf
http://www.golang-book.com/4
I am wondering why the program does not stop after the second Scanf and wait for user input? And how do I test if the user entered an integer and/or did not leave blank?
package main
import (
"fmt"
//"math"
)
// compute square roots by using Newton's method
func main() {
var x float64 //number to take square root
var y float64 //this is the guess
var q float64 //this is the quotient
var a float64 //this is the average
// how do check if the user entered a number
fmt.Print("Enter a number to take its square root: ")
var inputSquare float64
fmt.Scanf("%f", &inputSquare)
// why doesn't program stop after
// the Print statement and wait
// for user input?
fmt.Print("Enter first guess ")
var inputGuess float64
fmt.Scanf("%f", &inputGuess)
//x = 2
x = inputSquare
y = inputGuess
for i := 0; i < 10; i++ { //set up the for loop for iterations
q = x/y //compute the quotient; x and y are given
a = (q + y) / x //compute the average
y = a //set the guess to the average
} //for the next loop
fmt.Println("y --> ", y)
//fmt.Println("Sqrt(2)", math.Sqrt(2))
}
答案1
得分: 16
更新:已经在将近十年前修复。现在,关于fmt
的文档说明如下:
> 在所有的扫描函数中,紧跟在回车符后面的换行符被视为普通的换行符(\r\n与\n的意义相同)。
如果你继续遇到扫描错误,请注意这不是你的IDE的问题。
这是问题 5391:fmt
:在Windows上,Scanf
拒绝以\r\n
结尾的行。
作为解决方法和检查有效输入的方式,可以编写以下代码:
var inputSquare float64
n, err := fmt.Scanf("%f\n", &inputSquare)
if err != nil || n != 1 {
// 处理无效输入
fmt.Println(n, err)
}
和
var inputGuess float64
n, err = fmt.Scanf("%f\n", &inputGuess)
if err != nil || n != 1 {
// 处理无效输入
fmt.Println(n, err)
}
解决方法是在"%f\n"
格式字符串中加入换行符。
> 包fmt
>
> func Scanf
>
> func Scanf(format string, a ...interface{}) (n int, err error)
>
> Scanf
从标准输入中扫描文本,根据格式将连续的以空格分隔的值存储到连续的参数中。它返回成功扫描的项目数。
下面是一个完整的工作程序:
package main
import (
"fmt"
)
// 使用牛顿法计算平方根
func main() {
var x float64 // 要求平方根的数字
var y float64 // 猜测值
var q float64 // 商
var a float64 // 平均值
fmt.Print("输入一个数字以求其平方根:")
var inputSquare float64
n, err := fmt.Scanf("%f\n", &inputSquare)
if err != nil || n != 1 {
// 处理无效输入
fmt.Println(n, err)
return
}
fmt.Print("输入第一个猜测值:")
var inputGuess float64
n, err = fmt.Scanf("%f\n", &inputGuess)
if err != nil || n != 1 {
// 处理无效输入
fmt.Println(n, err)
return
}
x = inputSquare
y = inputGuess
for i := 0; i < 10; i++ {
q = x / y // 计算商;x和y是已知的
a = (q + y) / x // 计算平均值
y = a // 将猜测值设置为平均值
}
fmt.Printf("sqrt(%g) = %g\n", x, y)
}
输出:
输入一个数字以求其平方根:2.0
输入第一个猜测值:1.0
sqrt(2) = 1.414213562373095
我在Windows 7上使用的是Go 1.1.1:
C:\>go version
go version go1.1.1 windows/amd64
英文:
Update: was fixed almost a decade ago. The docs for fmt
now read
> In all the scanning functions, a carriage return followed immediately by a newline is treated as a plain newline (\r\n means the same as \n).
If you continue to have scanning errors, mind that it isn't your IDE's fault.
It's Issue 5391: fmt
: Scanf
rejects \r\n
at end of line on Windows.
As a workaround and to check for valid input, write,
var inputSquare float64
n, err := fmt.Scanf("%f\n", &inputSquare)
if err != nil || n != 1 {
// handle invalid input
fmt.Println(n, err)
}
and
var inputGuess float64
n, err = fmt.Scanf("%f\n", &inputGuess)
if err != nil || n != 1 {
// handle invalid input
fmt.Println(n, err)
}
The workaround is the newline in the "%f\n"
format strings.
> Package fmt
>
> func Scanf
>
> func Scanf(format string, a ...interface{}) (n int, err error)
>
> Scanf
scans text read from standard input, storing successive
> space-separated values into successive arguments as determined by the
> format. It returns the number of items successfully scanned.
Here's a complete working program:
package main
import (
"fmt"
)
// compute square roots by using Newton's method
func main() {
var x float64 //number to take square root
var y float64 //this is the guess
var q float64 //this is the quotient
var a float64 //this is the average
fmt.Print("Enter a number to take its square root: ")
var inputSquare float64
n, err := fmt.Scanf("%f\n", &inputSquare)
if err != nil || n != 1 {
// handle invalid input
fmt.Println(n, err)
return
}
fmt.Print("Enter first guess ")
var inputGuess float64
n, err = fmt.Scanf("%f\n", &inputGuess)
if err != nil || n != 1 {
// handle invalid input
fmt.Println(n, err)
return
}
x = inputSquare
y = inputGuess
for i := 0; i < 10; i++ {
q = x / y // compute the quotient; x and y are given
a = (q + y) / x // compute the average
y = a // set the guess to the average
}
fmt.Printf("sqrt(%g) = %g\n", x, y)
}
Output:
Enter a number to take its square root: 2.0
Enter first guess 1.0
sqrt(2) = 1.414213562373095
I used Go 1.1.1 on Windows 7:
C:\>go version
go version go1.1.1 windows/amd64
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论