GOPL Exercise

EX 3.10

练习 3.10: 编写一个非递归版本的comma函数,使用bytes.Buffer代替字符串链接操作。

func comma(s string) string {
	var buf bytes.Buffer
	n := len(s)
	fmt.Println(n)
	if n <= 3 {
		return s
	}
	for i := n; i > 0; i-- {
		if i%3 == 0 && i != n {
			buf.WriteByte(',')
		}
		buf.WriteByte(s[n-i])
	}
	return buf.String()
}

EX 3.11

练习 3.11: 完善comma函数,以支持浮点数处理和一个可选的正负号的处理。

func comma(s string) string {
	var buf bytes.Buffer
	mantissaStart := 0
	if s[0] == '+' || s[0] == '-' {
		buf.WriteByte(s[0])
		mantissaStart = 1
	}
	mantissaEnd := strings.Index(s, ".")
	if mantissaEnd == -1 {
		mantissaEnd = len(s)
	}
	mantissa := s[mantissaStart:mantissaEnd]
	n := len(mantissa)
	if n <= 3 {
		buf.WriteString(mantissa)
	} else {
		for i := n; i > 0; i-- {
			if i%3 == 0 && i != n {
				buf.WriteByte(',')
			}
			buf.WriteByte(mantissa[n-i])
		}
	}
	buf.WriteString(s[mantissaEnd:])
	return buf.String()
}

EX 3.12

练习 3.12: 编写一个函数,判断两个字符串是否是相互打乱的,也就是说它们有着相同的字符,但是对应不同的顺序。

// 一
func isAnagram1(a, b string) bool {
	j := 0
	for i := 0; i < len(a); i++ {
		if strings.Count(a, a[i:i+1]) == strings.Count(b, a[i:i+1]) {
			j++
		}
	}
	if !strings.EqualFold(a, b) && j == len(a) && len(a) == len(b) {
		return true
	}
	return false
}

// 二
func isAnagram2(a, b string) bool {
	aFrep := make(map[rune]int)
	for _, c := range a {
		aFrep[c]++
	}
	bFrep := make(map[rune]int)
	for _, c := range b {
		bFrep[c]++
	}
	for k, v := range aFrep {
		if bFrep[k] != v {
			return false
		}
	}
	for k, v := range bFrep {
		if aFrep[k] != v {
			return false
		}
	}
	return true
}

// 三
func isAnagram3(a, b string) bool {
	aFrep := make(map[rune]int)
	for _, c := range a {
		aFrep[c]++
	}
	bFrep := make(map[rune]int)
	for _, c := range b {
		bFrep[c]++
	}
	if reflect.DeepEqual(aFrep, bFrep) {
		return true
	}
	return false
}

EX 3.13

练习 3.13: 编写KB、MB的常量声明,然后扩展到YB。

const (
	KB = 1000
	MB = 1000 * KB
	GB = 1000 * MB
	PB = 1000 * GB
)

EX 7.1

练习 7.1: 使用来自ByteCounter的思路,实现一个针对单词和行数的计数器。你会发现bufio.ScanWords非常的有用。

type WordCounter int

func (c *WordCounter) Write(p []byte) (int, error) {
	scanner := bufio.NewScanner(bytes.NewReader(p))
	scanner.Split(bufio.ScanWords)
	for scanner.Scan() {
		*c += WordCounter(1)
	}
	return 0, nil
}

type LineCounter int

func (c *LineCounter) Write(p []byte) (int, error) {
	scanner := bufio.NewScanner(bytes.NewReader(p))
	scanner.Split(bufio.ScanLines)
	for scanner.Scan() {
		*c += LineCounter(1)
	}
	return 0, nil
}

EX 7.2

练习 7.2: 写一个带有如下函数签名的函数CountingWriter,传入一个io.Writer接口类型,返回一个把原来的Writer封装在里面的新的Writer类型和一个表示新的写入字节数的int64类型指针。

type ByteCounter struct {
	w       io.Writer
	written int64
}

func (c *ByteCounter) Write(p []byte) (int, error) {
	n, err := c.w.Write(p)
	c.written += int64(n)
	return n, err
}

func CountingWriter(w io.Writer) (io.Writer, *int64) {
	c := ByteCounter{w, 0}
	return &c, &c.written
}

EX 7.3

练习 7.3: 为在gopl.io/ch4/treesort (§4.4)中的*tree类型实现一个String方法去展示tree类型的值序列。

func (t *tree) String() string {
	var s string
	if t == nil {
		return s
	}
	s += t.left.String()
	if t.left != nil {
		s += ", "
	}
	s += strconv.Itoa(t.value)
	if t.right != nil {
		s += ", "
	}
	s += t.right.String()
	return s
}

EX 7.7

练习 7.7: 解释为什么帮助信息在它的默认值是20.0没有包含°C的情况下输出了°C。

因为 CelsiusFlag 拥有 Celsius 作为成员,而 Celsius 实现了 String 方法(实现了 fmt.Stringer 接口),
所以打印是会通过 Celsius.String() 输出

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值