为什么Go中的fmt.Scanf不等待用户输入?

huangapple go评论84阅读模式
英文:

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 (
&quot;fmt&quot;
//&quot;math&quot;
)


// compute square roots by using Newton&#39;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(&quot;Enter a number to take its square root: &quot;)
var inputSquare float64
fmt.Scanf(&quot;%f&quot;, &amp;inputSquare)

// why doesn&#39;t program stop after 
// the Print statement and wait
// for user input?
fmt.Print(&quot;Enter first guess &quot;)
var inputGuess float64
fmt.Scanf(&quot;%f&quot;, &amp;inputGuess)

//x = 2
x = inputSquare
y = inputGuess

for i := 0; i &lt; 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(&quot;y --&gt; &quot;, y)
//fmt.Println(&quot;Sqrt(2)&quot;, math.Sqrt(2))
}

答案1

得分: 16

更新:已经在将近十年前修复。现在,关于fmt的文档说明如下:

> 在所有的扫描函数中,紧跟在回车符后面的换行符被视为普通的换行符(\r\n与\n的意义相同)。

如果你继续遇到扫描错误,请注意这不是你的IDE的问题


这是问题 5391fmt:在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(&quot;%f\n&quot;, &amp;inputSquare)
if err != nil || n != 1 {
	// handle invalid input
	fmt.Println(n, err)
}

and

var inputGuess float64
n, err = fmt.Scanf(&quot;%f\n&quot;, &amp;inputGuess)
if err != nil || n != 1 {
	// handle invalid input
	fmt.Println(n, err)
}

The workaround is the newline in the &quot;%f\n&quot; 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 (
	&quot;fmt&quot;
)

// compute square roots by using Newton&#39;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(&quot;Enter a number to take its square root: &quot;)
	var inputSquare float64
	n, err := fmt.Scanf(&quot;%f\n&quot;, &amp;inputSquare)
	if err != nil || n != 1 {
		// handle invalid input
		fmt.Println(n, err)
		return
	}

	fmt.Print(&quot;Enter first guess &quot;)
	var inputGuess float64
	n, err = fmt.Scanf(&quot;%f\n&quot;, &amp;inputGuess)
	if err != nil || n != 1 {
		// handle invalid input
		fmt.Println(n, err)
		return
	}

	x = inputSquare
	y = inputGuess
	for i := 0; i &lt; 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(&quot;sqrt(%g) = %g\n&quot;, 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:\&gt;go version
go version go1.1.1 windows/amd64  

huangapple
  • 本文由 发表于 2013年7月1日 17:59:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/17401709.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定