文章目录
Linux第一个小程序-进度条
相关知识
特殊符号:
$@和$^
回车换行:回车和换行其实是两个东西。
回车:挪到下一行的最前面。
换行:挪到下一行的当前位置,就是从上往下。
缓冲区:
创建程序
1. 程序原理
我们先创建一个文件夹,进去

然后创建3个文件

然后进入processBar.h,写一下

然后往main.c里面写一点东西。

然后创建makefile文件,进去编写代码
            
            
              bash
              
              
            
          
          processbar:processBar.c main.c
        gcc -o $@ $^
.PHONY:clean
clean:
        rm -f processbar然后进入main.c,修改代码
            
            
              c
              
              
            
          
          # include "processBar.h"
#include <unistd.h>
int main()
{
        printf("hello world\n");
        sleep(2);//这个要用到unistd.h头文件
        return 0;
}现象是先打印hello world,然后休眠2s。

然后进入main.c,修改代码,去掉\n,那么现象会是什么呢?
是先打印hello world,然后休眠2s还是先休眠2s,然后打印hello world呢?
            
            
              c
              
              
            
          
          # include "processBar.h"
#include <unistd.h>
int main()
{
        printf("hello world");//1
        sleep(2);             //2
        return 0;
}得到的现象是先休眠2s,然后打印hello world。

咦,怎么会这样?难道先执行了第二条语句,然后执行第一条语句吗?
当然不是。
C语言是按顺序执行的,所以执行顺序一定是先执行第一条语句,再执行第二条语句。
那为什么会这样呢?
sleep期间,printf语句执行完了,那么它在这两秒内怎么了呢?
因为后面还是打印出来了,说明printf一定被保存起来了。
保存在了C语言的缓冲区,这个缓冲区就是指由C语言维护的一段内存。
如果我要强制刷新呢?
C语言文件默认打开3个文件:标准输入流,标准输出流(显示器显示),标准错误流
我们继续更改一下main.c文件,添加一行代码:
            
            
              c
              
              
            
          
          # include "processBar.h"
#include <unistd.h>
int main()
{
        printf("hello world");//1
        fflush(stdout); // 强制刷新标准输出缓冲区
        sleep(2);             //2
        return 0;
}再次运行的结果就不一样了,现象是先打印hello world,然后休眠2s。
关键点解释:
printf("hello world");
- 将字符串输出到标准输出
- 但由于缓冲机制,不一定立即显示在屏幕上
- 内容可能暂存在缓冲区中
fflush(stdout);
- 强制刷新标准输出缓冲区
- 确保"hello world"立即显示在屏幕上
- 不使用fflush时,内容可能要等到缓冲区满或程序结束才显示
sleep(2);
- 让程序暂停执行2秒
- 单位是秒
- 这期间程序什么都不做
如果去掉
fflush(stdout):
- "hello world"可能要等到程序结束才显示
- 因为程序很快就结束了,用户可能看不到2秒暂停的效果
2. 基础程序原理实现
好的 ,通过上面的原理,应该都知道了缓冲区的存在了。
比如我们输入一个9,那么光标就跑到9的后面了。
我们在9的前面输入一个8,那么9就被挤到8的后面了,得到了89
我们进入main.c文件,更改一下代码:
            
            
              c
              
              
            
          
          # include "processBar.h"
#include <unistd.h>
int main()
{
        //倒计时
        int cnt = 9;
        while(cnt){
                printf("%d",cnt);
                fflush(stdout);
                cnt--;
                sleep(2);
        }
        //printf("hello world");//1
        //fflush(stdout);
        //sleep(2);             //2
        return 0;
}得到:



但是这个不是让光标回到最开始写的,怎么修改呢?
我们加个\r就可以了
            
            
              c
              
              
            
          
          # include "processBar.h"
#include <unistd.h>
int main()
{
        //倒计时
        int cnt = 9;
        while(cnt){
                printf("%d\r",cnt);
                fflush(stdout);
                cnt--;
                sleep(2);
        }
    	printf("\n");
        //printf("hello world");//1
        //fflush(stdout);
        //sleep(2);             //2
        return 0;
}打印:


实现了一个简单的倒计时。
不过表面上看起来我们实现的很完美,可是如果倒计时变成两位数的话:
            
            
              c
              
              
            
          
          # include "processBar.h"
#include <unistd.h>
int main()
{
        //倒计时
        int cnt = 10;
        while(cnt>=0){
                printf("%d\r",cnt);
                fflush(stdout);
                cnt--;
                sleep(2);
        }
        printf("\n");
        //printf("hello world");//1
        //fflush(stdout);
        //sleep(2);             //2
        return 0;
}程序打印为:
10 --> 90 -->80。。。
因为打印的是字符。
这里我们只需要加一个-2就可以了,%-2d一次打印两个字符,而且是左对齐。
            
            
              bash
              
              
            
          
          # include "processBar.h"
#include <unistd.h>
int main()
{
        //倒计时
        int cnt = 10;
        while(cnt>=0){
                printf("%-2d\r",cnt);
                fflush(stdout);
                cnt--;
                sleep(2);
        }
        printf("\n");
        //printf("hello world");//1
        //fflush(stdout);
        //sleep(2);             //2
        return 0;
}井号进度条代码实现
processBar.c
            
            
              c
              
              
            
          
          #include "processBar.h"
#include <string.h>
#include <unistd.h>
const char *lable="|/-\\";
void processbar()
{
        char bar[NUM];
        memset(bar,'\0',sizeof(bar));
        int len=strlen(lable);
        int cnt=0;
        while(cnt<=100)
        {
                printf("[%-100s][%d%%][%c]\r",bar,cnt,lable[cnt%len]);
                fflush(stdout);
                bar[cnt++]=STYLE;
                usleep(100000);
        }
        printf("\n");
}processBar.h
            
            
              c
              
              
            
          
          #pragma once
  
#include <stdio.h>
#define NUM 102
#define STYLE '#'
extern void processbar();main.c
            
            
              c
              
              
            
          
          # include "processBar.h"
#include <unistd.h>
int main()
{
    processbar();
    return 0;
}实现效果:


箭头进度条代码实现
processBar.c
            
            
              c
              
              
            
          
          #include "processBar.h"
#include <string.h>
#include <unistd.h>
const char *lable="|/-\\";
void processbar()
{
        char bar[NUM];
        memset(bar,'\0',sizeof(bar));
        int len=strlen(lable);
        int cnt=0;
        while(cnt<=100)
        {
                printf("[%-100s][%d%%][%c]\r",bar,cnt,lable[cnt%len]);
                fflush(stdout);
                bar[cnt++]=STYLE;
                if(cnt <=100) bar[cnt]='>';
                usleep(100000);
        }
        printf("\n");
}processBar.h
            
            
              c
              
              
            
          
          #pragma once
  
#include <stdio.h>
#define NUM 102
#define STYLE '-'
extern void processbar();main.c
            
            
              c
              
              
            
          
          # include "processBar.h"
#include <unistd.h>
int main()
{
    processbar();
    return 0;
}实现效果:


多重进度条代码实现
processBar.c
            
            
              c
              
              
            
          
          #include "processBar.h"
#include <string.h>
#include <unistd.h>
const char *lable="|/-\\";
char bar[NUM];
void processbar(int rate)
{
    if(rate<0||rate>100) return;
    int len=strlen(lable);
    printf("[%-100s][%d%%][%c]\r",bar,rate,lable[rate%len]);
    fflush(stdout);
    bar[rate++]=BODY;
    if(rate <100) bar[rate]=RIGHT;
}
void initbar()
{
    memset(bar,'\0',sizeof(bar));
}processBar.h
            
            
              c
              
              
            
          
          #pragma once
  
#include <stdio.h>
#define NUM 102
#define TOP 100
#define BODY '='
#define RIGHT '>'
extern void processbar(int rate);
extern void initbar();main.c
            
            
              c
              
              
            
          
          # include "processBar.h"
#include <unistd.h>
typedef void (*callback_t)(int);
void downLoad(callback_t cd)
{
    int total = 1000; //1000MB
    int curr = 0; //0MB
    while(curr <= total){
        usleep(50000);
        int rate=curr*100/total;
        cd(rate);
        curr+=10;
    }
    printf("\n");
}
int main()
{
    printf("download 1: \n");
    downLoad(processbar);
    initbar();
    printf("download 2: \n");
    downLoad(processbar);
    initbar();
    printf("download 3: \n");
    downLoad(processbar);
    initbar();
    printf("download 4: \n");
    downLoad(processbar);
    initbar();
    return 0;
}实现效果:
