Перетворити рядок у цілий тип у 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.