前言:
此刻同学们对“c语言中string是什么”大体比较看重,同学们都想要知道一些“c语言中string是什么”的相关知识。那么小编也在网摘上汇集了一些对于“c语言中string是什么””的相关内容,希望小伙伴们能喜欢,姐妹们快快来了解一下吧!字符串在 Go 中值得特别提及,因为与其他语言相比,它们在实现上是不同的。
什么是string?
字符串string在Go中是一个bytes类型的切片。通过双引号创建字符串string。
name := "Hello World"
Go 中的字符串符合 Unicode 标准,并且采用 UTF-8编码。
访问字符串的单个字节
由于字符串是bytes类型的切片,所以完全可以访问字符串的每个字节。
package mainimport ( "fmt")func printBytes(s string) { fmt.Printf("Bytes: ") for i := 0; i < len(s); i++ { fmt.Printf("%x ", s[i]) }}func main() { name := "Hello World" fmt.Printf("String: %s\n", name) printBytes(name)}
%s 是打印字符串的格式说明符。在第16行中,打印输入字符串。第9行中,len(s)返回字符串中的字节数,我们使用 for 循环以十六进制表示法打印这些字节。%x 是十六进制的格式说明符。以上程序输出,
String: Hello World Bytes: 48 65 6c 6c 6f 20 57 6f 72 6c 64访问字符串的单个字符
让我们简单修改上面的程序来打印字符串的字符。
package mainimport ( "fmt")func printBytes(s string) { fmt.Printf("Bytes: ") for i := 0; i < len(s); i++ { fmt.Printf("%x ", s[i]) }}func printChars(s string) { fmt.Printf("Characters: ") for i := 0; i < len(s); i++ { fmt.Printf("%c ", s[i]) }}func main() { name := "Hello World" fmt.Printf("String: %s\n", name) printChars(name) fmt.Printf("\n") printBytes(name)}
上面程序中的第17行,printChars函数%c格式符用来打印字符串中的字符。会有如下打印:
String: Hello World Characters: H e l l o W o r l d Bytes: 48 65 6c 6c 6f 20 57 6f 72 6c 64
尽管上述程序看起来像是访问字符串各个字符的合法方法,但这有一个严重的bug。让我们找出该bug是什么。
package mainimport ( "fmt")func printBytes(s string) { fmt.Printf("Bytes: ") for i := 0; i < len(s); i++ { fmt.Printf("%x ", s[i]) }}func printChars(s string) { fmt.Printf("Characters: ") for i := 0; i < len(s); i++ { fmt.Printf("%c ", s[i]) }}func main() { name := "Hello World" fmt.Printf("String: %s\n", name) printChars(name) fmt.Printf("\n") printBytes(name) fmt.Printf("\n\n") name = "Señor" fmt.Printf("String: %s\n", name) printChars(name) fmt.Printf("\n") printBytes(name)}
上面的程序输出,
String: Hello World Characters: H e l l o W o r l d Bytes: 48 65 6c 6c 6f 20 57 6f 72 6c 64 String: Señor Characters: S e à ± o r Bytes: 53 65 c3 b1 6f 72
在上面程序的第30行中,我们尝试打印Señor的字符,它输出S e à ± o r这是错误的。为什么这个程序在Señor中中断,而它对 Hello World 来说效果很好。原因是ñ的 Unicode 码位是 U+00F1,其 UTF-8编码占用2个字节c3 和b1。我们尝试打印字符,假设每个代码点将是一个字节长,这是错误的。在 UTF-8编码中,一个码位可以占用1个以上的字节。那么我们如何解决这个问题呢?这就是Rune拯救我们的地方。
Rune
rune是Go中的内置类型,它是int32的别名。Rune表示Go中的 Unicode 码位。无论代码点占用多少字节,它都可以用rune表示。让我们修改上面的程序以使用rune打印字符,
package mainimport ( "fmt")func printBytes(s string) { fmt.Printf("Bytes: ") for i := 0; i < len(s); i++ { fmt.Printf("%x ", s[i]) }}func printChars(s string) { fmt.Printf("Characters: ") runes := []rune(s) for i := 0; i < len(runes); i++ { fmt.Printf("%c ", runes[i]) }}func main() { name := "Hello World" fmt.Printf("String: %s\n", name) printChars(name) fmt.Printf("\n") printBytes(name) fmt.Printf("\n\n") name = "Señor" fmt.Printf("String: %s\n", name) printChars(name) fmt.Printf("\n") printBytes(name)}
在上面程序的第16行中,字符串被转换为一rune切片。然后我们循环它并显示字符。该程序打印,
String: Hello World Characters: H e l l o W o r l d Bytes: 48 65 6c 6c 6f 20 57 6f 72 6c 64 String: Señor Characters: S e ñ o r Bytes: 53 65 c3 b1 6f 72使用for range循环访问rune
上面的程序是迭代字符串的各个rune的完美方法。但是 Go 为我们提供了一种更简单的方法来使用 for range循环来做到这一点。
package mainimport ( "fmt")func charsAndBytePosition(s string) { for index, rune := range s { fmt.Printf("%c starts at byte %d\n", rune, index) }}func main() { name := "Señor" charsAndBytePosition(name)}
在上面程序的第8行中,字符串使用 for range 循环进行迭代。循环返回rune与rune一起开始的字节的位置。此程序输出,
S starts at byte 0 e starts at byte 1 ñ starts at byte 2o starts at byte 4 r starts at byte 5
从上面的例子可以看出,ñ占两个字节,由于下一个字符o从byte 4开始而不是3。
从一个bytes切片创建字符串
package mainimport ( "fmt")func main() { byteSlice := []byte{0x43, 0x61, 0x66, 0xC3, 0xA9} str := string(byteSlice) fmt.Println(str)}
上面程序第8行中的 byteSlice 包含字符串Café的UTF-8 编码十六进制字节。程序打印,
Café
如果我们有十六进制值的十进制等效值会怎么样?上述程序会起作用吗?一起来看看吧。
package mainimport ( "fmt")func main() { byteSlice := []byte{67, 97, 102, 195, 169}// {'\x43', '\x61', '\x66', '\xC3', '\xA9'} str := string(byteSlice) fmt.Println(str)}
十进制值也有效,上面的程序也将打印Café。
从rules切片创建字符串
package mainimport ( "fmt")func main() { runeSlice := []rune{0x0053, 0x0065, 0x00f1, 0x006f, 0x0072} str := string(runeSlice) fmt.Println(str)}
在上面的程序中,runeSlice 包含十六进制字符串 Señor 的 Unicode 码位。程序输出,
Señor字符串的长度
utf8包的RuneCountInString(s string) (n int) 函数可用于查找字符串的长度。此方法将字符串作为参数,并返回其中的runes数。
len(s)用于查找字符串中的字节数,并且不返回字符串长度。正如我们已经讨论过的,某些 Unicode 字符的代码点占用超过1个字节。使用 len 找出这些字符串的长度将返回不正确的字符串长度。
package mainimport ( "fmt" "unicode/utf8")func main() { word1 := "Señor" fmt.Printf("String: %s\n", word1) fmt.Printf("Length: %d\n", utf8.RuneCountInString(word1)) fmt.Printf("Number of bytes: %d\n", len(word1)) fmt.Printf("\n") word2 := "Pets" fmt.Printf("String: %s\n", word2) fmt.Printf("Length: %d\n", utf8.RuneCountInString(word2)) fmt.Printf("Number of bytes: %d\n", len(word2))}
上面的程序输出,
String: Señor Length: 5 Number of bytes: 6String: Pets Length: 4 Number of bytes: 4字符串比较
==操作符常用于比较两个字符串是否相等。
package mainimport ( "fmt")func compareStrings(str1 string, str2 string) { if str1 == str2 { fmt.Printf("%s and %s are equal\n", str1, str2) return } fmt.Printf("%s and %s are not equal\n", str1, str2)}func main() { string1 := "Go" string2 := "Go" compareStrings(string1, string2) string3 := "hello" string4 := "world" compareStrings(string3, string4)}
在上面的 compareString 函数中,第8行使用 == 运算符比较两个字符串 str1 和 str2 是否相等。如果它们相等,则打印相应的消息,函数返回。上面的程序打印,
Go and Go are equal hello and world are not equal字符串拼接
Go中有多种方式进行字符串的拼接,让我们一一看一下。
最简单的方式用来拼接字符串是+运算符。
package mainimport ( "fmt")func main() { string1 := "Go" string2 := "is awesome" result := string1 + " " + string2 fmt.Println(result)}
上面的程序中,string1和string2中间隔个空字符进行拼接,打印,
Go is awesome
第二种方式是用fmt包中的Spintf函数。
Sprintf 函数根据输入格式说明符设置字符串的格式,并返回结果字符串。让我们使用 Sprintf 函数重写上面的程序。
package mainimport ( "fmt")func main() { string1 := "Go" string2 := "is awesome" result := fmt.Sprintf("%s %s", string1, string2) fmt.Println(result)}
在上面程序的第10行中,%s %s 是 Sprintf 的格式说明符输入。此格式说明符将两个字符串作为输入,并在两者之间有一个空格。这将连接两个字符串,中间有一个空格。生成的字符串存储在result中。该程序还打印,
Go is awesome字符串是不可变的
Go中字符串是不可变的,一旦字符串被被创建就不能修改它了。
package mainimport ( "fmt")func mutate(s string)string { s[0] = 'a' return s}func main() { h := "hello" fmt.Println(mutate(h))}
在上述程序的第8行中,我们尝试将字符串的第一个字符更改为'a'。单引号内的任何有效 Unicode字符都是rune。我们尝试将rune a 分配给切片的第0个位置。这是不允许的,因为字符串是不可变的,因此程序无法编译并显示错误./prog.go:8:7:cannot assign s[0]
为了解决这种字符串不可变性的问题,字符串被转换为rune切片。然后,该切片会随着所需的任何更改而发生变异,并转换回新字符串。
package mainimport ( "fmt")func mutate(s []rune) string { s[0] = 'a' return string(s)}func main() { h := "hello" fmt.Println(mutate([]rune(h)))}
在上述程序的第7行中,mutate函数接受rune切片作为参数。然后,它将切片的第一个元素更改为'a',将rune转换回字符串并返回它。此方法从程序的第13行调用。h被转换成一rune切片,并在第13行中传递到mutate。此程序输出aello。
总结
1.%s 是打印字符串的格式说明符;
%x是十六进制的格式说明符;
%c是字符格式说明符;由于UTF-8 编码中,一个代码点可以占用1个以上的字节,所以使用%c打印字符会出现bug,这时可以使用rune进行解决。
2. 使用for index, rune := range s 进行遍历rune字符;
3.len(s)用于查找字符串中的字节数;utf8包的RuneCountInString(s string) (n int) 函数可用于查找字符串的长度;
4.==操作符常用于比较两个字符串是否相等;
5.两种方式拼接字符串;
6.字符串是不可变的。
标签: #c语言中string是什么