wake-up-neo.com

Konvertieren Sie String in Ganzzahl in Go?

Ich versuche, eine von flag.Arg(n) zurückgegebene Zeichenfolge in eine int zu konvertieren. Was ist der idiomatische Weg, dies in Go zu tun?

191
Matt Joiner

Zum Beispiel,

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)
}
238
peterSO

Einfache Strings konvertieren

Die einfachste Möglichkeit ist die Verwendung der Funktion strconv.Atoi() .

Beachten Sie, dass es viele andere Möglichkeiten gibt. Zum Beispiel fmt.Sscan() und strconv.ParseInt() , die größere Flexibilität bieten, da Sie beispielsweise Basis und Bitgröße angeben können. Wie auch in der Dokumentation von strconv.Atoi() erwähnt:

Atoi ist die Abkürzung für ParseInt (s, 10, 0).

Hier ein Beispiel mit den genannten Funktionen (probieren Sie es auf dem Go Playground ):

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)
}

Ausgabe (wenn mit Argument "123" aufgerufen):

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

Analysieren von benutzerdefinierten Zeichenfolgen

Es gibt auch ein praktisches fmt.Sscanf() , das eine noch größere Flexibilität bietet, da Sie mit dem Formatstring das Zahlenformat (wie Breite, Basis usw.) sowie zusätzliche zusätzliche Zeichen in der Eingabe string angeben können.

Dies ist ideal zum Analysieren von benutzerdefinierten Zeichenfolgen, die eine Zahl enthalten. Wenn Ihre Eingabe beispielsweise in einer Form von "id:00123" bereitgestellt wird, in der Sie ein Präfix "id:" haben, und die Zahl 5 Ziffern lang ist, die mit Nullen aufgefüllt werden, wenn dies kürzer ist, lässt sich dies sehr leicht so analysieren:

s := "id:00123"

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

Es gibt drei Möglichkeiten, Strings in Ganzzahlen zu parsen, von der schnellsten zur langsamsten:

  1. strconv.ParseInt(...) am schnellsten
  2. strconv.Atoi(...) immer noch sehr schnell
  3. fmt.Sscanf(...) nicht besonders schnell aber flexibel

Hier ist ein Benchmark, der die Verwendung und das Beispiel für das Timing für jede Funktion zeigt:

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)
    }
  }
}

Sie können es ausführen, indem Sie als atoi_test.go speichern und go test -bench=. atoi_test.go ausführen.

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
11
maerics

Versuche dies

import ("strconv")

value : = "123"
number,err := strconv.ParseUint(value, 10, 32)
0
MD.Mahedi hasan

Wenn Sie die Eingabedaten steuern, können Sie die Miniversion verwenden

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
    }   
}

die schnellste Option (schreiben Sie ggf. einen Scheck). Ergebnis:

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
0
Jenyokcoder