Je veux convertir une chaîne en entier en golang. Mais je ne connais pas le format de chaîne. Par exemple, "10"
-> 10
, "65.0"
-> 65
, "xx"
-> 0
, "11xx" -> 11, "xx11" -> 0
Je fais des recherches et trouve strconv.ParseInt()
. Mais il ne peut pas gérer "65.0"
. Je dois donc vérifier le format de la chaîne.
Y a-t-il un meilleur moyen?
Je crois que la fonction que vous recherchez est
strconv.ParseFloat()
voir exemple ici
Mais le type de retour de cette fonction est float64.
Si vous n'avez pas besoin d'une fraction du nombre passé en tant que fonction suivante, la fonction suivante fera le travail:
func StrToInt(str string) (int, error) {
nonFractionalPart := strings.Split(str, ".")
return strconv.Atoi(nonFractionalPart[0])
}
package main
import "strconv"
import "fmt"
// The built-in package "strconv" provides the number parsing.
//For `ParseInt`, the `10` means infer the base from
// the string. `64` requires that the result fit in 64
// bits.
value, err := strconv.ParseInt("123", 10, 64)
if err != nil {
panic(err)
}
fmt.Println(value)
Je veux convertir une chaîne en entier en golang.
Comme vous l'avez déjà mentionné, il existe une fonction strconv.ParseInt
qui fait exactement cela!
Mais je ne connais pas le format de chaîne.
Cela semble effrayant (et stimulant), mais après avoir examiné vos exemples, je peux facilement en conclure que vous connaissez le format et que le problème peut être énoncé comme suit:
Comment puis-je analyser une partie initiale d'une chaîne comme un entier?
Comme strconv.ParseInt
renvoie 0 en cas d'erreur de syntaxe, cela ne convient pas; du moins pas directement. Mais il peut analyser votre portion initiale si vous extraire il. Je suis sûr que vous l'avez déjà compris, mais c'est vraiment la solution la plus propre: extrayez votre contenu de la chaîne, analysez-le.
Vous pouvez extraire le premier entier de plusieurs façons, l'une d'entre elles consiste à utiliser regexp
:
package main
import (
"fmt"
"regexp"
"strconv"
)
// Extract what you need
var leadingInt = regexp.MustCompile(`^[-+]?\d+`)
func ParseLeadingInt(s string) (int64, error) {
s = leadingInt.FindString(s)
if s == "" { // add this if you don't want error on "xx" etc
return 0, nil
}
return strconv.ParseInt(s, 10, 64)
}
func main() {
for _, s := range []string{"10", "65.0", "xx", "11xx", "xx11"} {
i, err := ParseLeadingInt(s)
fmt.Printf("%s\t%d\t%v\n", s, i, err)
}
}
_ { http://play.golang.org/p/d7sS5_WpLj } _
Je crois que ce code est simple et démontre clairement les intentions. Vous utilisez également la variable ParseInt
standard qui fonctionne et vous fournit toutes les vérifications d'erreur dont vous avez besoin.
Si, pour une raison quelconque, vous ne pouvez pas vous permettre d'extraire l'entier principal (vous avez besoin d'une analyse rapide de téraoctets de données et votre patron vous crie dessus, ils en ont besoin maintenant maintenant et mieux hier, alors courbez le temps et livrez-le: sifflement :) Je suggère de plonger dans le code source } et de modifier l’analyseur standard afin de ne pas signaler les erreurs de syntaxe, mais de renvoyer une partie analysée de la chaîne.
Extraire un int depuis le début d'une chaîne est l'une des choses les plus courantes que je fais. En C, vous pouvez utiliser atoi () ou strtol (). C'est ridicule que Go n'ait pas de fonction de bibliothèque std pour le faire. En tout cas en voici un que je viens de retrousser
// strToInt gets the integer from the start of the string.
// It returns the value and the offset of the first non-digit.
func StrToInt(s string) (v int, offset int) {
offset = strings.IndexFunc(s, func(r rune) bool { return r < '0' || r > '9' })
if offset == -1 { offset = len(s) }
if offset == 0 { return } // Avoid Atoi on empty string
v, _ = strconv.Atoi(s[:offset])
return
}
Vous aurez besoin d'une légère réparation si vous voulez gérer -ve entier.
Vous pouvez écrire une FieldsFunc
pour analyser et obtenir les valeurs numériques seules séparément.
package main
import (
"fmt"
"strconv"
"strings"
"unicode"
)
func stripNonIntFloat(s string) string {
f := func(c rune) bool {
return !unicode.IsNumber(c) && (c != 46)
}
output := strings.FieldsFunc(s, f)
if len(output) > 0 {
return output[0]
} else {
return ""
}
}
func main() {
strList := []string{"10", "65.0", "xx", "11xx", "xx11"}
for i := 0; i < len(strList); i++ {
s := stripNonIntFloat(strList[i])
v, err := strconv.ParseFloat(s, 10)
if err != nil {
fmt.Println(strList[i], 0)
} else {
fmt.Println(strList[i], v)
}
}
}
La sortie ici est
10 10
65.0 65
xx 0
11xx 11
xx11 11
Notez que votre dernière condition de xx11 le traite en tant que 11.