海林建设局网站,百度知道推广软件,wordpress水印,团队建设网站介绍写本文的起源是因为在安装一些工具的时候#xff0c;发现在终端上并行安装的情况下#xff0c;显示安装信息是会修改之前已经打印出来的内容#xff0c;这是怎么做到的呢#xff1f;抱着对这个问题的好奇我进行了一些探索。
终端是如何运行的
首先是最关键的问题#xf…写本文的起源是因为在安装一些工具的时候发现在终端上并行安装的情况下显示安装信息是会修改之前已经打印出来的内容这是怎么做到的呢抱着对这个问题的好奇我进行了一些探索。
终端是如何运行的
首先是最关键的问题终端是如何运行的
这个问题并不是我思考的第一个问题但是在写本文的时候我认为这是最关键的问题思考了这个文件那么面对一些问题就很好解释了
下面介绍一下标准输出stdout和 C/C 之间的工作流程 第一标准输出stdout是一个只读文件并不能进行修改终端将会显示这些内容。 第二如果是 C 语言那么printf()将内容输出到标准输出stdout中然后终端将会显示这些内容。 第三如果是 C那么cout将会输出内容到缓冲streambuf中最后在合适的机会将其传递给标准输出stdout中打印出来比如说遇到fflush()刷新或者\n换行符的时候。 可能你对上面的一些点还是很迷惑下面仔细来说说看。
刷新单行内容的最佳方法
如果是单行刷新可以使用转义字符\r或\b前者将会跳转到这行的开头再打印而后者会移到前一个字符的位置再打印带入一下旧式的打字机就可以理解了。
举个例子在同一行里从1循环到100既可以使用\b\b\b因为最大是三位数
#include stdio.h
#include unistd.hint main(int argc, char *argv[]) {int i 1;while (i100) {printf(%d\b\b\b, i);//休眠一秒再进入下次循环不然显示太快了sleep(1);}return 0;
}比较推荐使用\r这样就可以应对不同长度的数字。
但是二者在stdout中的内容并不会被覆盖而是如下情况
1\r2\r3\r4\r.......所以如果需要刷新多行内容这种方法就不行了。因为\r或\b本质上并不是删除了之前的内容而是在这里跳转了光标进行重新渲染输出标准输出中的内容并没有发生任何改变。而且二者的跳转都是横向跳转的\n是纵向的变化。
那么多行刷新应该怎么办呢
多行内容刷新的解决方案一使用 ANSI Code
这是一个诞生于上世纪七十年代的产物它被用于控制终端上光标的位置、颜色、字体等属性。ANSI Code 本质是一个 ASCII Code 的组合也是一种转义字符结构为\033[XX\033在 ASCII 中就是 “ESC”的意思转义字符的英文就是 “Escape Character”并且广泛应用于众多类 Unix 系统的终端中。
如果想打印出下面这样的情况只刷新第一行的数字
39
倒计时中那么就可以使用下面的代码注意还是使用了\r因为当前光标上移可能是在中间或最后的位置
#include stdio.h
#include unistd.hint main(int argc, char *argv[]) {int i 1;while (i100) {printf(%d\n, i);printf(倒计时中\033[A\r);sleep(1);}return 0;
}此外个人建议如果使用这种方法最好在循环外加上printf(\n);不然结束程序也可能会影响显示。
这里有篇文章记录了各种移动光标的转义字符可以当做手册查看《Bash Prompt HOWTO: Chapter 6. ANSI Escape Sequences: Colours and Cursor Movement》
你如果和我一样遍历过/bin那么你可能会发现知道ls列出的第一个程序就是[又名test也是确定“condition”的。不过这个是评估条件的而不是位置的这句话是一个小双关和 ANSI Code 并没有任何关系只是巧合。
多行内容刷新的解决方案二使用ncurses或Windows Console API
这种方法需要使用其他的库根据平台选择 ncurses类 Unix或Windows Console APIWindows。
个人不是很推荐这种方法
第一不是自带的有些终端不能用第二编译构建安装的时间有点长第三这种方法类似less会新建一个窗口或者清空窗口进行显示。这种方法的样式不是我需要的。
不过作为技术储备我还是进行了一些研究。
ncurses 的下载地址为https://invisible-island.net/ncurses/#download_ncurses。
下载之后解压配置安装的命令如下
$ tar zxvf ncurses-xxx.tar.gz
$ cd ncurses-xxx
$ ./configure
$ make -j4
$ sudo make install 安装好了之后编译的时候使用-lncurses连接库即可。下面是官方的一个案例这里假设这个文件为hello.c
#include ncurses.hint main()
{ initscr(); /* Start curses mode */printw(Hello World !!!); /* Print Hello World */refresh(); /* Print it on to the real screen */getch(); /* Wait for user input */endwin(); /* End curses mode */return 0;
}编译命令为
$ cc hello.c -lncurses然后运行即可看到结果 这里有很详细的官方文档https://tldp.org/HOWTO/NCURSES-Programming-HOWTO/可以看看。
希望能帮到有需要的人