0

0

【linux】进度条

爱谁谁

爱谁谁

发布时间:2025-06-26 12:26:31

|

171人浏览过

|

来源于php中文网

原创

  1. 屏幕缓冲区

屏幕缓冲区是指在输出设备(如终端或控制台)之前,数据被临时存储的内存区域。应用程序将输出数据写入这个缓冲区,然后系统会统一将缓冲区的内容刷新到屏幕上。使用缓冲区可以提高i/o操作的效率,因为它允许数据批量刷新,而不是每次输出都进行一次i/o操作。

缓冲区的刷新模式决定了何时将缓冲区内容刷新到终端屏幕上。主要有以下几种模式:

  • 全缓冲模式(Fully Buffered):数据只有在缓冲区满时才会被刷新到屏幕上,通常用于文件I/O。
  • 行缓冲模式(Line Buffered):当遇到换行字符(LF, \n)时,缓冲区内容会被刷新到屏幕上,常见于终端I/O。一些标准输出流(如stdout)在连接到终端时默认使用行缓冲模式。
  • 无缓冲模式(Unbuffered):数据每次写入缓冲区后立即被刷新到屏幕上,适用于需要实时输出的场景,如错误输出流(如stderr)通常是无缓冲的。

在屏幕缓冲区的刷新以及终端输出中,换行字符和回车字符起着重要作用:

  • 换行(Line Feed, \n):将光标移到下一行。在行缓冲模式下,遇到换行字符时,缓冲区的内容会被立即刷新到屏幕上。在许多现代终端和编程环境中,输出一个换行字符通常意味着会将当前行的数据刷新到屏幕。
  • 回车(Carriage Return, \r):将光标移动到当前行的起始位置(即行首),但不移动到下一行。常用于覆盖同一行内容,如进度条或动态日志输出。输出回车字符后,下一次的输出会从行首开始,覆盖当前行的内容。

换行和回车在屏幕缓冲区中的作用:

  • 行缓冲模式:换行字符(\n)会触发缓冲区刷新,将内容显示到屏幕上。
  • 回车字符(\r):不触发缓冲区刷新,而是移动光标,通常与手动刷新缓冲区结合使用,以实现动态行更新。

总结来说,缓冲区刷新模式(全缓冲、行缓冲和无缓冲)控制了何时将数据从缓冲区刷新到屏幕。换行字符(\n)在行缓冲模式下起到触发缓冲区刷新的作用,同时将光标移到下一行。回车字符(\r)将光标移动到行首,常用于覆盖当前行的内容,而不触发缓冲区刷新。综合使用换行和回车字符,可以实现灵活的终端输出效果,特别在实时显示和动态更新场景中非常常见。

从您提供的代码来看,您有两个几乎相同的代码块,但您希望了解的现象可能是与终端缓冲和输出可见性相关的。让我们总结并推测可能的观察现象。

代码块1:

#include 
#include   // For sleep()
int main() {
    printf("hello Makefile!\n");
    sleep(3);
    return 0;
}

代码块2:

#include 
#include   // For sleep()
int main() {
    printf("hello Makefile!");
    sleep(3);
    return 0;
}

终端输出现象:

  • 代码块1:输出字符串 “hello Makefile!” 后接换行符 \n。在行缓冲模式下,遇到 \n 立即刷新输出缓冲区内容到终端。您会立即看到 “hello Makefile!” 和换行,接下来程序会暂停3秒钟,然后退出。终端显示:
hello Makefile!
(暂停3秒钟)
  • 代码块2:输出字符串 “hello Makefile!”,但没有换行符 \n。在行缓冲模式下,由于没有遇到 \n,缓冲区不立即刷新到终端,除非缓冲区满或者进程结束。因为接下来代码调用 sleep(3) 而没有刷新缓冲区,所以在大多数情况下,您在终端上可能看不到立即的输出。直到程序退出或缓冲区被手动刷新,“hello Makefile!” 的内容才会显示。终端显示:
(暂停3秒钟)
hello Makefile!

如果希望在没有换行符的情况下立即刷新输出缓冲区,可以在 printf 后调用 fflush(stdout)

修改后的代码块2:

#include 
#include 
int main() {
    printf("hello Makefile!");
    fflush(stdout);    // 手动刷新标准输出缓冲区
    sleep(3);
    return 0;
}

这样做确保 “hello Makefile!” 会立即显示在终端上,不需要等到程序退出或缓冲区满。

终端显示:

Omneky
Omneky

用最先进的深度学习为客定制个性化的广告

下载
hello Makefile!
(暂停3秒钟)

总结:

  • 带有换行符 \nprintf 在行缓冲模式下会立即刷新到终端。
  • 没有换行符的 printf 可能不会立即刷新缓冲区,需要手动调用 fflush(stdout)
  • 使用 \nfflush(stdout) 确保输出立即可见,尤其是在待运行一段时间的代码(如 sleep())之后进行输出时。

这些现象主要源于终端缓冲机制的行为,在不同开发和调试环境中(特别是高速输出场景下)理解这些机制尤其有用。

  1. 进度条

有了上面缓冲区的知识,我们就可以实现一个简易版的进度条。

【linux】进度条

文件结构如下:

【linux】进度条【linux】进度条

准备工作完成后,我们下面只需完成进度条的主体代码即可。

#include"Processbar.h"
#include
#include
#define length 101
#define Style '#'
void Procbar(){
  char bar[101];
  memset(bar,'\0',sizeof(bar));
  int cnt=0;
  while(cnt < 100){
    printf("[%-100s][%d%%]\r", bar, cnt);
    fflush(stdout);
    bar[cnt++] = Style;
    usleep(10000);
  }
  printf("\n");
}

进度条显示函数 Procbar

  • char bar[length];:声明一个字符数组 bar,长度为 length(101 个字符),用于存储进度条的内容。
  • memset(bar, '\0', sizeof(bar));:将 bar 数组的所有元素初始化为\0,表示进度条初始为空。
  • int cnt = 0;:初始化一个整型变量 cnt,作为进度百分比,从0开始。
  • while(cnt :使用 while 循环,将 cnt 从0逐步增到100,模拟从0%到100%的进度条显示。
    • printf("[%-100s][%d%%]\r", bar, cnt);格式化输出进度条。%-100s表示左对齐,宽度为100的字符串,%d%%表示当前的百分比。\r 让光标返回行首。
    • fflush(stdout);:刷新标准输出,使得进度条及时更新。
    • bar[cnt++] = Style;:将 bar 数组的第 cnt 个位置设置为 #,并将 cnt 递增1,表示进度条推进一格。
    • usleep(10000);:暂停程序10毫秒,以模拟进度条的动态效果。
  • printf("\n");:循环结束后,打印一个换行符,结束进度条的显示。

优化版本:

【linux】进度条

我们设置文件大小和带宽速度,这时候进度条的函数需要进行修改。

#include"Processbar.h"
#include

void download()
{
  double filesize=100*1024*1024*1.0;
  double current=0.0;
  double bandwidth=1024*1024*1.0;
  printf("download begin,current: %lf\n",current);
  while(current < filesize){
    current += bandwidth;
    if(current > filesize) current = filesize;
    Procbar(filesize,current);
    usleep(10000);
  }
  printf("download finished,current: %lf\n",current);
}
#include"Processbar.h"
#include
#include

#define length 101
#define Style '#'

void Procbar(double total,double current)
{
  char bar[101];

  memset(bar,'\0',sizeof(bar));
  int cnt=0;
  double rate = (current*100.0)/total;
  int loop_count =(int)rate;

  while(cnt < loop_count){
    printf("[%-100s][%.2f%%]\r", bar, rate);
    fflush(stdout);
    bar[cnt++] = Style;
  }
  printf("[%-100s][%.2f%%]\r", bar, rate);
  fflush(stdout);
}

相关专题

更多
while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

90

2023.09.25

printf用法大全
printf用法大全

php中文网为大家提供printf用法大全,以及其他printf函数的相关文章、相关下载资源以及各种相关课程,供大家免费下载体验。

73

2023.06.20

fprintf和printf的区别
fprintf和printf的区别

fprintf和printf的区别在于输出的目标不同,printf输出到标准输出流,而fprintf输出到指定的文件流。根据需要选择合适的函数来进行输出操作。更多关于fprintf和printf的相关文章详情请看本专题下面的文章。php中文网欢迎大家前来学习。

281

2023.11.28

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

258

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

208

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1468

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

620

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

550

2024.03.22

PS使用蒙版相关教程
PS使用蒙版相关教程

本专题整合了ps使用蒙版相关教程,阅读专题下面的文章了解更多详细内容。

23

2026.01.19

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 5.4万人学习

Node.js 教程
Node.js 教程

共57课时 | 8.9万人学习

CSS3 教程
CSS3 教程

共18课时 | 4.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号