首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >go计划9 freq(1)

go计划9 freq(1)
EN

Code Review用户
提问于 2021-06-08 21:06:46
回答 1查看 78关注 0票数 4

我在go中实现了计划9中的freq(1)程序。

代码语言:javascript
复制
/* 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的一个示例:

代码语言:javascript
复制
 $ 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

每行打印符文的代码点(以十进制、八进制和十六进制表示),并输出符文本身,然后是出现计数。

我怎样才能使代码更加优雅和地道呢?

EN

回答 1

Code Review用户

回答已采纳

发布于 2021-06-09 10:32:03

总体看来已经相当干净了。

  • 就像注释中已经说过的那样,不需要var和显式函数类型,实际上freq := freqBytes看起来要干净得多。
  • 可以删除!*dflag && ...周围的括号。
  • 分别使用os.Stdin,命令行参数看起来不错,只有其他可能添加的东西是使用--作为分隔符来禁用对-的特殊处理。Close的错误输出可能也应该被记录下来,尽管可能不是致命的情况。
  • int保证是至少32位宽rune的化名int32,所以同样的参数也适用。考虑到这一点,考虑在任何地方使用int,然后就可以使用sort.Ints了。
  • 在重用方面,freqRunesfreqBytes确实可以在任何io.Reader上运行。使用更通用的类型更好,因为您可以立即看到它实际上是一个更强大的函数,它操作任何类型的IO输入(例如,套接字或字节缓冲区),而不仅仅是文件。
  • 如果有对性能的关注,当然,分析应该是有序的,否则我不会对此发表任何评论。
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/262819

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档