当前位置:   article > 正文

Linux一个小程序--进度条_写一个linux小程序

写一个linux小程序

目录

回车换行的概念

进度条代码


回车换行的概念

        Linux中回车换行是两个概念。回车是将光标返回本行的第一个位置,换行是将光标列不变,行增加1,也就是说换行才是真正的换行,回车仅仅是将光标挪动到最前面。由这两个操作达到了换行的目的。

这两种代码有什么不同的现象呢?

        一个是不带\n换行的,一个是带\n的。不带\n的现象会先停5s,再显示结果,带\n会先显示结果,再停止5s。这种现象就说明Hello wolrd数据并没有丢失,但是不带\n的先休眠5s再显示结果,这难道是sleep先于printf运行吗?

        其实并不是,这是因为printf已经执行,但是数据没有被立即刷新到显示器当中!当没有\n的时候,字符串会暂时保存起来!会保存到用户C语言级别的缓冲区,显示器设备刷新策略就是行刷新,遇到\n即进行刷新!

        凡是显示到显示器上面的内容都是字符printf("%d\n"x);x=123,凡是从键盘读取内容的也都是字符,我们将显示器和键盘统称为字符设备

 那么有没有什么不用写\n而且还能先显示数据的方法呢?

这里C标准库中会提供一个函数接口,fflush(),他是属于文件流

 

 在程序中,无论什么语言,都会默认打开三个输入输出流:stdin,stdout,stderr。分别代表键盘,显示器,显示器。这三个的存在就是为了将数据写进程序,通过程序的数据结构管理,输出结果/错误输出,才有了这几个文件流。

回到我们的主题,运用fflush,可将数据输出到显示器上,不必再写\n,就可以先显示数据,再执行sleep。

  1. [wjy@VM-24-9-centos test02]$ cat myproc.c
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. int main()
  5. {
  6. printf("Hello world!");
  7. fflush(stdout);
  8. sleep(5);
  9. return 0;
  10. }
  11. [wjy@VM-24-9-centos test02]$ make clean;make
  12. rm -f mytest myproc
  13. gcc -o myproc myproc.c -std=c99
  14. [wjy@VM-24-9-centos test02]$ ./myproc
  15. Hello world![wjy@VM-24-9-centos test02]$

进度条代码

        当写一个倒计时程序,如何能在同一位置依次写入不同数据?

        通过上面我们知道只回车,那么光标会回到该行的第一个位置,回车一次就会将上一次的数据覆盖

        那么想要回车不换行的命令是\r,此时可以做到不换行,但是数据并没有立即显示到屏幕上,这里就用到了fflush将数据先打印到屏幕上再sleep。这样就达到了倒计时的效果。

  1. [wjy@VM-24-9-centos test02]$ cat mycode.c
  2. #include <stdio.h>
  3. #include <unistd.h>
  4. int main()
  5. {
  6. int count=10;
  7. while(count)
  8. {
  9. printf("%2d\r",count);//2d预留出两个位置空间
  10. fflush(stdout);
  11. count--;
  12. sleep(1);
  13. }
  14. return 0;
  15. }

根据这种情况,我们写一个缓冲区

  1. [wjy@VM-24-9-centos test02]$ cat bar.c
  2. #include<stdio.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. int main()
  6. {
  7. #define NUM 100
  8. char bar[NUM+1];//缓冲区
  9. memset(bar,'\0',sizeof(bar));//初始化
  10. //放‘#’字符
  11. for(int i=0;i<sizeof(bar);i++)
  12. {
  13. //先打印,因为第一次i=0不需要打印#字符
  14. printf("%s\r",bar);//如果只是“%s”,什么都没有,那么#累加的结果会一直+=在字符串后面
  15. //加\r回车命令,覆盖上一次的结果,每次达到加1的效果。
  16. bar[i]='#';
  17. fflush(stdout);
  18. usleep(10000);
  19. }
  20. return 0;
  21. }

这仅仅是打印出进度条,为了美观,我们可以加上【】包起来,并且在后面显示进度条进度百分比。

  1. int main()
  2. {
  3. #define NUM 100
  4. char bar[NUM+1];
  5. memset(bar,'\0',sizeof(bar));
  6. int i=0;
  7. while(i<=100)
  8. {
  9. printf("[%-100s][%-3d%%]",bar,i);
  10. //因为linux系统是右对齐,会从右向左打印#,所以加上-
  11. //因为一个%不能显示%字符,两个%%才能打印出%
  12. fflush(stdout);
  13. bar[i]='#';
  14. i++;
  15. usleep(50000);
  16. }
  17. printf("\n");
  18. }

作为进度条,我们需要时刻关注它是否在运行,可以做一个运转图形化图标。当一个圆圈在转动,分别用|/—\组成,他们不停显示,达到圆圈转动效果,而\作为转义字符,需要两个反斜杠才能表示出”\“字符。

在循环之内,为了遇到该位置下标的字符就显示它,所以需要模一个4,这样才能得到其下标。

printf("[%-100s][%-3d%%] %c\r",bar,i,lable[i%4]);

这样才算完成了这样一个简易的进度条


做好了框架,我们也可以再优化一下,做一些细枝末节

比如所配色问题,可以直接搜printf配色,这里我就不详细介绍,举个例子,将printf打印设为红色字体,在输出行前加上‘\033[31m’

 printf("\033[31m[%-100s][%-3d%%] [%c]\r",bar,i,lable[i%4]);
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/322608
推荐阅读
相关标签
  

闽ICP备14008679号