douluogu8713 2019-09-01 19:06
浏览 106
已采纳

意外的循环与无效的浮点数

I'm working through the Coursera Go course ... it's pretty good.

In my code below, it works fine when the user correctly a float. But when they enter some random string, it prints the error message and prompt again for each character. Why is that?

package main

import "fmt"

func readFloat(title string) float64 {
  var userInput float64

  for {
    fmt.Println("Please enter a float: ")
    _, err := fmt.Scanf("%f", &userInput)

    if err != nil {
      fmt.Printf("Wooops! That's not a float
")
    } else {
      return userInput
    }
  }
}

func main() {
  var f float64

  f = readFloat("acceleration")
    fmt.Printf("You entered: %.04f
", f)
}
~/src/coursera/go/course-2-functions-methods/week2 $ go run so.go
Please enter a float:
33.3
You entered: 33.3000
~/src/coursera/go/course-2-functions-methods/week2 $ go run so.go
Please enter a float:
sdf
Wooops! That's not a float
Please enter a float:
Wooops! That's not a float
Please enter a float:
Wooops! That's not a float
Please enter a float:
Wooops! That's not a float
Please enter a float:
  • 写回答

2条回答 默认 最新

  • duan02468 2019-09-01 19:55
    关注

    The problem is that if fmt.Scanf() encounters an invalid input, it will stop consuming it. E.g. you want to parse a float using %f, but if user inputs sdf, fmt.Scanf() will know it's invalid after the first s character, so returns an error and will not consume the rest.

    So the next loop iteration begins, it consumes the second character d, which is again invalid etc.

    If you try to enter s2 for example, this will become clear:

    Please enter a float: 
    s2
    Wooops! That's not a float
    Please enter a float: 
    You entered: 2.0000
    

    First s char is invalid, but the next iteration will parse 2.

    One way to "fix" this is to read a whole line as a string, then attempt to parse a float out of the string. For reading a line, use bufio.Scanner, for parsing a float, use strconv.ParseFloat().

    Here's an example how you can do that:

    func readFloat(title string) float64 {
        scanner := bufio.NewScanner(os.Stdin)
        for {
            fmt.Printf("Please enter a float for %s: ", title)
            if !scanner.Scan() {
                fmt.Println("Error readling line")
                return 0 // Should return an error too!
            }
    
            line := scanner.Text()
            userInput, err := strconv.ParseFloat(line, 64)
            if err == nil {
                return userInput
            }
            fmt.Printf("Wooops! That's not a float
    ")
        }
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 ubuntu虚拟机打包apk错误
  • ¥199 rust编程架构设计的方案 有偿
  • ¥15 回答4f系统的像差计算
  • ¥15 java如何提取出pdf里的文字?
  • ¥100 求三轴之间相互配合画圆以及直线的算法
  • ¥100 c语言,请帮蒟蒻写一个题的范例作参考
  • ¥15 名为“Product”的列已属于此 DataTable
  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发