《Go程序設計語言》Exercise 11.1

1 題目

Exercise 11.1 Write tests for the charcount program in Section 4.3

2 實現

2.1 改造源代碼

原代碼是一個main包,改造成函數:

// Copyright © 2016 Alan A. A. Donovan & Brian W. Kernighan.
// License: https://creativecommons.org/licenses/by-nc-sa/4.0/

// See page 97.
//!+

// Charcount computes counts of Unicode characters.
package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"unicode"
	"unicode/utf8"
)

func main() {
	counts, utflen, invalid := charcount(os.Stdin)
	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)
		}
	}
	if invalid > 0 {
		fmt.Printf("\n%d invalid UTF-8 characters\n", invalid)
	}
}

// 	counts: counts of Unicode characters
//	utflen: count of lengths of UTF-8 encodings
//	invalid: count of invalid UTF-8 characters
func charcount(reader io.Reader) (counts map[rune]int, utflen []int, invalid int) {
	counts = make(map[rune]int)         // counts of Unicode characters
	utflen = make([]int, utf8.UTFMax+1) // count of lengths of UTF-8 encodings
	invalid = 0                         // count of invalid UTF-8 characters

	in := bufio.NewReader(reader)
	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
		}
		counts[r]++
		utflen[n]++
	}
	return
}

//!-

2.2 編寫測試用例

package main

import (
	"bytes"
	"testing"
)

func TestCharCount(t *testing.T) {
	str := &bytes.Buffer{}
	str.WriteString("hello 世界")
	counts, utflen, invalid := charcount(str)

	countsWant := map[rune]int{
		'h': 1,
		'e': 1,
		'l': 2,
		'o': 1,
		'世': 1,
		'界': 1,
		' ': 1,
	}
	utflenWant := []int{0, 6, 0, 2, 0}
	invalidWant := 0

	if invalid != invalidWant {
		t.Errorf("invalid count = %v, want %v", invalid, invalidWant)
	}

	for c, n := range countsWant {
		if got, ok := counts[c]; !ok || got != n {
			t.Errorf("counts = %v, want %v", counts, countsWant)
		}
	}

	if len(utflenWant) != len(utflen) {
		t.Errorf("utflen = %v, want %v", utflen, utflenWant)
	}

	for i := range utflenWant {
		if utflen[i] != utflenWant[i] {
			t.Errorf("utflen = %v, want %v", utflen, utflenWant)
			break
		}
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章