Go'da dize tamsayı türüne dönüştürülsün mü?


236

Ben dönen bir dize dönüştürmek için çalışıyorum flag.Arg(n)bir etmek int. Go'da bunu yapmanın deyimsel yolu nedir?

Yanıtlar:


298

Örneğin,

package main

import (
    "flag"
    "fmt"
    "os"
    "strconv"
)

func main() {
    flag.Parse()
    s := flag.Arg(0)
    // string to int
    i, err := strconv.Atoi(s)
    if err != nil {
        // handle error
        fmt.Println(err)
        os.Exit(2)
    }
    fmt.Println(s, i)
}

14
func main() { ... }argüman almaz ve değer döndürmez. osPaket Exitişlevini kullanın örn.os.Exit(2).
peterSO

2
Alternatif olarak sadece ölümcül bir eg yapınpanic(err)
Peter Bengtsson

70

Basit dizeleri dönüştürme

En kolay yol strconv.Atoi()işlevi kullanmaktır .

Başka birçok yol olduğunu unutmayın. Örneğin fmt.Sscan()ve örneğin strconv.ParseInt()tabanı ve bit boyutunu belirtebileceğiniz gibi daha fazla esneklik sağlar. Ayrıca belgelerinde belirtildiği gibi strconv.Atoi():

Atoi, int türüne dönüştürülen ParseInt (s, 10, 0) ile eşdeğerdir.

Bahsedilen işlevleri kullanan bir örnek ( Go Playground'da deneyin ):

flag.Parse()
s := flag.Arg(0)

if i, err := strconv.Atoi(s); err == nil {
    fmt.Printf("i=%d, type: %T\n", i, i)
}

if i, err := strconv.ParseInt(s, 10, 64); err == nil {
    fmt.Printf("i=%d, type: %T\n", i, i)
}

var i int
if _, err := fmt.Sscan(s, &i); err == nil {
    fmt.Printf("i=%d, type: %T\n", i, i)
}

Çıktı (bağımsız değişken ile çağrılırsa "123"):

i=123, type: int
i=123, type: int64
i=123, type: int

Özel dizeleri ayrıştırma

fmt.Sscanf()Biçim dizgisinde sayı biçimini (genişlik, taban vb. Gibi) belirtebileceğiniz gibi daha fazla esneklik sağlayan kullanışlı bir özellik de vardır .string .

Bu, bir sayı tutan özel dizeleri ayrıştırmak için mükemmeldir. Örneğin , girdiniz "id:00123"bir ön ekin olduğu bir biçimde sağlanmışsa "id:"ve sayı 5 basamaklıysa, daha kısasa sıfırlarla doldurulmuşsa, bu çok kolay bir şekilde ayrıştırılabilir:

s := "id:00123"

var i int
if _, err := fmt.Sscanf(s, "id:%5d", &i); err == nil {
    fmt.Println(i) // Outputs 123
}

İkinci argüman ne ParseIntbelirtiyor?
kaushik94

1
@ kaushik94 tıklayın strconv.ParseInt()bağlantısını ve hemen göreceksiniz: ParseInt(s string, base int, bitSize int). Yani bu temel: "ParseInt verilen tabanda bir dizeyi (2 - 36) yorumlar"
icza

Strconv.ParseInt () için bitSize bağımsız değişkeninin, dizeyi tür seçiminize dönüştürmeyeceğini, yalnızca sonucu belirli bir 'bitness' ile sınırlamak için olduğunu unutmayın. Ayrıca bakınız: stackoverflow.com/questions/55925894/…
viv

@viv Evet, doğru. Türde bir değer ise intgereklidir ve strconv.ParseInt()kullanılan, el tür dönüşüm (ihtiyaç duyulmaktadır int64için int).
icza

16

En hızlı çalışma zamanından en yavaşına kadar dizeleri tamsayılara ayrıştırmanın üç yolu şunlardır:

  1. strconv.ParseInt(...) En hızlı
  2. strconv.Atoi(...) hala çok hızlı
  3. fmt.Sscanf(...) çok hızlı değil ama en esnek

Aşağıda, her bir işlev için kullanım ve örnek zamanlamayı gösteren bir karşılaştırma ölçütü bulunmaktadır:

package main

import "fmt"
import "strconv"
import "testing"

var num = 123456
var numstr = "123456"

func BenchmarkStrconvParseInt(b *testing.B) {
  num64 := int64(num)
  for i := 0; i < b.N; i++ {
    x, err := strconv.ParseInt(numstr, 10, 64)
    if x != num64 || err != nil {
      b.Error(err)
    }
  }
}

func BenchmarkAtoi(b *testing.B) {
  for i := 0; i < b.N; i++ {
    x, err := strconv.Atoi(numstr)
    if x != num || err != nil {
      b.Error(err)
    }
  }
}

func BenchmarkFmtSscan(b *testing.B) {
  for i := 0; i < b.N; i++ {
    var x int
    n, err := fmt.Sscanf(numstr, "%d", &x)
    if n != 1 || x != num || err != nil {
      b.Error(err)
    }
  }
}

Farklı kaydedip atoi_test.goçalıştırarak çalıştırabilirsiniz go test -bench=. atoi_test.go.

goos: darwin
goarch: amd64
BenchmarkStrconvParseInt-8      100000000           17.1 ns/op
BenchmarkAtoi-8                 100000000           19.4 ns/op
BenchmarkFmtSscan-8               2000000          693   ns/op
PASS
ok      command-line-arguments  5.797s

2

Bunu dene

import ("strconv")

value : = "123"
number,err := strconv.ParseUint(value, 10, 32)

0

Giriş verilerini kontrol ederseniz mini versiyonu kullanabilirsiniz

package main

import (
    "testing"
    "strconv"
)

func Atoi (s string) int {
    var (
        n uint64
        i int
        v byte
    )   
    for ; i < len(s); i++ {
        d := s[i]
        if '0' <= d && d <= '9' {
            v = d - '0'
        } else if 'a' <= d && d <= 'z' {
            v = d - 'a' + 10
        } else if 'A' <= d && d <= 'Z' {
            v = d - 'A' + 10
        } else {
            n = 0; break        
        }
        n *= uint64(10) 
        n += uint64(v)
    }
    return int(n)
}

func BenchmarkAtoi(b *testing.B) {
    for i := 0; i < b.N; i++ {
        in := Atoi("9999")
        _ = in
    }   
}

func BenchmarkStrconvAtoi(b *testing.B) {
    for i := 0; i < b.N; i++ {
        in, _ := strconv.Atoi("9999")
        _ = in
    }   
}

en hızlı seçenek (gerekirse çekinizi yazın). Sonuç:

Path>go test -bench=. atoi_test.go
goos: windows
goarch: amd64
BenchmarkAtoi-2                 100000000               14.6 ns/op
BenchmarkStrconvAtoi-2          30000000                51.2 ns/op
PASS
ok      path     3.293s

1
Ne ? Gerçekten mi ? "Git" yazan insanlar çok kolaylaştı. Direksiyonunuzu döndürmeyin :)
Balaji Boggaram Ramanarayan

Atoi ("- 9999") ne olacak?
Oleksiy Chechel
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.