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。

[wjy@VM-24-9-centos test02]$ cat myproc.c
#include <stdio.h>
#include <unistd.h>

int main()
{
  printf("Hello world!");
  fflush(stdout);

  sleep(5);
  return 0;
}
[wjy@VM-24-9-centos test02]$ make clean;make
rm -f mytest myproc
gcc -o myproc myproc.c -std=c99
[wjy@VM-24-9-centos test02]$ ./myproc
Hello world![wjy@VM-24-9-centos test02]$

进度条代码

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

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

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

[wjy@VM-24-9-centos test02]$ cat mycode.c
#include <stdio.h>
#include <unistd.h>

int main()
{
  int count=10;
  while(count)
  {
    printf("%2d\r",count);//2d预留出两个位置空间
    fflush(stdout);
    count--;
    sleep(1);
  }
  return 0;
}

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

[wjy@VM-24-9-centos test02]$ cat bar.c
#include<stdio.h>
#include <string.h>
#include <unistd.h>

int main()
{
#define NUM 100
  char bar[NUM+1];//缓冲区
  memset(bar,'\0',sizeof(bar));//初始化

  //放‘#’字符
  for(int i=0;i<sizeof(bar);i++)
  {
    //先打印,因为第一次i=0不需要打印#字符
    printf("%s\r",bar);//如果只是“%s”,什么都没有,那么#累加的结果会一直+=在字符串后面
    //加\r回车命令,覆盖上一次的结果,每次达到加1的效果。
    bar[i]='#';
    fflush(stdout);
    usleep(10000);
  }
  return 0;
}

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

int main()
{
#define NUM 100
  char bar[NUM+1];
  memset(bar,'\0',sizeof(bar));

  int i=0;
  while(i<=100)
  {
    printf("[%-100s][%-3d%%]",bar,i);
    //因为linux系统是右对齐,会从右向左打印#,所以加上-
    //因为一个%不能显示%字符,两个%%才能打印出%
    fflush(stdout); 
    bar[i]='#';
    i++;
    usleep(50000);
  }
  printf("\n");
  
}

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

在循环之内,为了遇到该位置下标的字符就显示它,所以需要模一个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]);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值