• Go程序设计语言练习题(7.1-7.10)


    7.1:使用类似ByteCounter的想法,实现单词和行的计数器,实现时考虑使用bufio.ScanWords。

    package main
    
    import (
        "bufio"
        "fmt"
    )
    
    type WordsCounter int
    
    func (c *WordsCounter) Write(content []byte) (int, error) {
        for start := 0; start < len(content); {
            //跳过开头的space,返回遇到第一个word后下次scan的开始index
            //Hello Worlds 调用bufio.ScanWords返回
            //6 [Hello的字节slice] nil
            advance, _, err := bufio.ScanWords(content[start:], true)
            if err != nil {
                return 0, err
            }
            start += advance
            (*c)++
        }
        return int(*c), nil
    }
    
    type LinesCounter int
    
    func (c *LinesCounter) Write(content []byte) (int, error) {
        for start := 0; start < len(content); {
            advance, _, err := bufio.ScanLines(content[start:], true)
            if err != nil {
                return 0, err
            }
            start += advance
            (*c)++
        }
        return int(*c), nil
    }
    
    func main() {
        var wc WordsCounter
        wc.Write([]byte("Hello Worlds Test Me"))
        fmt.Println(wc) // 4
        wc.Write([]byte("append something to the end"))
        fmt.Println(wc) // 9
    
        var lc LinesCounter
        fmt.Fprintf(&lc, "%s
    %s
    %s
    ", "Hello World", "Second Line", "Third Line")
        fmt.Println(lc) // 3
        fmt.Fprintf(&lc, "%s
    %s
    %s", "第4行", "第5行", "")
        fmt.Println(lc) // 5
    }
    View Code

    7.2:实现一个满足如下签名的CountingWriter函数,输入一个io.Writer,输出一个封装了输入值的心Writer,以及一个置项int64的指针,改制真对应的值是新的Writer吸入的字节数。

    package main
    
    import (
        "fmt"
        "io"
        "os"
    )
    
    type CountWriter struct {
        Writer io.Writer
        Count  int
    }
    
    func (cw *CountWriter) Write(content []byte) (int, error) {
        n, err := cw.Writer.Write(content)
        if err != nil {
            return n, err
        }
        cw.Count += n
        return n, nil
    }
    
    func CountingWriter(writer io.Writer) (io.Writer, *int) {
        cw := CountWriter{
            Writer: writer,
        }
        return &cw, &(cw.Count)
    }
    
    func main() {
        cw, counter := CountingWriter(os.Stdout)
        fmt.Fprintf(cw, "%s", "Print somethind to the screen...")
        fmt.Println(*counter)
        cw.Write([]byte("Append soething..."))
        fmt.Println(*counter)
    }
    View Code

    7.3:为gopl.io/ch4/treesort中的*tree类型写一个String方法,用于展示其中的值序列。

    package main
    
    import (
        "fmt"
        "math/rand"
    )
    
    type tree struct {
        value       int
        left, right *tree
    }
    
    func (t *tree) String() string {
        res := ""
        if t == nil {
            return res
        }
        res += t.left.String()
        res = fmt.Sprintf("%s %d", res, t.value)
        res += t.right.String()
        return res
    }
    func buildTree(data []int) *tree {
        var root = new(tree)
        for _, v := range data {
            root = add(root, v)
        }
        return root
    }
    func add(t *tree, e int) *tree {
        if t == nil {
            t = new(tree)
            t.value = e
            return t
        }
    
        if e < t.value {
            t.left = add(t.left, e)
        } else {
            t.right = add(t.right, e)
        }
        return t
    }
    
    func main() {
        data := make([]int, 50)
        for i := range data {
            data[i] = rand.Int() % 50
        }
        root := buildTree(data)
        fmt.Println(root)
    
        //空指针
        fmt.Println(new(tree))
    
        //只有根节点
        root = new(tree)
        root.value = 100
        fmt.Println(root)
    
        //没有右子树
        data = []int{5, 4, 3, 2, 1}
        root = buildTree(data)
        fmt.Println(root)
    
        //没有左子树
        data = []int{1, 3, 2, 4, 5}
        root = buildTree(data)
        fmt.Println(root)
    }
    View Code

    7.4:strings.NewReader函数输入一个字符串,返回一个从字符串读取数据并满足io.Reader接口的值。请实现该函数。

    package main
    
    import (
        "fmt"
        "io"
    )
    
    type StringReader struct {
        data string
        n    int
    }
    
    func (sr *StringReader) Read(b []byte) (int, error) {
        data := []byte(sr.data)
        if sr.n >= len(data) {
            return 0, io.EOF
        }
    
        data = data[sr.n:]
        n := 0
        if len(b) >= len(data) {
            n = copy(b, data)
            sr.n = sr.n + n
            return n, nil
        }
        n = copy(b, data)
        sr.n = sr.n + n
        return n, nil
    }
    
    func NewReader(in string) *StringReader {
        sr := new(StringReader)
        sr.data = in
        return sr
    }
    
    func main() {
        str := "Hello World"
        sr := NewReader(str)
        data := make([]byte, 10)
        n, err := sr.Read(data)
        for err == nil {
            fmt.Println(n, string(data[0:n]))
            n, err = sr.Read(data)
        }
    }
    View Code

    7.5:io包中的LimitReader函数接受一个io.Reader r和字节数n,返回一个Reader,该返回值从r读取数据,但在读取n字节后报告文件结束,请实现该函数。

    func LimitReader(r io.Reader,n int64) io.Reader

    package main
    
    import (
        "fmt"
        "io"
        "os"
    )
    
    type LimitedReader struct {
        Reader  io.Reader
        Limit   int
        current int
    }
    
    func (r *LimitedReader) Read(b []byte) (int, error) {
        if r.current >= r.Limit {
            return 0, io.EOF
        }
    
        if r.current+len(b) > r.Limit {
            b = b[:r.Limit-r.current]
        }
        n, err := r.Reader.Read(b)
        if err != nil {
            return n, err
        }
        r.current += n
        return n, nil
    }
    
    func LimitReader(r io.Reader, limit int) io.Reader {
        lr := LimitedReader{
            Reader: r,
            Limit:  limit,
        }
        return &lr
    }
    
    func main() {
        file, err := os.Open("limit.txt") // 1234567890
        if err != nil {
            panic(err)
        }
        defer file.Close()
    
        lr := LimitReader(file, 5)
        buf := make([]byte, 10)
        n, err := lr.Read(buf)
        if err != nil {
            panic(err)
        }
        fmt.Println(n, buf) // 5 [49 50 51 52 53 0 0 0 0 0]
    }
    View Code

    7.8:(先实现一部分)将多个排序方法存到一个slice中,先按最后的方法排序,再按之前的方法排序。

    package main
    
    import (
        "fmt"
        "sort"
    )
    
    type book struct {
        name   string
        price  float64
        author string
    }
    type byFunc func(i, j int) bool
    type tableSlice struct {
        lists     []*book
        lessFuncs []byFunc
    }
    
    func (ts tableSlice) Len() int {
        return len(ts.lists)
    }
    func (ts tableSlice) Swap(i, j int) {
        ts.lists[i], ts.lists[j] = ts.lists[j], ts.lists[i]
    }
    func (ts tableSlice) Less(i, j int) bool {
        for t := len(ts.lessFuncs) - 1; t >= 0; t-- {
            if ts.lessFuncs[t](i, j) {
                return true
            } else if !ts.lessFuncs[t](j, i) {
                continue
            } else {
                return false
            }
        }
        return false
    }
    
    func (ts tableSlice) byName(i, j int) bool {
        return ts.lists[i].name < ts.lists[j].name
    }
    func (ts tableSlice) byPrice(i, j int) bool {
        return ts.lists[i].price < ts.lists[j].price
    }
    
    func main() {
        book1 := book{"GoLang", 65.50, "Aideng"}
        book2 := book{"PHP", 45.50, "Sombody"}
        book3 := book{"C", 45.50, "Tan"}
        ts := tableSlice{
            lists: []*book{&book1, &book2, &book3},
        }
        ts.lessFuncs = []byFunc{ts.byName, ts.byPrice}
        sort.Sort(ts)
        for _, book := range ts.lists {
            fmt.Println(*book)
        }
    }
    View Code

    7.10:写一个函数IsPalindrome(s sort.Interface)bool判断一个序列是否是回文。

    package palindrome
    
    import (
        "fmt"
        "sort"
    )
    
    func IsPalindrome(s sort.Interface) bool {
        if s.Len() == 0 {
            return false
        }
        i, j := 0, s.Len()-1
        for i < j {
            if !s.Less(i, j) && !s.Less(j, i) {
                i++
                j--
            } else {
                return false
            }
        }
        return true
    }
    
    func main() {
        a := []int{1, 2, 3, 2, 1}
        fmt.Println(IsPalindrome(sort.IntSlice(a))) // true
        a = []int{2, 1, 3, 4, 5}
        fmt.Println(IsPalindrome(sort.IntSlice(a))) //false
        a = []int{1}
        fmt.Println(IsPalindrome(sort.IntSlice(a))) // true
        a = []int{}
        fmt.Println(IsPalindrome(sort.IntSlice(a))) // false
    }
    View Code
  • 相关阅读:
    UVA120Stacks of Flapjacks
    [.NET] 基于windows mobile 5.0 开发环境配置说明
    C#实现UDP打洞
    webBrowser对跳转后的页面的处理
    Windows Mobile程序环境配置以及Windows Mobile与PC进行UDP通信总结
    C#【Fox即时通讯核心】 开发记录之三(知识储备:TCP UDP打洞)
    jqplot统计图工具简单例子
    订单编号
    windows mobile 5.0 PocketPC模拟器上网的设置 【正确】
    今明2年主要目标20112012
  • 原文地址:https://www.cnblogs.com/ling-diary/p/10294916.html
Copyright © 2020-2023  润新知