How to use fmt.Sscan to parse integers into an array?

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

How to use fmt.Sscan to parse integers into an array?

问题

我正在尝试将一个字符串中的整数列表扫描到一个数组(或者可以选择使用切片)中。

  1. package main
  2. import "fmt"
  3. func main() {
  4. var nums [5]int
  5. n, _ := fmt.Sscan("1 2 3 4 5", &nums) // 这样不起作用
  6. fmt.Println(nums)
  7. }

为了使这段代码起作用,你需要将什么作为Sscan的第二个参数传递?

我知道可以传递nums[0],nums[1]...等等,但我更希望只传递一个参数。

英文:

I'm trying to scan a list of integers from a string into an array (or alternatively, a slice)

  1. package main
  2. import "fmt"
  3. func main() {
  4. var nums [5]int
  5. n, _ := fmt.Sscan("1 2 3 4 5", &nums) // doesn't work
  6. fmt.Println(nums)
  7. }

What do I need to pass as second argument to Sscan in order for this to work?

I know I could pass nums[0], nums[1] ... etc., but I'd prefer a single argument.

答案1

得分: 6

我不认为这可以作为一个方便的一行代码来实现。因为Sscan接受...interface{}参数,所以你需要传递一个接口切片,因此需要先将你的数组转换为接口切片:

  1. func main() {
  2. var nums [5]int
  3. // 转换为接口切片
  4. xnums := make([]interface{}, len(nums))
  5. for n := range nums {
  6. xnums[n] = &nums[n]
  7. }
  8. n, err := fmt.Sscan("1 2 3 4 5", xnums...)
  9. if err != nil {
  10. fmt.Printf("field %d: %s\n", n+1, err)
  11. }
  12. fmt.Println(nums)
  13. }

显然,你可以在接口切片中混合不同类型的值,这样可以更容易地扫描更复杂的字符串。对于仅包含以空格分隔的整数,你可能更好地使用strings.Splitbufio.Scanner以及strconv.Atoi

英文:

I don't think this is possible as a convenient one-liner. As Sscan takes ...interface{}, you would need to pass slice of interfaces as well, hence converting your array first:

  1. func main() {
  2. var nums [5]int
  3. // Convert to interfaces
  4. xnums := make([]interface{}, len(nums))
  5. for n := range nums {
  6. xnums[n] = &nums[n]
  7. }
  8. n, err := fmt.Sscan("1 2 3 4 5", xnums...)
  9. if err != nil {
  10. fmt.Printf("field %d: %s\n", n+1, err)
  11. }
  12. fmt.Println(nums)
  13. }

http://play.golang.org/p/1X28J7JJwl

Obviously you could mix different types in your interface array, so it would make the scanning of more complex string easier. For simply space-limited integers, you might be better using strings.Split or bufio.Scanner along with strconv.Atoi.

答案2

得分: 3

为了使其适用于不仅仅是硬编码的字符串,最好使用bufio.Scannerio.Reader接口来完成这个任务:

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io"
  6. "strconv"
  7. "strings"
  8. )
  9. func scanInts(r io.Reader) ([]int, error) {
  10. s := bufio.NewScanner(r)
  11. s.Split(bufio.ScanWords)
  12. var ints []int
  13. for s.Scan() {
  14. i, err := strconv.Atoi(s.Text())
  15. if err != nil {
  16. return ints, err
  17. }
  18. ints = append(ints, i)
  19. }
  20. return ints, s.Err()
  21. }
  22. func main() {
  23. input := "1 2 3 4 5"
  24. ints, err := scanInts(strings.NewReader(input))
  25. if err != nil {
  26. fmt.Println(err)
  27. }
  28. fmt.Println(ints)
  29. }

输出结果:

[1 2 3 4 5]

Playground

英文:

To allow this to work on more than just hard-coded strings, it's probably better to use a bufio.Scanner, and an io.Reader interface to do this:

  1. package main
  2. import (
  3. "bufio"
  4. "fmt"
  5. "io"
  6. "strconv"
  7. "strings"
  8. )
  9. func scanInts(r io.Reader) ([]int, error) {
  10. s := bufio.NewScanner(r)
  11. s.Split(bufio.ScanWords)
  12. var ints []int
  13. for s.Scan() {
  14. i, err := strconv.Atoi(s.Text())
  15. if err != nil {
  16. return ints, err
  17. }
  18. ints = append(ints, i)
  19. }
  20. return ints, s.Err()
  21. }
  22. func main() {
  23. input := "1 2 3 4 5"
  24. ints, err := scanInts(strings.NewReader(input))
  25. if err != nil {
  26. fmt.Println(err)
  27. }
  28. fmt.Println(ints)
  29. }

Produces:

>[1 2 3 4 5]

Playground

答案3

得分: 1

除非你特别想使用Sscann,否则你也可以尝试以下替代方法:

  • 将输入字符串按空格分割
  • 遍历结果数组
  • 将每个字符串转换为整数
  • 将结果值存储到整数切片中

像这样:

  1. package main
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. )
  7. func main() {
  8. nums := make([]int, 0)
  9. for _, s := range strings.Split("1 2 3 4 5", " ") {
  10. i, e := strconv.Atoi(s)
  11. if e != nil {
  12. i = 0 // 如果不是数字,默认为0
  13. }
  14. nums = append(nums, i)
  15. }
  16. fmt.Println(nums)
  17. }

http://play.golang.org/p/rCZl46Ixd4

英文:

Unless you're trying to use Sscann specifically you can also try this as an alternative:

  • split the input string by spaces
  • iterate the resulting array
  • convert each string into an int
  • store the resulting value into an int slice

Like this:

  1. package main
  2. import (
  3. "fmt"
  4. "strconv"
  5. "strings"
  6. )
  7. func main() {
  8. nums := make([]int, 0)
  9. for _, s := range strings.Split("1 2 3 4 5", " ") {
  10. i, e := strconv.Atoi(s)
  11. if e != nil {
  12. i = 0 // that was not a number, default to 0
  13. }
  14. nums = append(nums, i)
  15. }
  16. fmt.Println(nums)
  17. }

http://play.golang.org/p/rCZl46Ixd4

huangapple
  • 本文由 发表于 2015年2月19日 18:58:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/28604563.html
匿名

发表评论

匿名网友

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

确定