练习4.1
编写一个函数,计算两个SHA256哈希码中不同bit的数目。(参考2.6.2节的PopCount函数。)
func PopCount(ptr *[32]byte) int {
var res int
for i := 0; i < 32; i++ {
x := int(ptr[i])
for x != 0 {
res += x & 1
x >>= 1
}
}
return res
}
练习4.2
编写一个程序,默认情况下打印标准输入的SHA256编码,并支持通过命令行flag定制,输出SHA384或SHA512哈希算法。
package main
import (
"bufio"
"crypto/sha256" //!+
"crypto/sha512"
"flag"
"fmt"
"os"
)
var n = flag.Int("n", 256, "SHA param")
func main() {
flag.Parse()
var s string
input := bufio.NewScanner(os.Stdin)
for input.Scan() {
s += input.Text()
}
switch *n {
case 256:
fmt.Printf("%x", sha256.Sum256([]byte(s)))
case 384:
fmt.Printf("%x", sha512.Sum384([]byte(s)))
case 512:
fmt.Printf("%x", sha512.Sum512([]byte(s)))
}
}
练习4.3
重写reverse函数,使用数组指针代替slice。
func reverse(s *[6]int) {
for i, j := 0, len(*s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
}
练习4.4
编写一个rotate函数,通过一次循环完成旋转。
func rotate(s []int, ind int) {
out := make([]int, cap(s)-ind)
copy(out, s[ind:])
for i := 0; i < ind; i++ {
out = append(out, s[i])
}
copy(s, out)
}
练习4.5
写一个函数在原地完成消除[]string中相邻重复的字符串的操作。
func nonrepeat(strings []string) []string {
i := 0
for j := range strings {
if j != 0 && strings[j] == strings[j-1] {
continue
} else {
strings[i] = strings[j]
i++
}
}
return strings[:i]
}
练习4.6
编写一个函数,原地将一个UTF-8编码的[]byte类型的slice中相邻的空格(参考unicode.IsSpace)替换成一个空格返回
func nonrepeat(s []byte) []byte {
for j := 0; j < len(s); j++ {
if j != 0 && unicode.IsSpace(rune(s[j])) && s[j] == s[j-1] {
copy(s[j-1:], s[j:])
s = s[:len(s)-1]
j--
}
}
return s
}
练习4.7
修改reverse函数用于原地反转UTF-8编码的[]byte。是否可以不用分配额外的内存?
不能不分配额外的内存,byte需要转为rune,否则会出现乱码
func reverse(s []byte) []rune {
r := []rune(string(s))
for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
return r
}
练习4.8
修改charcount程序,使用unicode.IsLetter等相关的函数,统计字母、数字等Unicode中不同的字符类别。
package main
import (
"bufio"
"fmt"
"io"
"os"
"unicode"
"unicode/utf8"
)
func main() {
counts := make(map[rune]int) // counts of Unicode characters
var utflen [utf8.UTFMax + 1]int // count of lengths of UTF-8 encodings
invalid := 0 // count of invalid UTF-8 characters
var utftype [3]int
in := bufio.NewReader(os.Stdin)
for {
r, n, err := in.ReadRune() // returns rune, nbytes, error
if err == io.EOF {
break
}
if err != nil {
fmt.Fprintf(os.Stderr, "charcount: %v\n", err)
os.Exit(1)
}
if r == unicode.ReplacementChar && n == 1 {
invalid++
continue
}
switch {
case unicode.IsLetter(r):
utftype[0]++
case unicode.IsDigit(r):
utftype[1]++
default:
utftype[2]++
}
counts[r]++
utflen[n]++
}
fmt.Printf("rune\tcount\n")
for c, n := range counts {
fmt.Printf("%q\t%d\n", c, n)
}
fmt.Print("\nlen\tcount\n")
for i, n := range utflen {
if i > 0 {
fmt.Printf("%d\t%d\n", i, n)
}
}
fmt.Print("\ntype\tcount\n")
for i, n := range utftype {
switch i {
case 0:
fmt.Print("letter:")
case 1:
fmt.Print("digit:")
case 2:
fmt.Print("other:")
}
fmt.Println(n)
}
if invalid > 0 {
fmt.Printf("\n%d invalid UTF-8 characters\n", invalid)
}
}
练习4.9
编写一个程序wordfreq程序,报告输入文本中每个单词出现的频率。在第一次调用Scan前先调用input.Split(bufio.ScanWords)函数,这样可以按单词而不是按行输入。文章来源:https://www.toymoban.com/news/detail-678571.html
func wordfreq() {
counts := make(map[string]int)
in := bufio.NewScanner(os.Stdin)
in.Split(bufio.ScanWords)
for in.Scan() {
counts[in.Text()]++
}
for k, v := range counts {
fmt.Println("%s %d\n", k, v)
}
}
练习4.10
修改issues程序,根据问题的时间进行分类,比如不到一个月的、不到一年的、超过一年。文章来源地址https://www.toymoban.com/news/detail-678571.html
package main
import (
"fmt"
"log"
"os"
"time"
"gopl.io/ch4/github"
)
func main() {
//now 为现在的时间,yearAgo 为距现在一年的时间,monthAgo 为距现在一月的时间。
now := time.Now()
yearAgo := now.AddDate(-1, 0, 0)
monthAgo := now.AddDate(0, -1, 0)
//三个切片,用来存储 不足一个月的问题,不足一年的问题,超过一年的问题。
yearAgos := make([]*github.Issue, 0)
monthAgos := make([]*github.Issue, 0)
noMonthAgos := make([]*github.Issue, 0)
result, err := github.SearchIssues(os.Args[1:])
if err != nil {
log.Fatal(err)
}
fmt.Printf("%d issues:\n", result.TotalCount)
for _, item := range result.Items {
if yearAgo.After(item.CreatedAt) {
yearAgos = append(yearAgos, item)
} else if monthAgo.After(item.CreatedAt) {
monthAgos = append(monthAgos, item)
} else if monthAgo.Before(item.CreatedAt) {
noMonthAgos = append(noMonthAgos, item)
}
}
fmt.Printf("\n一年前\n")
for _, item := range yearAgos {
fmt.Printf("#%-5d %9.9s %.55s\n",
item.Number, item.User.Login, item.Title)
}
fmt.Printf("\n一月前\n")
for _, item := range monthAgos {
fmt.Printf("#%-5d %9.9s %.55s\n",
item.Number, item.User.Login, item.Title)
}
fmt.Printf("\n不足一月\n")
for _, item := range noMonthAgos {
fmt.Printf("#%-5d %9.9s %.55s\n",
item.Number, item.User.Login, item.Title)
}
}
到了这里,关于GO语言圣经 第四章习题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!