方案
<?php
// 参考https://mengkang.net/1412.html
$width = exec("tput cols");
$progress = "[]100%";
$del = strlen($progress);
$width = $width - $del;
$progress = "[%-{$width}s]%d%%\r";
for($i=1;$i<=$width;$i++){
printf($progress,str_repeat("=",$i),($i/$width)*100);
usleep(30000);
}
echo "\n";
解释说明
-
tput cols
获取终端的“宽度”,实际是字符列数;
-
%s
我们知道是字符串的占位符;
-
%-{n}s
的意思是占位n
个字符,不足的用空格补充,这样在输出进度条的时候,最末尾的值的位置就是固定的;
-
%%
输出百分号;
- 最重要的一点,格式的末尾使用了
\r
则将光标移动到行首,则下次再输出时则把上次的整行覆盖,给人进度条动态变化的效果。
C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <unistd.h>
int main()
{
struct winsize size;
ioctl(STDIN_FILENO, TIOCGWINSZ, &size);
int width = size.ws_col;
const char *progress = "[]100%";
width = width - strlen(progress);
char width_str[10] = {0};
sprintf(width_str,"%d",width);
char progress_format[20] = {0};
strcat(progress_format,"[%-");
strcat(progress_format,width_str);
strcat(progress_format,"s]%d%%\r");
// printf("%s\n",progress_format);
// [%-92s]%d%%\r
char progress_bar[width+1];
memset(progress_bar,0,width+1);
for(int i=1;i<=width;i++){
strcat(progress_bar,"=");
printf(progress_format,progress_bar,(i*100/width));
// 或者使用
// fprintf(stdout,progress_format,progress_bar,(i*100/width));
fflush(stdout); // 必须刷新缓存区,否则会显得很卡顿
usleep(10000);
}
printf("\n");
return 0;
}