为了账号安全,请及时绑定邮箱和手机立即绑定

有没有更好的方法来实现模仿有限字符显示的水平滚动文本效果?

有没有更好的方法来实现模仿有限字符显示的水平滚动文本效果?

Go
婷婷同学_ 2023-08-14 14:31:50
我试图在命令行上模仿 16 个字符的显示,它在一个长字符串上循环,无限类似于股票交易股票。现在,我首先打印 ASCII 字符串的前 16 字节切片,并一次移动 1 个字节:package mainimport (    "fmt"    "time")const (    chars = 16    text  = "There are many variations of passages of Lorem Ipsum available!!!")func main() {    fmt.Print("\033[2J") // clear screen    buf := []byte(text)    i := chars    for {        fmt.Print("\033[H") // move cursor back to first position        fmt.Printf(string(buf[i-chars : i]))        i++        if i == len(buf)+1 {            i = chars        }        time.Sleep(time.Second / 4)        // visualization of what's happening:        // fmt.Printf("\t\t Character:%d of Length:%d | Slice: %d:%d \n", i, len(buf), i-chars, i)    }}当我到达文本末尾时,我重置循环内的计数器并从第一个切片开始再次打印。我不想这样做,而是想获得“翻转”效果,其中切片的头部无缝连接到切片的尾部。问题是,我不能使用空缓冲区并将头部附加到循环内的尾部,因为它会无限增长。因此,我没有这样做,而是决定在循环之前将字符串的前 16 个字节附加到其尾部,并立即缩小切片 -16 个字节。但由于 -16 字节仍然存在于支持数组中,我可以从循环中扩展/收缩:func main() {    fmt.Print("\033[2J") // clear screen    buf := []byte(text)    buf = append(buf, buf[:chars]...)    buf = buf[:len(buf)-chars]    var expanded bool    i := chars    for {        fmt.Print("\033[H") // move cursor back to first position        fmt.Printf(string(buf[i-chars : i]))        i++        if i+1 == len(buf)-chars && !expanded {            buf = buf[:len(buf)+chars]            expanded = true        }        if i+1 == len(buf) {            i = chars            buf = buf[:len(buf)-chars]            expanded = false        }        time.Sleep(time.Second / 2)        // visualization of what's happening:        //fmt.Printf("\t\t Character:%d of Length:%d | Slice: %d:%d | Cap: %d\n", i, len(buf), i-chars, i, cap(buf))    }}这让我到达了我想要的地方,但我对 Go 相当陌生,所以我想知道是否有更好的方法来达到相同的结果?
查看完整描述

1 回答

?
慕码人8056858

TA贡献1803条经验 获得超6个赞

首先我不会改变缓冲区。0将前 16 个字符附加到其末尾以轻松获得“滚动”效果是一个好主意,但是当您到达末尾时将位置重置到更容易且更便宜。

接下来,您不需要对字节切片进行操作。只需在string. 字符串可以像切片一样进行索引和切片,并且切片 astring甚至不会进行复制(不必),它会返回一个新字符串(标头),该字符串共享字符串数据的后备数组。不要忘记索引和切片string使用字节索引(不是rune索引),这对于 ASCII 文本来说很好(它们的字符在 UTF-8 中一对一映射到字节),但不适用于多字节特殊字符。你的示例文本很好。

也不要用于fmt.Printf()打印需要格式的文本string(将其第一个参数视为格式字符串)。相反,只需使用fmt.Print().

总而言之,您的解决方案可以简化为这样,这在性能方面要好得多,而且更干净、更简单:

func main() {

    fmt.Print("\033[2J") // clear screen

    s := text + text[:chars]


    for i := 0; ; i = (i + 1) % len(text) {

        fmt.Print("\033[H") // move cursor back to first position

        fmt.Print(s[i : i+chars])

        time.Sleep(time.Second / 2)

    }

}

另请注意,当位置达到 时len(text),我们将其重置为0,因此之前的文本从最后一个字符开始text并chars-1从头开始使用。因此,附加chars-1而不是chars:


s := text + text[:chars-1]


查看完整回答
反对 回复 2023-08-14
  • 1 回答
  • 0 关注
  • 71 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信