我在go中实现了计划9中的freq(1)程序。
/* print histogram of character frequencies */
package main
import (
"bufio"
"flag"
"fmt"
"io"
"log"
"os"
"sort"
"unicode"
)
var dflag = flag.Bool("d", false, "print decimal value")
var xflag = flag.Bool("x", false, "print hex value")
var oflag = flag.Bool("o", false, "print octal value")
var cflag = flag.Bool("c", false, "print unicode character if printable")
var rflag = flag.Bool("r", false, "count UTF8 sequences (runes)")
func main() {
var freq func(*os.File, map[int32]int) = freqBytes
counts := make(map[int32]int)
var codes []int32
flag.Parse()
if (!*dflag && !*oflag && !*xflag && !*cflag) {
*dflag = true
*oflag = true
*xflag = true
*cflag = true
}
if (*rflag) {
freq = freqRunes
}
if (len(flag.Args()) == 0) {
freq(os.Stdin, counts)
} else {
for _, arg := range flag.Args() {
if arg == "-" {
freq(os.Stdin, counts)
} else {
f, err := os.Open(arg)
if err != nil {
log.Fatal(err)
}
freq(f, counts)
f.Close()
}
}
}
for code := range counts {
codes = append(codes, code)
}
sort.Slice(codes, func(i, j int) bool { return codes[i] < codes[j] })
for _, code := range codes {
if (*dflag) {
fmt.Printf("%3d ", code)
}
if (*oflag) {
fmt.Printf("%03o ", code)
}
if (*xflag) {
fmt.Printf("%02x ", code)
}
if (*cflag) {
c := rune(code)
if (!unicode.IsPrint(c) || unicode.IsSpace(c)) {
c = '-'
}
fmt.Printf("%c ", c)
}
fmt.Printf("%8d\n", counts[code])
}
}
func freqRunes(f *os.File, counts map[int32]int) {
in := bufio.NewReader(f)
for {
r, n, err := in.ReadRune()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
if r == unicode.ReplacementChar && n == 1 {
continue
}
counts[r]++
}
}
func freqBytes(f *os.File, counts map[int32]int) {
in := bufio.NewReader(f)
for {
b, err := in.ReadByte()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
counts[int32(b)]++
}
}freq(1)统计标准输入或给定文件中每个字节(如果给定-r选项,则计算每个符文)的出现情况。有关手册的更多信息。不可打印和空格字符被替换为-。下面是使用世界语Lorem Ipsum的一个示例:
$ echo "eĥoŝanĝo ĉiuĵaŭde" | ./freq -r
10 012 0a - 1
32 040 20 - 1
97 141 61 a 2
100 144 64 d 1
101 145 65 e 2
105 151 69 i 1
110 156 6e n 1
111 157 6f o 2
117 165 75 u 1
265 411 109 ĉ 1
285 435 11d ĝ 1
293 445 125 ĥ 1
309 465 135 ĵ 1
349 535 15d ŝ 1
365 555 16d ŭ 1每行打印符文的代码点(以十进制、八进制和十六进制表示),并输出符文本身,然后是出现计数。
我怎样才能使代码更加优雅和地道呢?
发布于 2021-06-09 10:32:03
总体看来已经相当干净了。
var和显式函数类型,实际上freq := freqBytes看起来要干净得多。!*dflag && ...周围的括号。os.Stdin,命令行参数看起来不错,只有其他可能添加的东西是使用--作为分隔符来禁用对-的特殊处理。Close的错误输出可能也应该被记录下来,尽管可能不是致命的情况。int保证是至少32位宽,rune的化名int32,所以同样的参数也适用。考虑到这一点,考虑在任何地方使用int,然后就可以使用sort.Ints了。freqRunes和freqBytes确实可以在任何io.Reader上运行。使用更通用的类型更好,因为您可以立即看到它实际上是一个更强大的函数,它操作任何类型的IO输入(例如,套接字或字节缓冲区),而不仅仅是文件。https://codereview.stackexchange.com/questions/262819
复制相似问题