Go程序设计语言第1版 71页遇到下面一题,当时没有解出来,我这个人有个特点,越困难越想上,这个问题一直放在脑子里很不舒服。因此用了一下午时间(边工作边挤时间,一边python一边go 哈!~)还好最终解了出来。
题目: 练习4.7:修改函数reverse,来翻转一个UTF8编码的字符串中的字符元素,传入参数是该字符串对应字节slice类型([]byte)。你可以做到不需要重新分配内存就实现功能吗?
注:这道题真是费了不少功夫,走了很多弯路,但做完对golang基础知识 slice utf8 []byte rune 等加深了印象和理解。所以建议同行们看书一定要多动手,反复练习,记住过程、思路,重要的不是结果。
思路:
举例 比如字符串“中华人民共和国”转换成[]byte类型如下:
[228 184 173 229 141 142 228 186 186 230 176 145 229 133 177 229 146 140 229 155 189]
现在要实现字符的倒序,也就是最终为 国和共民人华中。而上面[]byte类型中 ,
228 184 173 对应 “中”
229 155 189 对应 “国”
所以倒序不是简单的一个一个byte字节位置转换,且utf8 字符使用1~4个范围字节表示,肯定也不是3个3个位置置换,本文只是使用中文举例。
其实此题解决关键书中已经给出,只要你把前面知识真正掌握并理解,加上自己的思路综合运用答案就出来了。
先忽略字节数,思路如下:
首先,把它化简为简单的数组,如[1,2,3,4,5], 前提使用 s[i], s[j] = s[j], s[i] 已经不可行,现在需要新的解决办法,且要达到“不需要重新分配内存”这个要求。
因此,想出下面不改变原长度改变字节位置的挪动思路:
最初 [1,2,3,4,5]
步骤1 [2,3,4,5,1]
步骤2 [3,4,5,2,1]
步骤3[4,5,3,2,1]
步骤4 [5,4,3,2,1]
根据上面思路,参照原文知识点及代码例子,...(中间反复调试,加深基础知识理解,特别是把python 知识想当然带入了go, 深浅拷贝的巨坑 哎 )还好解决之 :)。
package main
import (
"fmt"
"unicode/utf8"
)
func reverse_byte(slice []byte) {
fmt.Println(slice)
for l := len(slice); l > 0; {
r, size := utf8.DecodeRuneInString(string(slice[0:]))
copy(slice[0:l], slice[0+size:l])
copy(slice[l-size:l], []byte(string(r)))
l -= size
}
fmt.Println(slice)
}
func main() {
reverse_byte([]byte("中华人民共和国"))
}
输出结果为:
[228 184 173 229 141 142 228 186 186 230 176 145 229 133 177 229 146 140 229 155 189]
[229 155 189 229 146 140 229 133 177 230 176 145 228 186 186 229 141 142 228 184 173]