制作进度条小程序

进度条程序

  • 注意事项
    • 回车和换行
    • Linux刷新策略
    • fflush
  • 编写思路
  • 代码样例
  • 编译代码
    • make原理
    • make使用

在这里插入图片描述
这里我们来看一下如何制作一个动态增长的进度条小程序

注意事项

回车和换行

要想做一个动态增长的进度条程序,我们需要了解一下Linux下的屏幕刷新策略
执行下面一行代码我们可以看到程序在每间隔1秒的时候会换行打印从10到1的数字,但是进度条程序可不能进行换行打印,需要在同一行上打印,这时候就需要了解一下回车和换行的区别了。

#include
#include
int main()
{
  int count=10;
  while(count)
  {
    printf("%2d\n",count);
    count--;
    sleep(1);
  }
  return 0;
}

制作进度条小程序_第1张图片
很多人认为回车和换行是一个意思,其实不然,换行是从当前位置换到下一行,列不变,而回车则是回到当前行的最开始。我们在C语言中常用的\n代表的意思是回车换行,而回车则是使用\r选项 那让我们看看代码效果如何:

#include
#include

int main()
{
  int count=10;
  while(count)
  {
    printf("%2d\r",count);//进行回车操作
    count--;
    sleep(1);
  }
  return 0;
}

在这里插入图片描述
我们可以看到运行结果并没有打印出来,这是为什么呢?

Linux刷新策略

上面的测试用例我们可以看到使用\r进行回车,但是printf打印的值并没有显示到显示器上,这个原因就在于在Linux系统下虽然printf已经执行,但是数据没有被立即刷新到显示器上,没有\n字符串会先在用户缓冲区暂时保存起来,显示器刷新策略是行刷新即遇到\n立刻进行刷新。

fflush

fflush:这个函数的意思是立即刷新到输出流,我们可以看一下他的数据手册
制作进度条小程序_第2张图片
使用fflush函数后我们就可以将数据直接刷新到显示器上,测试代码如下:

#include
#include

int main()
{
  int count=10;
  while(count)
  {
    printf("%2d\r",count);
    fflush(stdout);
    count--;
    sleep(1);
  }
  return 0;
}

运行结果如下,这里可以看到他在动态的刷新从10到1的数字
在这里插入图片描述
在这里插入图片描述

编写思路

实现一个进度条小程序,代码还是比较简单的。
首先我们需要知道进度条的长度大小,一般是100,因此我们需要定义一个char类型的数组用来显示进度。

  char bar[NUM+1];//开辟进度条空间大小
  memset(bar,'\0',sizeof(bar));//将其都设置为\0打印时直接用%s即可按当前长度进行打印

然后我们使用一个循环加上sleep暂停函数来实现进度条的动态增长,这里printf需要使用的是\r回车操作

  while(i<=100)
  {
    printf("[%-100s][%-3d%%]\r",bar,i);//这里为了美观需要进行格式控制
    fflush(stdout);//立即刷新到显示器上
    bar[i]='*';//进度条用*代替 也可以使用#等字符
    i++;
    usleep(100000);//微秒 sleep的单位是s 因此在这里使用usleep使进度条刷新不至于过慢
  }

这样一来我们的大致的进度条程序就差不多完成了,但是想要更加美观一些我们可以在进度条最后加上一个选择的光标显示当前正在运行
在这里插入图片描述
想要实现这个光标还是比较简单的,我们可以定义一个字符串在里面输入光标种类,然后通过循环来控制光标的旋转

 const char* arr="|/-\\";
  while(i<=100)
  {
    printf("[%c]\r",arr[i%4]);//4种光标于是可以通过%4的方式来控制打印不同光标
    fflush(stdout);
    i++;
    usleep(100000);//微秒
  }

这样一来我们的光标旋转也完成了。

代码样例

这边我们看一下完成后的代码样例

#include
#include
#include

#define NUM 100

int main()
{
  char bar[NUM+1];//开辟进度条空间大小
  memset(bar,'\0',sizeof(bar));//将其都设置为\0
  int i=0;
  const char* arr="|/-\\";
  while(i<=100)
  {
    printf("\033[31m[%-100s][%-3d%%][%c]\r",bar,i,arr[i%4]);
    fflush(stdout);
    bar[i]='*';
    i++;
    usleep(100000);//微秒
  }
  printf("\n");
  return 0;
}

运行结果:
在这里插入图片描述

编译代码

在Linux系统下,如果想要编译代码每次都需要使用

gcc -o myprobar myprobar.c

这一类的命令时会显得比较麻烦,而且不方便进行大型项目的编译,因此在Linux系统下我们有make这个功能

make原理

  1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
  2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“myprobar.c”这个文件, 并把这个文件作为最终的目标文件。
  3. 如果该文件不存在,或是myprobar所依赖的后面的myprobar.o文件的文件修改时间要比myprobar这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成myprobar这个文件。
  4. 如果myprobar所依赖的myprobar.o文件不存在,那么make会在当前文件中找目标为myprobar.o文件的依赖性,如果找到则再根据那一个规则生成myprobar.o文件。(这有点像一个堆栈的过程)
  5. 当然,你的C文件和H文件是存在的啦,于是make会生成 myprobar.o 文件,然后再用 myprobar.o 文件声明 make的终极任务,也就是执行文件myprobar了。
  6. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文 件。
  7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错, 而对于所定义的命令的错误,或是编译不成功,make根本不理。
  8. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么make指令将无法执行

make使用

这里介绍一下make的简单用法,对于进度条程序,我们只需要进行项目的编译和清理即可,例如:

myprobar:myprobar.c
	gcc -o $@ $^
.PHONY:clean
clean:
	rm -f myprocbar

这里需要注意的是一般我们这种clean的目标文件,我们将它设置为伪目标,用 .PHONY修饰,伪目标的特性是,总是被执行的。

你可能感兴趣的:(C语言,Linux,C++,c语言,linux,c++)