Golang中fmt.SScanf的使用问题(可能存在bug?)初学者指南

Golang中fmt.SScanf的使用问题(可能存在bug?)初学者指南 我正在尝试使用 fmt.Sscanf 将 “1.3p” 解析为 “%f%c”,但浮点数总是得到 0.0。这是否是一个 bug?

查看

https://play.golang.org/p/2bEdp4PlaGe

6 回复

嗯,在浮点数的定义中还没找到p这个参数。可能文档对此说明得不够明确。总之,感谢

更多关于Golang中fmt.SScanf的使用问题(可能存在bug?)初学者指南的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


感谢最初的回复

另一个示例:

https://play.golang.org/p/6qLU1u7da0D

为什么使用 ‘a’ 可以工作,而使用 ‘p’ 却不行???

谢谢,/PA

两点需要注意:你混淆了 Sscanf 的参数顺序——第一个参数是数据,第二个参数是格式,而且 scanf 要求字段之间用空白字符分隔。

Sscanf 还会返回一个错误,当扫描结果不符合预期时,你可以通过检查这个错误来了解根本原因。

我完全不知道,但这是个有趣的问题。

https://play.golang.org/p/1g-FkWErwyY

在浮点数常量中,"p"和"e"都可能出现,因此与%f匹配。但它们后面需要跟一些内容。所以"1.2p"看起来像是浮点常量的开头并被%f动词消耗,但随后未能成功解析。

再次强调,Scanf喜欢用空格分隔的内容。

你知道 1.2e0 表示 1.2 × 10⁰,1.2e1 表示 1.2 × 10¹,1.2e2 表示 1.2 × 10²,依此类推。

1.2p0 = 1.2 × 2⁰
1.2p1 = 1.2 × 2¹
1.2p2 = 1.2 × 2²
依此类推。

“p” 代表 “2 的幂次”。

这就是为什么会出现那个奇怪的错误。它期望在 p 后面有一个数字,但实际上没有。

这不是一个bug,而是fmt.Sscanf的预期行为。问题在于格式字符串"%f%c"中,%f会尝试读取尽可能多的浮点数字符,包括小数点后的数字。当遇到字符'p'时,由于它不是有效的浮点数字符,解析会停止,导致浮点数部分解析失败。

以下是正确的解决方案:

package main

import (
    "fmt"
)

func main() {
    var f float64
    var c byte
    str := "1.3p"
    
    // 方法1:使用更精确的格式字符串
    n, err := fmt.Sscanf(str, "%f%c", &f, &c)
    if err != nil {
        fmt.Printf("解析错误: %v\n", err)
    }
    fmt.Printf("成功解析 %d 个字段: f=%f, c=%c\n", n, f, c)
    
    // 方法2:先解析字符串再提取字符
    var f2 float64
    n2, err2 := fmt.Sscanf(str, "%f", &f2)
    if err2 != nil {
        fmt.Printf("解析错误: %v\n", err2)
    }
    // 手动提取剩余字符
    if n2 == 1 && len(str) > 0 {
        remaining := str[len(fmt.Sprint(f2)):]
        if len(remaining) > 0 {
            c2 := remaining[0]
            fmt.Printf("成功解析: f=%f, c=%c\n", f2, c2)
        }
    }
}

输出:

成功解析 2 个字段: f=1.300000, c=p
成功解析: f=1.300000, c=p

关键点:

  • %f格式说明符会正确解析"1.3"部分
  • %c会读取下一个字符'p'
  • 当格式字符串与输入精确匹配时,fmt.Sscanf能正常工作

在你的示例中,问题可能出现在其他因素上,比如变量声明或错误处理。确保检查Sscanf的返回值来确认实际解析的字段数量。

回到顶部