Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 有没有更好的方法来实现水平滚动文本效果,模仿有限的字符显示?_String_Loops_Go_Command Line Interface_Slice - Fatal编程技术网

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

String 有没有更好的方法来实现水平滚动文本效果,模仿有限的字符显示?,string,loops,go,command-line-interface,slice,String,Loops,Go,Command Line Interface,Slice,我试图在命令行上模拟一个16个字符的显示,它在一个无限长的字符串上循环,类似于证券交易所的股票行情 现在,我首先打印ASCII字符串的第一个16字节片段,每次移动1个字节: 主程序包 进口( “fmt” “时间” ) 常数( 字符数=16 text=“Lorem Ipsum的段落有很多变体!!!” ) func main(){ fmt.Print(“\033[2J”)//清除屏幕 buf:=[]字节(文本) i:=chars 为了{ fmt.Print(“\033[H”)//将光标移回第一个位置

我试图在命令行上模拟一个16个字符的显示,它在一个无限长的字符串上循环,类似于证券交易所的股票行情

现在,我首先打印ASCII字符串的第一个16字节片段,每次移动1个字节:

主程序包
进口(
“fmt”
“时间”
)
常数(
字符数=16
text=“Lorem Ipsum的段落有很多变体!!!”
)
func main(){
fmt.Print(“\033[2J”)//清除屏幕
buf:=[]字节(文本)
i:=chars
为了{
fmt.Print(“\033[H”)//将光标移回第一个位置
fmt.Printf(字符串(buf[i-chars:i]))
我++
如果i==len(buf)+1{
i=字符
}
时间。睡眠(时间。秒/4)
//对正在发生的事情进行可视化:
//fmt.Printf(“\t\t字符:%d,长度:%d |切片:%d:%d\n”,i,len(buf),i-chars,i)
}
}
当我到达文本的末尾时,我重置了循环内的计数器,并从第一个切片开始再次打印。我不想这样做,而是想得到一种“翻转”效果,即切片的头部无缝连接到切片的尾部

问题是,我不能使用空缓冲区并在循环中将头部附加到尾部,因为它将无限增长

因此,我没有这样做,而是决定在循环之前将字符串的前16个字节附加到它的尾部,并立即收缩片段-16个字节。但是由于-16个字节仍然存在于备份数组中,我可以从循环中展开/收缩:

func main(){
fmt.Print(“\033[2J”)//清除屏幕
buf:=[]字节(文本)
buf=append(buf,buf[:chars]…)
buf=buf[:len(buf)-字符]
var扩展布尔
i:=chars
为了{
fmt.Print(“\033[H”)//将光标移回第一个位置
fmt.Printf(字符串(buf[i-chars:i]))
我++
如果i+1==len(buf)-chars&&!展开{
buf=buf[:len(buf)+字符]
扩展=真
}
如果i+1==len(buf){
i=字符
buf=buf[:len(buf)-字符]
扩展=错误
}
时间。睡眠(时间。秒/2)
//对正在发生的事情进行可视化:
//fmt.Printf(“\t\t字符:%d,长度:%d |切片:%d |封顶:%d\n”,i,len(buf),i-chars,i,Cap(buf))
}
}

这让我达到了我想要的目的,但我是一个新手,所以我想知道是否有更好的方法来达到同样的效果?

首先,我不会更改缓冲区。最好在缓冲区的末尾附加前16个字符,以便轻松获得“滚动”效果,但当到达终点时,只需将位置重置为
0
就更容易、更便宜了

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

也不要使用打印文本,因为它需要一个格式
字符串
(将其第一个参数视为格式字符串)。只需使用

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

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]