Перетворити рядок у цілий тип у Go?


Відповіді:


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).
peterSO

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?
kaushik94

1
@ Kaushik94 Натисніть на strconv.ParseInt()посилання , і ви побачите відразу: ParseInt(s string, base int, bitSize int). Отже, це основа: "ParseInt інтерпретує рядок s у даній базі (від 2 до 36)"
icza

Зауважте, що аргумент bitSize в strconv.ParseInt () не буде перетворювати рядок у ваш вибір типу, а натомість є лише для обмеження результату певним "бітом". Дивіться також: 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 та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.