गो में पूर्णांक प्रकार में स्ट्रिंग बदलें?


236

मैं एक स्ट्रिंग flag.Arg(n)को एक से लौटाने की कोशिश कर रहा हूं int। गो में ऐसा करने का मुहावरेदार तरीका क्या है?

जवाबों:


298

उदाहरण के लिए,

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() { ... }कोई तर्क नहीं लेता है और कोई मूल्य नहीं देता है। osपैकेज Exitफ़ंक्शन का उपयोग करें जैसेos.Exit(2).
पीटर

2
वैकल्पिक रूप से सिर्फ एक घातक एग करते हैंpanic(err)
पीटर बेंग्टसन

70

सरल तारों को परिवर्तित करना

इसका उपयोग करने का सबसे आसान तरीका है strconv.Atoi() फ़ंक्शन करना।

ध्यान दें कि कई अन्य तरीके हैं। उदाहरण के लिए fmt.Sscan()और strconv.ParseInt()जो अधिक से अधिक लचीलापन देते हैं क्योंकि आप उदाहरण के लिए आधार और बिट्स निर्दिष्ट कर सकते हैं। के प्रलेखन में भी उल्लेख किया strconv.Atoi():

Atoi ParseInt (s, 10, 0) के बराबर है, जिसे int टाइप किया गया है।

यहां दिए गए फ़ंक्शंस का उपयोग करके एक उदाहरण दिया गया है (इसे 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)
}

आउटपुट (यदि तर्क के साथ कहा जाता है "123"):

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

कस्टम स्ट्रिंग पार्स करना

एक ऐसा काम भी है fmt.Sscanf()जो प्रारूप स्ट्रिंग के साथ और भी अधिक लचीलापन देता है string। आप इनपुट में अतिरिक्त अतिरिक्त वर्णों के साथ संख्या प्रारूप (जैसे चौड़ाई, आधार आदि) निर्दिष्ट कर सकते हैं ।

यह एक नंबर पकड़े हुए कस्टम स्ट्रिंग को पार्स करने के लिए बहुत अच्छा है। उदाहरण के लिए यदि आपका इनपुट एक ऐसे रूप में प्रदान किया गया है "id:00123"जहाँ आपके पास एक उपसर्ग है "id:"और संख्या 5 अंक तय है, तो यदि इसे छोटा किया जाता है, तो इसे बहुत आसानी से पार्स करने योग्य है।

s := "id:00123"

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

ParseIntनिर्दिष्ट करने के लिए दूसरा तर्क क्या है ?
कौशिक94

1
@ kaushik94 strconv.ParseInt()लिंक पर क्लिक करें और आप तुरंत देखेंगे ParseInt(s string, base int, bitSize int):। तो यह आधार है: "ParseInt दिए गए आधार में एक स्ट्रिंग s की व्याख्या करता है (2 से 36)"
icza

ध्यान दें कि strSvv.arseInt () के बिट्साइज़ तर्क को स्ट्रिंग को आपकी पसंद के प्रकार में नहीं बदला जाएगा, लेकिन इसके बजाय केवल एक विशिष्ट 'बिटनेस' के लिए परिणाम को सीमित करना है। इन्हें भी देखें: stackoverflow.com/questions/55925894/…
viv

@viv हाँ, यह सही है। यदि प्रकार intका एक मूल्य आवश्यक है औरstrconv.ParseInt() प्रयोग किया जाता है, मैनुअल प्रकार रूपांतरण (से की जरूरत है int64करने के लिए int)।
आईसीजे

16

सबसे तेजी से क्रम से सबसे धीमी गति से तार में पार्स करने के तीन तरीके हैं:

  1. strconv.ParseInt(...) सबसे तेजी से
  2. strconv.Atoi(...) अभी भी बहुत तेज है
  3. fmt.Sscanf(...) बहुत तेज़ नहीं है लेकिन सबसे अधिक लचीला है

यहां एक बेंचमार्क है जो प्रत्येक फ़ंक्शन के लिए उपयोग और उदाहरण समय दिखाता है:

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

आप इसे चलाने atoi_test.goऔर चलाने के रूप में सहेज कर रख सकते हैं 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


0

यदि आप इनपुट डेटा को नियंत्रित करते हैं, तो आप मिनी संस्करण का उपयोग कर सकते हैं

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

सबसे तेज़ विकल्प (यदि आवश्यक हो तो अपना चेक लिखें)। परिणाम :

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
क्या ? वास्तव में ? "गो" लिखने वाले लोगों ने बहुत आसान बना दिया। अपना पहिया न
चलाएं

अटोई के बारे में क्या है ("- 9999")?
ओलेक्सी चेचेल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.