进度条小程序

文章目录

铺垫

回车换行

回车和换行是两个独立的动作

回车是将光标移动到当前行的最开始(最左侧)

换行是竖直向下平移一行

在C语言中,\n是同时进行了回车换行,\r实现了回车操作

缓冲区

概述

先来看一个小现象:

实例代码:

shell 复制代码
#include<stdio.h>                                                                                                                       
#include<unistd.h>
int main()
{
	printf("hello gwj,hello Linux...\n");
    sleep(3);
    return 0;
}

运行mytest.exe执行程序,会输出hello gwj,hello Linux...,紧接着调用sleep函数,休眠三秒

如果将printf函数中\n删掉,会出现什么结果呢??


现象:先休眠三秒,在最后结束的狮虎打印出内容

这这种场景中,sleep函数和printf函数,哪一个先运行的呢??

答案是printf先运行,在休眠的这三秒时间里,printf已经执行完了,字符串被保存在缓冲区

缓冲区的概念需要在操作系统层面上理解,单纯在语言基础上是很难理解的

缓冲区是一个内存空间,当休眠的时候,字符串在缓冲区里,当程序结束return 0时,,强制冲刷缓冲区,再打印出字符串。

强制冲刷缓冲区

任何一个C语言程序都会默认打开三个流:

  • stdin:标准输入流
  • stdout:标准输出流
  • stderr比爱准错错误

可以通过fflush函数来刷新缓冲区

示例代码:

powershell 复制代码
   #include<stdio.h>
   #include<unistd.h>
   int main()
   {
     printf("hello gwj,hello Linux...");
     fflush(stdout);                                                                                                                       
     sleep(3);
   
     return 0;
 }


现象:

简单实现倒计时功能

示例代码:

powershell 复制代码
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 int main()
  4 {
  5   int cnt=9;
  6   while(cnt>=0)
  7   {
  8     printf("%d\r",cnt);
  9     fflush(stdout);                                                                                                                     
 10     cnt--;
 11     sleep(1);
 12   }
 13   return 0;
 14 }

效果展示:

代码解读:

倒计时使用新数字去覆盖老数字,并且都出一同一位置,因此在printf函数里不能使用\n,使用换行会让新数字在老数字下面。

正确做法是在printf函数后面使用\r回车符号,每打印一个数字,让光标回到这一行最开始的位置,这样打印出来的新数字就会覆盖旧数字。

但是\r不会冲刷缓冲区,因此每打印完一个数字调用 fflush(stdout)来冲刷缓冲区。

进度条小程序

版本一

实例代码

Processbar.h文件:

powershell 复制代码
#pragma once 

#include<stdio.h>

void ProcBar();      
powershell 复制代码
#include"Processbar.h"    
#include<string.h>    
#include<unistd.h>    
    
#define Length 101    
#define Style '#'    
    
const char *lable="|/-\\";    
    
//version1:    
void ProcBar()    
{    
  char bar[Length];    
  memset(bar,'\0',sizeof(bar));    
  int len=strlen(lable);    
    
  int cnt=0;    
  while(cnt<=100)    
  {    
    printf("[%-100s][%3d%%][%c]\r",bar,cnt,lable[cnt%len]);                                                                                 
    fflush(stdout);    
    bar[cnt]=Style;    
    cnt++;    
    usleep(20000);    
  }    
  printf("\n");    
}  

效果展示

分析

该进度条的原理是一次比一次多打印一点内容、

定义一个bar数组,通过循环,每次多打印一个字符,视觉上就会形成进度条是从右向左走

由于进度条每次打印是在同一行上,因此需要\r符号,让光标回到最开始的位置

版本二

Processbar.h文件:

powershell 复制代码
#pragma once    
    
#include <stdio.h>    
    
typedef void(*callback_t)(double, double);    

void ProcBar(double total, double current);                                                                                                 

Main.c文件:

powershell 复制代码
void download(double filesize,callback_t cb)    
{    
    double current = 0.0;    
    
    printf("download begin, current: %lf\n", current);    
    while(current <= filesize)    
    {    
        cb(filesize, current);    
        //从网络中获取数据                                                                                                                  
        usleep(100000);    
        current += bandwidth;    
    }    
    printf("\ndownload done, filesize: %lf\n",filesize);    
}    
    
int main()    
{    
    download(100*1024*1024,ProcBar);    
    download(2*1024*1024,ProcBar);    
    
    return 0;    
}    

Processbar.c文件:

powershell 复制代码
#include"Processbar.h"    
#include<string.h>    
#include<unistd.h>    
    
#define Length 101    
#define Style '#'  

//version 2                                                                   
void ProcBar(double total, double current)                                    
{                                                                             
    char bar[Length];                                                         
    memset(bar, '\0', sizeof(bar));                                           
    int len = strlen(lable);                                                  
                                                                              
    int cnt = 0;                                                              
    double rate = (current*100.0)/total;                                      
    int loop_count = (int)rate;                                               
    while(cnt <= loop_count)                                                  
    {                                                                         
        bar[cnt++] = Style;                                                   
        usleep(20000);                                                                                                                      
    }                                             
    printf("[%-100s][%.1lf%%][%c]\r", bar, rate, lable[cnt%len]);    
    fflush(stdout);    
}  

效果展示:

相关推荐
乔冠宇5 分钟前
微信小程序中将图片截图为正方形(自动居中)
微信小程序·小程序·typescript·uniapp
卷卷的小趴菜学编程9 分钟前
c++之多态
c语言·开发语言·c++·面试·visual studio code
播播资源21 分钟前
ChatGPT付费创作系统V3.1.3独立版 WEB端+H5端+小程序端 (DeepSeek高级通道+推理输出格式)安装教程
前端·ai·chatgpt·ai作画·小程序·deepseek·deepseek-v3
安冬的码畜日常41 分钟前
【Mastering Vim 2_05】第四章:深入理解 Vim 的结构化文本
编辑器·vim·undotree·文本编辑·ctags·youcompleteme·结构化文本
你好呀我是裤裤1 小时前
Linux基础开发工具的使用(apt、vim、gcc、g++、gdb、make、makefile)
linux·运维·vim
大白的编程日记.2 小时前
【C++笔记】C+11深度剖析(三)
c语言·开发语言·c++
莲动渔舟2 小时前
国产编辑器EverEdit - 语法着色及嵌入式多语言着色
编辑器·emeditor·notepad·everedit
莲动渔舟2 小时前
国产编辑器EverEdit - 如何在EverEdit中管理工程?
编辑器·emeditor·notepad·everedit
Et2nity2 小时前
tiptap md 编辑器实用场景开发
前端·javascript·编辑器·markdown
和光同尘@3 小时前
56. 合并区间 (LeetCode 热题 100)
c语言·开发语言·数据结构·c++·算法·leetcode·职场和发展