在golang中如何将字符串转换为整数

20
我想在golang中将字符串转换为整数,但我不知道字符串的格式。例如,"10" -> 10"65.0" -> 65"xx" -> 0,"11xx" -> 11,"xx11"->0。
我进行了一些搜索并发现strconv.ParseInt()。但它无法处理"65.0",所以我必须检查字符串的格式。
有更好的方法吗?

2
"65.0" 是一个浮点数,而不是整数。 - elithrar
3
请查看https://dev59.com/dmIk5IYBdhLWcg3wn_f1。 - VonC
为什么不将其解析为浮点数并转换为字符串?或者先尝试整数,然后退而求其次解析为浮点数等? - Not_a_Golfer
1
无法将“11xx”解决为11。 - Li Shen
https://dev59.com/OVwZ5IYBdhLWcg3waPvX - Narendra N
strconv.Atoi("10") 可将字符串转换为整数。 strconv.Itoa(10) 可将整数转换为字符串。请参见:https://dev59.com/OVwZ5IYBdhLWcg3waPvX#62740786。 - user12817546
9个回答

11

我相信你要找的函数是

strconv.ParseFloat()

在这里可以看到示例

但是,这个函数的返回类型是float64。

如果您不需要作为字符串传递的数字的小数部分,则以下函数可以完成该任务:

func StrToInt(str string) (int, error) {
    nonFractionalPart := strings.Split(str, ".")
    return strconv.Atoi(nonFractionalPart[0])
}

此解决方案无法处理“11xx”-> 11和“xx11”-> 0。 - Li Shen
1
这是正确的。从问题中不清楚您是否需要处理像“11xx”-> 11这样的情况,我认为解析整数并留下其他字符不是一个好的做法。 - Mayank Patel
是的,我没有表达清楚我的问题。我会更新它。谢谢! - Li Shen

10

您可以使用以下三个函数将字符串值转换为整数或浮点数。

注意: 必须导入 strconv 内置包才能执行这些函数。

  1. func Atoi(s string) (int, error)
  2. func ParseInt(s string, base int, bitSize int) (i int64, err error)
  3. func ParseFloat(s string, bitSize int) (float64, error)
package main

import (
    "fmt"
    "strconv"
)

func main() {
    i, _ := strconv.Atoi("-42")
    fmt.Println(i)

    j,_ := strconv.ParseInt("-42", 10, 8)
    fmt.Println(j)

    k,_ := strconv.ParseFloat("-42.8", 8)
    fmt.Println(k)
}

5
package main

import "strconv"
import "fmt"

// The built-in package "strconv" provides the number parsing.

// For `ParseInt`, the `0` means infer the base from
// the string. `64` requires that the result fit in 64
// bits.


value, err := strconv.ParseInt("123", 0, 64)
if err != nil {
    panic(err)
}
fmt.Println(value)

参考,请单击此处

如果您希望始终获得相同的内容,也可以传递非零基数(例如10)。


2
我希望你能在golang中将字符串转换为整数。正如你已经提到的,有一个名为strconv.ParseInt的函数可以做到这一点!
但我不知道字符串的格式。
听起来很可怕(和具有挑战性),但是在查看您的示例后,我可以轻松地得出结论,您知道格式,并且问题可以陈述如下:
如何将字符串的初始部分解析为整数?
由于strconv.ParseInt在语法错误时返回0,因此它不适合;至少不是直接适合。但是,如果你提取它,它可以解析你的初始部分。我相信你已经想到了,但这确实是最干净的解决方案:从字符串中提取内容,然后解析它。
您可以通过几种方式提取前导整数,其中之一是使用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

我认为这段代码简单明了地展示了其意图。您还使用了标准的ParseInt,它可以正常工作并提供您所需的所有错误检查。

如果由于任何原因您无法提取前导整数(例如需要快速解析量级为TB的数据,并且您的老板正在催促您立即交付,甚至更早之前,所以请尽快完成),那么我建议您深入研究源代码并修改标准解析器,使其不报告语法错误,而是返回字符串的已解析部分。


2

在@MayankPatel和@DeepakG的优秀答案中,可以将字符串设置为各种数字类型。各种数字类型可以设置为字符串。同样,“true”可以设置为bool类型,true也可以设置为字符串。

package main

import (
    "fmt"
    "strconv"
)

func main() {
    //convert a string to another type
    f, _ := strconv.ParseFloat("70.99", 64)
    i, _ := strconv.Atoi(fmt.Sprintf("%.f", f))
    t, _ := strconv.ParseBool("true")
    c := []interface{}{[]byte("70.99"), f, i, rune(i), t}
    checkType(c) //[]uint8 [55 48 46 57 57], float64 70.99, int 71, int32 71, bool true

    //convert another type to a string
    c = []interface{}{fmt.Sprintf("%s", []byte("70.99")), fmt.Sprintf("%.f", f), strconv.Itoa(i), string(rune(i)), strconv.FormatBool(t)}
    checkType(c) //string 70.99, string 71, string 71, string G, string true
}

func checkType(s []interface{}) {
    for k, _ := range s {
        fmt.Printf("%T %v\n", s[k], s[k])
    }
}

一个字符串类型代表了一系列的字符串值。一个字符串值是一个(可能为空的)字节序列。字节数被称为字符串长度,它永远不会是负数。字符串是不可变的。查看https://Golang.org/ref/spec#String_types
以下是三种将字符串解析为整数的方法,从最快到最慢:1. strconv.ParseInt(...) 最快 2. strconv.Atoi(...) 仍然非常快 3. fmt.Sscanf(...) 不是特别快,但最灵活。查看https://dev59.com/bW855IYBdhLWcg3wilCD#47317150
避免将字符串转换为[]byte:b := []byte(s)。它分配了一个新的内存空间并将整个内容复制到其中。查看https://dev59.com/zGox5IYBdhLWcg3wFAU1#52943136。查看https://dev59.com/5J3ha4cB1Zd3GeqPa-H2#41460993。引号已经编辑过。

布尔型、数值型或字符串型可以设置为另一种类型。有关[]byte的信息,请参见https://dev59.com/CmIk5IYBdhLWcg3wfOSe#62725637;有关`float64`的信息,请参见https://dev59.com/XlsW5IYBdhLWcg3wT155#62753031;有关`int`的信息,请参见https://dev59.com/e2Yr5IYBdhLWcg3w0taE#62737936;有关`[]rune`的信息,请参见https://dev59.com/XJrga4cB1Zd3GeqPiSNs#62739051;有关`bool`的信息,请参见https://dev59.com/Y2oy5IYBdhLWcg3wq_7O#62726854。 - user12817546

1

从字符串开头提取整数是我经常做的事情之一。在C语言中,您可以使用atoi()或strtol()函数。令人惊讶的是,Go语言没有标准库函数来执行此操作。不管怎样,这里是我刚刚写的一个函数:

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

如果您想处理负整数,您需要进行一些小的修复。


除了检查前导负号外,您可能首先想要跳过前导空格,以确保完整性。我将这留作练习。 - Andrew W. Phillips

1
你可以编写一个FieldsFunc来解析并单独获取数字值。

在这里播放

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

这里的输出是:
10 10
65.0 65
xx 0
11xx 11
xx11 11

请注意,xx11的最后一个条件将其处理为11。

0

我的当前解决方案是:

// Convert string to integer in best effort.                                                                                
 // TODO: handle overflow and add unittest                                                                                   
func StrToInt(str string) (int64, error) {                                                                                  
    if len(str) == 0 {                                                                                                      
        return 0, nil                                                                                                       
     }                                                                                                                       
     negative := false                                                                                                       
     i := 0                                                                                                                  
     if str[i] == '-' {                                                                                                      
         negative = true                                                                                                     
         i++                                                                                                                 
     } else if str[i] == '+' {                                                                                               
         i++                                                                                                                 
     }                                                                                                                       
     r := int64(0)                                                                                                           
     for ; i < len(str); i++ {                                                                                             
         if unicode.IsDigit(rune(str[i])) {                                                                                  
             r = r*10 + int64(str[i]-'0')                                                                                    
         } else {
             break
          }                                                                                                                   
     }                                                                                                                       
     if negative {                                                                                                           
         r = -r                                                                                                              
     }                                                                                                                       
     // TODO: if i < len(str), we should return error                                                                        
     return r, nil                                                                                                           
 }    

您正在使用字节循环遍历str,但却将其与符文进行比较。我建议使用for _, r := range str[i:]通过符文循环遍历字符串(或者不要关注Unicode,直接测试ASCII 0和9的字面值)。 - Dave C
在我看来,如果你想要一个API能够在解析到一半时停止并忽略尾随字符,那么该API应该返回已消耗/解析的字节数或输入中剩余未解析部分(当然还要包括现有的返回值)。 - Dave C

0
import (
  "strconv"
  "strings"
)

func StrToInt(str string) int {
  // Delete any non-numeric character from the string
  str = strings.TrimFunc(str, func(r rune) bool {
      return r < '0' || r > '9'
  })

  // Convert the cleaned-up string to an integer
  n, _ := strconv.Atoi(str)
  return n
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接