Go语言类型练习题

Go语言类型练习题

题目一

1、为 float64 定义一个别名类型 Celsius,并给它定义 String(),它输出一个十进制数和 °C 表示的温度值。

package main

import "fmt"

// 为 float64 定义一个别名类型 Celsius,并给它定义 String(),它输出一个十进制数和 °C 表示的温度值。
type Celsius float64

func (c Celsius) String() string {
	return fmt.Sprintf("%g °C", c)
}

func main() {
	c := Celsius(23.5)
	fmt.Println(c.String())
}

解释:
在上面的代码中,我使用 type 关键字定义了一个新的类型 Celsius,它是 float64 的别名类型。然后,在 Celsius 类型上定义了 String() 方法,该方法返回一个格式化的字符串,表示温度值和单位 °C。

在 main() 函数中,我创建了一个 Celsius 类型的变量 c,并打印了它的 String() 方法的输出结果。 输出结果为 23.5°C。

题目二

2、为 int 定义一个别名类型 Day,定义一个字符串数组它包含一周七天的名字,为类型 Day 定义 String() 方法,它输出星期几的名字。使用 iota 定义一个枚举常量用于表示一周的中每天(MO、TU…)。

package main

import "fmt"

// 为 int 定义一个别名类型 Day,定义一个字符串数组它包含一周七天的名字,
// 为类型 Day 定义 String() 方法,它输出星期几的名字。
// 使用 iota 定义一个枚举常量用于表示一周的中每天(MO、TU...)。
type Day int

const (
	MO Day = iota
	TU
	WE
	TH
	FR
	SA
	SU
)

var dayNames = [...]string{"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"}

func (d Day) String() string {
	if d < MO || d > SU {
		return "Wrong, not the week"
	}
	return dayNames[d]
}

func main() {
	fmt.Println(MO.String())
	fmt.Println(TU.String())
	fmt.Println(WE.String())
	fmt.Println(TH.String())
	fmt.Println(FR.String())
	fmt.Println(SA.String())
	fmt.Println(SU.String())
}

解释:
在上面的代码中,我使用 type 关键字定义了一个新的类型 Day,它是 int 的别名类型。然后,我使用 const 和 iota 定义了一周中每天的枚举常量,从 MO 开始,逐个加1。

我还定义了一个包级变量 dayNames,它是一个字符串数组,包含了一周七天的名字。

最后,我在 Day 类型上定义了 String() 方法,该方法接收一个 Day 类型的参数,返回相应星期几的名字。

题目三

3、实现栈(stack)数据结构:

题目三栈结构

它的格子包含数据,比如整数 i、j、k 和 l 等等,格子从底部(索引 0)至顶部(索引 n)来索引。这个例子中假定 n=3,那么一共有 4 个格子。

一个新栈中所有格子的值都是 0。

push 将一个新值放到栈的最顶部一个非空(非零)的格子中。

pop 获取栈的最顶部一个非空(非零)的格子的值。现在可以理解为什么栈是一个后进先出(LIFO)的结构了吧。

为栈定义一 Stack 类型,并为它定义一个 Push 和 Pop 方法,再为它定义 String() 方法(用于调试)它输出栈的内容,比如:[0:i] [1:j] [2:k] [3:l]。

1)stack_arr.go:使用长度为 4 的 int 数组作为底层数据结构。
2)stack_struct.go:使用包含一个索引和一个 int 数组的结构体作为底层数据结构,索引表示第一个空闲的位置。
3)使用常量 LIMIT 代替上面表示元素个数的 4 重新实现上面的 1)和 2),使它们更具有一般性。

1)使用长度为 4 的 int 数组作为底层数据结构实现栈:

package main

import (
    "fmt"
)

type Stack [4]int

func (s *Stack) Push(value int) {
    for i, v := range s {
        if v == 0 {
            s[i] = value
            return
        }
    }
}

func (s *Stack) Pop() int {
    for i := len(s) - 1; i >= 0; i-- {
        if s[i] != 0 {
            value := s[i]
            s[i] = 0
            return value
        }
    }
    return 0
}

func (s Stack) String() string {
    var str string
    for i, v := range s {
        str += fmt.Sprintf("[%d:%d] ", i, v)
    }
    return str
}

func main() {
    s := new(Stack)
    s.Push(1)
    s.Push(2)
    s.Push(3)
    s.Push(4)
    fmt.Println(s)
    fmt.Println(s.Pop())
    fmt.Println(s.Pop())
    fmt.Println(s)
}

解释:
在上面的代码中,我定义了一个 Stack 类型,它是一个长度为 4 的 int 数组的别名类型。我还为它定义了 Push() 和 Pop() 方法,以及 String() 方法。

在 Push() 方法中,我遍历栈中的元素,找到第一个空闲的位置,将新值插入到该位置。如果栈已满,该方法不做任何操作。

在 Pop() 方法中,我从栈顶开始遍历栈中的元素,找到第一个非空元素,返回它,并将该位置上的值清零。如果栈为空,该方法返回 0。

在 String() 方法中,我遍历整个栈,输出每个格子的索引和值,以字符串形式返回。

在 main() 函数中,我创建了一个 Stack 类型的变量 s,依次将值 1、2、3、4 压入栈中,打印栈的内容,然后弹出两个元素,再次打印栈的内容。

2)使用包含一个索引和一个 int 数组的结构体作为底层数据结构实现栈:

package main

import (
    "fmt"
)

type Stack struct {
    index int
    data  [4]int
}

func (s *Stack) Push(value int) {
    if s.index < len(s.data) {
        s.data[s.index] = value
        s.index++
    }
}

func (s *Stack) Pop() int {
    if s.index > 0 {
        s.index--
        value := s.data[s.index]
        s.data[s.index] = 0
        return value
    }
    return 0
}

func (s Stack) String() string {
    var str string
    for i, v := range s.data {
        str += fmt.Sprintf("[%d:%d] ", i, v)
    }
    return str
}

func main() {
    s := new(Stack)
    s.Push(1)
    s.Push(2)
    s.Push(3)
    s.Push(4)
    fmt.Println(s)
    fmt.Println(s.Pop())
    fmt.Println(s.Pop())
    fmt.Println(s)
}

解释:
在上面的代码中,我定义了一个 Stack 结构体,它包含一个索引和一个长度为 4 的 int 数组。我还为它定义了 Push() 和 Pop() 方法,以及 String() 方法。

在 Push() 方法中,如果栈未满,我将新值插入到索引指向的位置,并将索引加一。

在 Pop() 方法中,如果栈非空,我将索引减一,并返回当前索引所指向的位置的值。如果栈为空,该方法返回 0。

在 String() 方法中,我遍历整个数组,输出每个格子的索引和值,以字符串形式返回。

在 main() 函数中,我创建了一个 Stack 类型的变量 s,依次将值 1、2、3、4 压入。

3)使用常量 LIMIT 代替上面表示元素个数的 4 重新实现上面的 1)和 2),使它们更具有一般性。

以下是使用常量 LIMIT 重构后实现的代码:

1)使用长度为 LIMIT 的 int 数组作为底层数据结构实现栈:

package main

import (
    "fmt"
)

const LIMIT = 4

type Stack [LIMIT]int

func (s *Stack) Push(value int) {
    for i, v := range s {
        if v == 0 {
            s[i] = value
            return
        }
    }
}

func (s *Stack) Pop() int {
    for i := len(s) - 1; i >= 0; i-- {
        if s[i] != 0 {
            value := s[i]
            s[i] = 0
            return value
        }
    }
    return 0
}

func (s Stack) String() string {
    var str string
    for i, v := range s {
        str += fmt.Sprintf("[%d:%d] ", i, v)
    }
    return str
}

func main() {
    s := new(Stack)
    s.Push(1)
    s.Push(2)
    s.Push(3)
    s.Push(4)
    fmt.Println(s)
    fmt.Println(s.Pop())
    fmt.Println(s.Pop())
    fmt.Println(s)
}

解释:
在上面的代码中,我用 const 关键字定义了一个名为 LIMIT 的常量。然后,我使用 LIMIT 来代替之前直接写死的数组长度 4,使得代码更加具有一般性。

2)使用包含一个索引和一个 int 数组的结构体作为底层数据结构实现栈:

package main

import (
    "fmt"
)

const LIMIT = 4

type Stack struct {
    index int
    data  [LIMIT]int
}

func (s *Stack) Push(value int) {
    if s.index < len(s.data) {
        s.data[s.index] = value
        s.index++
    }
}

func (s *Stack) Pop() int {
    if s.index > 0 {
        s.index--
        value := s.data[s.index]
        s.data[s.index] = 0
        return value
    }
    return 0
}

func (s Stack) String() string {
    var str string
    for i, v := range s.data {
        str += fmt.Sprintf("[%d:%d] ", i, v)
    }
    return str
}

func main() {
    s := new(Stack)
    s.Push(1)
    s.Push(2)
    s.Push(3)
    s.Push(4)
    fmt.Println(s)
    fmt.Println(s.Pop())
    fmt.Println(s.Pop())
    fmt.Println(s)
}

解释:
在上面的代码中,我同样使用 const 关键字定义了一个名为 LIMIT 的常量。然后,我用 LIMIT 来代替之前直接写死的数组长度,使得代码更加具有一般性。

总体来说,使用常量可以抽象出代码中的硬编码部分,让代码更具有可读性和可维护性。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SmallFatMan

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值