Golang中STD I/O函数的一个小但烦人的问题

Golang中STD I/O函数的一个小但烦人的问题 你好,我是Go语言的新手,但之前一直在用C++编程。我决定学习Go,对我来说,最好的方法就是看一些结构化的视频教程,然后去解决SPOJ、Codeforces等平台上的编程问题。

我现在正在尝试解决一个几乎微不足道的问题,因为它的逻辑并不复杂,但我觉得我在标准输入部分遇到了问题,想看看这里是否有人能帮我。我一直在试图弄清楚为什么会发生这种情况,但还没有找到确切的答案。

以下是输入示例、我得到的输出,以及问题的链接(如果你想知道的话): (输入示例) 2 2 1 2 3 4 3 1 2 3 4 5 6

(输出示例) [1 1] [3 3] [1 3 4] [6 6 6]

(问题链接) SPOJ.com - Problem FASHION SPOJ.com - Problem FASHION

我目前的怀疑是问题出在fmt.Scanf上,好像它没有在控制台行中逐个元素地前进,而总是读取同一个第一个元素(这听起来很荒谬),但我还没有找到任何解释其原因的资料,甚至连函数描述里也没有。

非常感谢。

package main

import (

    "fmt"

)

func main() {

    var (

        cases, couples int

        array          []int

        array2         []int

        x              int

       // suma           int = 0

    )

    fmt.Scanln(&cases)

    for i := 0; i < cases; i++ {

        fmt.Scanln(&couples)

        array = nil

        for j := 0; j < couples; j++ {

            fmt.Scanf("%d ", &x)

            array = append(array, x)

        }

        fmt.Println(array)

        array2 = nil

        for j := 0; j < couples; j++ {

            //fmt.Println("flag")

            fmt.Scanf("%d ", &x)

            array2 = append(array2, x)

            //suma += 0

        }

        fmt.Println(array2)

    }

}

更多关于Golang中STD I/O函数的一个小但烦人的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

不要忽略从 Scan 返回的错误。它可能提供线索。

更多关于Golang中STD I/O函数的一个小但烦人的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


嘿,谢谢你的回复。我已经解决了这个问题,不得不使用 bufio.Scannerstrings.Splitstrconv.Atoi。虽然问题解决了,但我仍然想知道为什么会发生这个错误,我打算继续研究一下。

问题出在fmt.Scanf("%d ", &x)中的空格格式符。在Go的fmt.Scanf中,尾随空格会导致函数持续读取输入直到遇到非空白字符,这会造成读取行为异常。

以下是修正后的代码:

package main

import (
    "fmt"
)

func main() {
    var cases, couples int
    fmt.Scanln(&cases)
    
    for i := 0; i < cases; i++ {
        fmt.Scanln(&couples)
        
        array := make([]int, couples)
        for j := 0; j < couples; j++ {
            fmt.Scanf("%d", &array[j])
        }
        fmt.Println(array)
        
        array2 := make([]int, couples)
        for j := 0; j < couples; j++ {
            fmt.Scanf("%d", &array2[j])
        }
        fmt.Println(array2)
    }
}

更简洁的替代方案是使用fmt.Scan

package main

import (
    "fmt"
)

func main() {
    var cases, couples int
    fmt.Scan(&cases)
    
    for i := 0; i < cases; i++ {
        fmt.Scan(&couples)
        
        array := make([]int, couples)
        for j := 0; j < couples; j++ {
            fmt.Scan(&array[j])
        }
        fmt.Println(array)
        
        array2 := make([]int, couples)
        for j := 0; j < couples; j++ {
            fmt.Scan(&array2[j])
        }
        fmt.Println(array2)
    }
}

对于竞赛编程,推荐使用bufio.Scanner以获得更好的性能:

package main

import (
    "bufio"
    "fmt"
    "os"
    "strconv"
    "strings"
)

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    scanner.Scan()
    cases, _ := strconv.Atoi(scanner.Text())
    
    for i := 0; i < cases; i++ {
        scanner.Scan()
        couples, _ := strconv.Atoi(scanner.Text())
        
        scanner.Scan()
        nums1 := strings.Fields(scanner.Text())
        array := make([]int, couples)
        for j := 0; j < couples; j++ {
            array[j], _ = strconv.Atoi(nums1[j])
        }
        fmt.Println(array)
        
        scanner.Scan()
        nums2 := strings.Fields(scanner.Text())
        array2 := make([]int, couples)
        for j := 0; j < couples; j++ {
            array2[j], _ = strconv.Atoi(nums2[j])
        }
        fmt.Println(array2)
    }
}

关键点:在Go的fmt.Scanf中避免使用尾随空格格式符,它们会导致意外的读取行为。

回到顶部