【问题标题】:Golang converting from rune to stringGolang 从符文转换为字符串
【发布时间】:2016-08-31 09:22:06
【问题描述】:

我有以下代码,它应该将rune 转换为string 并打印出来。但是,打印时我得到了未定义的字符。我无法弄清楚错误在哪里:

package main

import (
    "fmt"
    "strconv"
    "strings"
    "text/scanner"
)

func main() {
    var b scanner.Scanner
    const a = `a`
    b.Init(strings.NewReader(a))
    c := b.Scan()
    fmt.Println(strconv.QuoteRune(c))
}

【问题讨论】:

标签: string parsing go unicode rune


【解决方案1】:

那是因为您使用 Scanner.Scan() 来读取 rune 但它做了其他事情。 Scanner.Scan() 可用于读取由Scanner.Mode 位掩码控制的特殊令牌的tokensrunes,它从text/scanner 包返回特殊常量,而不是读取符文本身。

要读取单个rune,请改用Scanner.Next()

c := b.Next()
fmt.Println(c, string(c), strconv.QuoteRune(c))

输出:

97 a 'a'

如果您只想将单个rune 转换为string,请使用简单类型conversionruneint32 的别名,将整数转换为string

将有符号或无符号整数值转换为字符串类型会生成一个包含整数的 UTF-8 表示形式的字符串。

所以:

r := rune('a')
fmt.Println(r, string(r))

输出:

97 a

还可以循环遍历 string 值的符文,您可以简单地使用 for ... range 构造:

for i, r := range "abc" {
    fmt.Printf("%d - %c (%v)\n", i, r, r)
}

输出:

0 - a (97)
1 - b (98)
2 - c (99)

或者您可以简单地将string 值转换为[]rune

fmt.Println([]rune("abc")) // Output: [97 98 99]

还有utf8.DecodeRuneInString()

试试Go Playground上的例子。

注意:

您的原始代码(使用Scanner.Scan())的工作方式如下:

  1. 您调用了 Scanner.Init(),它将模式 (b.Mode) 设置为 scanner.GoTokens
  2. 在输入上调用Scanner.Scan()(来自"a")返回scanner.Ident,因为"a"是一个有效的Go标识符:

    c := b.Scan()
    if c == scanner.Ident {
        fmt.Println("Identifier:", b.TokenText())
    }
    
    // Output: "Identifier: a"
    

【讨论】:

    【解决方案2】:

    我知道我参加聚会有点晚了,但这里有一个 []rune to string 函数:

    func runesToString(runes []rune) (outString string) {
        // don't need index so _
        for _, v := range runes {
            outString += string(v)
        }
        return
    }
    

    是的,有一个命名返回,但我认为在这种情况下没关系,因为它减少了行数并且函数很短

    【讨论】:

    • []runestring 的转换是由规范原生支持的,这完全没有必要而且速度很慢。而是使用简单的转换:outString := string(runes)
    • @icza 启发性的评论。我在这里引用了你stackoverflow.com/a/62739051/12817546
    【解决方案3】:

    自从我来这个问题搜索 rune 和 string 和 char 以来,认为这可能会帮助像我这样的新手

    // str := "aഐbc"
    // testString(str)
    func testString(oneString string){
    
        //string to byte slice - No sweat -just type cast it
        // As string  IS A byte slice
        var twoByteArr []byte = []byte(oneString)
    
        // string to rune Slices - No sweat 
        // string IS A slice of runes 
        var threeRuneSlice []rune = []rune(oneString)
    
       // Hmm! String seems to have a dual personality it is both a slice of bytes and
       // a slice of runes - yeah - read on
        
        // A rune slice can be convered to string -
        // No sweat - as string == rune slice
        var thrirdString string = string(threeRuneSlice)
        
        // There is a catch here and that is in printing "characters", using for loop and range 
        
        fmt.Println("Chars in oneString")
        for i,r := range oneString {
            fmt.Printf(" %d  %v  %c ",i,r,r) //you may not get index 0,1,2,3 here  
            // since the range runs specially over strings  https://blog.golang.org/strings
        }
        
        fmt.Println("\nChars in threeRuneSlice")
        for i,r := range threeRuneSlice {
            fmt.Printf(" %d  %v  %c ",i,r,r) // i = 0,1,2,4 , perfect!!
            // as runes are made up of 4 bytes (rune is int32 and byte in unint8
            // and a set of bytes is used to represent a rune which is used to 
           // represent  UTF characters == the REAL CHARECTER 
        }
    
        fmt.Println("\nValues in oneString ")
        for j := 0; j < len(oneString); j++ {
            fmt.Printf(" %d %v ",j,oneString[j]) // No you cannot get charecters if you iterate through string in this way
            // as you are going over bytes here - not runes
        }
        fmt.Println("\nValues in twoByteArr")
        for j := 0; j < len(twoByteArr); j++ {
            fmt.Printf(" %d=%v ",j,twoByteArr[j]) // == same as above
        }
        
        fmt.Printf("\none - %s, two %s, three %s\n",oneString,twoByteArr,thrirdString)
    }
    

    还有一些毫无意义的演示 https://play.golang.org/p/tagRBVG8k7V 改编自https://groups.google.com/g/golang-nuts/c/84GCvDBhpbg/m/Tt6089MPFQAJ

    显示“字符”根据 unicode 代码点编码为 1 到最多 4 个字节

    【讨论】:

      【解决方案4】:

      这个简单的代码可以将符文转换为字符串

      s := fmt.Sprintf("%c", rune)
      

      【讨论】:

        猜你喜欢
        • 2014-02-27
        • 2018-10-08
        • 1970-01-01
        • 2017-09-25
        • 2017-06-05
        • 1970-01-01
        • 2011-09-22
        • 2019-05-03
        • 2017-01-19
        相关资源
        最近更新 更多