欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Linux環(huán)境的進(jìn)度條實(shí)現(xiàn)方法

 更新時間:2025年01月08日 10:19:59   作者:.17.  
在Linux環(huán)境下,C語言的輸入輸出控制有其獨(dú)特的魅力和實(shí)際應(yīng)用場景,本文將從回車換行和緩沖區(qū)的基礎(chǔ)知識講起,帶領(lǐng)大家探索如何在Linux環(huán)境中實(shí)現(xiàn)一個動態(tài)倒計(jì)時功能,并進(jìn)一步完成一個具有交互感的進(jìn)度條,需要的朋友可以參考下

前言

在Linux環(huán)境下,C語言的輸入輸出控制有其獨(dú)特的魅力和實(shí)際應(yīng)用場景。本文將從回車換行和緩沖區(qū)的基礎(chǔ)知識講起,帶領(lǐng)大家探索如何在Linux環(huán)境中實(shí)現(xiàn)一個動態(tài)倒計(jì)時功能,并進(jìn)一步完成一個具有交互感的進(jìn)度條。通過這些內(nèi)容,你不僅可以理解C語言在Linux中的輸出行為,還能掌握如何通過代碼提升程序的可視化表現(xiàn)。無論是Linux開發(fā)初學(xué)者,還是想深入了解C語言底層實(shí)現(xiàn)的同學(xué),這篇文章都將為你帶來新的啟發(fā)。

一、預(yù)備知識

1.1 回車換行

真正意義上,回車換行其實(shí)是兩個動作,在C語言中\n卻同時完成了回車+換行的兩步動作。

  • 回車:將光標(biāo)移到當(dāng)前行的最左側(cè)
  • 換行:將光標(biāo)移到當(dāng)前行對應(yīng)位置的下一行

在C語言中可以使用轉(zhuǎn)義字符\n來實(shí)現(xiàn)單獨(dú)的回車行為。

如圖展示以下以前的老式鍵盤:

在這里插入圖片描述

這種電腦鍵盤上的ENTER按鍵就是同時實(shí)現(xiàn)了回車和換行的功能,按下ENTER鍵,光標(biāo)會去到下一行的最左側(cè)的位置。

1.2 緩沖區(qū)

先看一段代碼

#include <unistd.h>
int main() {
     printf("hello world\n");                                               
     sleep(2);
     return 0;
}

這段代碼很簡單,現(xiàn)在屏幕上打印出hello world,接著調(diào)用sleep函數(shù)讓程序休眠兩秒,

在這里插入圖片描述

間隔兩秒后。

在這里插入圖片描述

接下來,我們對上面的代碼稍作修改,去掉\n再來試試。

#include <unistd.h>
int main() {
     printf("hello world");                                  
     sleep(2);
     return 0;
}

在去掉/n后對代碼編譯運(yùn)行,先是休眠了兩秒,

在這里插入圖片描述

接著才在屏幕上打印出hello world,并且因?yàn)闆]有\n,所以打印完后沒有換行,導(dǎo)致命令行提示符就緊跟在打印結(jié)果的后面。

在這里插入圖片描述

情景分析

那么問題來了,這段代碼是先執(zhí)行sleep,還是先執(zhí)行printf打印呢?

很多人會根據(jù)上面的現(xiàn)象猜測,這段代碼先執(zhí)行了sleep休眠,再去執(zhí)行printf打印,這樣的猜測是錯誤的!因?yàn)槿魏我粋€C語言程序,都是嚴(yán)格按照代碼的編寫順序去執(zhí)行的。

那在休眠的兩秒期間,printf的打印結(jié)果存在哪里了呢?

hello world其實(shí)是保存在了緩沖區(qū)中,緩沖區(qū)是用于臨時存儲數(shù)據(jù)的內(nèi)存空間,默認(rèn)當(dāng)程序結(jié)束的時候才會將緩沖區(qū)中的內(nèi)容刷新出來

如何強(qiáng)制刷新緩沖區(qū)

任何一個C語言程序運(yùn)行的時候都會默認(rèn)幫我們打開以下三個流:

  • stdin - - - - 標(biāo)準(zhǔn)輸入流(鍵盤)
  • stdout - - - - 標(biāo)準(zhǔn)輸出流(顯示器)
  • stderr - - - - 標(biāo)準(zhǔn)錯誤(顯示器)

在這里插入圖片描述

Linux下一切皆文件,這三個流都是FILE*的指針,所以任何一個C語言程序運(yùn)行的時候,操作系統(tǒng)會幫我們打開以上三個文件。今天我們只需要關(guān)心stdout標(biāo)準(zhǔn)輸出流即可。我們可以通過fflush函數(shù)來刷新緩沖區(qū)。

#include <stdio.h>
#include <unistd.h>

int main(){
    printf("hello world");
    fflush(stdout);                                                                                          
    sleep(2);

    return 0;
}

在這里插入圖片描述

等待兩秒后…

在這里插入圖片描述

通過上面的分析我們可以得出,刷新緩沖區(qū)主要有以下幾種方法:

  • \n可以刷新緩沖區(qū)。
  • 程序結(jié)束也會刷新緩沖區(qū)。
  • fflush(stdout)可以手動刷新緩沖區(qū)。

二、倒計(jì)時

學(xué)習(xí)了上面的東西,我們可以先來實(shí)現(xiàn)一個簡單的倒計(jì)時練練手

2.1 源代碼

#include "processBar.h"
#include <unistd.h>

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

2.2 效果展示

從 10 開始計(jì)數(shù)

在這里插入圖片描述

直到變成 0 為止。

2.3 注意事項(xiàng):

  • 每打印一個數(shù)字后緊跟著打印一個\r回車,讓光標(biāo)回到這一行最開始的位置,這樣新打印的數(shù)字就會去覆蓋掉老的數(shù)字。但是\r不會去刷新緩沖區(qū),因此在每打印完一個數(shù)字后,需要調(diào)用fflush(stdout)來刷新緩沖區(qū)。
  • 這里我們需要知道,往顯示器上打印整型10,本質(zhì)上是打印了字符1和字符0,由于這兩個字符是挨在一起的,我們看起來就像是整型10。因此打印10,會占用兩個字符,而打印0~9只需要一個字符,所以\r回車之后去覆蓋寫,只會覆蓋一個字符,對第二個字符0始終沒有影響,因此我們需要用%-2d來控制,每次打印兩個位寬的字符,-表示將這兩個字符左對齊。如果不進(jìn)行格式化控制,打印出來的結(jié)果將是下面這樣:

在這里插入圖片描述

三、進(jìn)度條

3.1 源代碼

processBar.h

#pragma once
#include <stdio.h>
#define NUM 102
#define STYLE '='                                                                                                  
#define TOP 100
#define BODY '$'
extern void processbar();

processBar.c

#include "processBar.h"
#include <string.h>
#include <unistd.h>
const char* lable = "|/-\\";//旋轉(zhuǎn)提示
void processbar(){
    char bar[NUM];
    memset(bar, '\0', sizeof(bar));
	int len = strlen(lable);

	int cnt = 0;
	while(cnt <= TOP){
    	printf("[%-100s][%d%%][%c]\r", bar, cnt, lable[cnt%len]);
   		fflush(stdout);
    	bar[cnt++] = STYLE;
    	if(cnt < 100) {
        bar[cnt] = BODY;                                                                                           
    	}
    	usleep(100000);//以微秒為單位進(jìn)行休眠,想讓進(jìn)度條10秒跑完,因?yàn)橐还矔h(huán)101次,所以每次循環(huán)大概就是休眠0.1秒,100毫秒,10000微秒
	}
	printf("\n");
}

效果演示

在這里插入圖片描述

3.2 代碼分析

進(jìn)度條往右走的實(shí)現(xiàn)原理

  1. 進(jìn)度條的可視化:
    • bar表示進(jìn)度條的當(dāng)前狀態(tài),用字符填充進(jìn)度條并逐步延長。
    • cnt代表當(dāng)前進(jìn)度百分比(從0到100)。
  2. 動態(tài)旋轉(zhuǎn)提示:
    • lable是旋轉(zhuǎn)提示符,依次顯示|/-\,用來模擬動態(tài)效果。
  3. 每次刷新屏幕:
    • 使用\r回到行首并覆蓋之前的內(nèi)容,fflush(stdout)刷新輸出緩沖區(qū),確保顯示即時更新。
    • 通過usleep(100000)控制刷新間隔(每0.1秒更新一次)。

while循環(huán)邏輯分析:

while(cnt <= TOP) {
    printf("[%-100s][%d%%][%c]\r", bar, cnt, lable[cnt % len]);
    fflush(stdout);  // 強(qiáng)制刷新輸出緩沖
    bar[cnt++] = STYLE;  // 填充進(jìn)度條中的下一個字符
    if(cnt < 100) {
        bar[cnt] = BODY;  // 設(shè)置進(jìn)度條下一位置的占位符(非滿狀態(tài))
    }
    usleep(100000);  // 延遲0.1秒
}

分析逐步展開:

  1. 初始狀態(tài):
    • cnt0開始,bar數(shù)組全為空字符,進(jìn)度條未顯示任何填充內(nèi)容。
    • 動態(tài)提示符從lable的第一個字符開始(|)。
  2. 每次循環(huán)中:
    • 動態(tài)更新輸出:
      • 使用printf打印格式化輸出:
        • [%-100s]:打印一個左對齊的進(jìn)度條,長度為100字符。
        • [cnt%%]:打印當(dāng)前百分比。
        • [lable[cnt % len]]:顯示旋轉(zhuǎn)提示符,cnt % len保證提示符循環(huán)顯示。
    • 刷新進(jìn)度條:
      • bar[cnt++] = STYLE:在bar數(shù)組的第cnt位置填充進(jìn)度條樣式字符STYLE。
      • 如果cnt < 100,在下一個位置設(shè)置占位符BODY(非滿狀態(tài)時)。
    • 延遲:
      • usleep(100000)延遲0.1秒,控制進(jìn)度條更新的速度。
    • 覆蓋上一行:
      • 使用\r回到行首,使當(dāng)前輸出覆蓋上一行,達(dá)到刷新效果。
  3. 終止條件:
    • 當(dāng)cnt > TOP時退出循環(huán),表示進(jìn)度條已完成。

3.3 實(shí)際使用場景

上面的processBar.c中為了演示進(jìn)度條的原理,在里面寫了一個while循環(huán)來模擬,但實(shí)際上的進(jìn)度條并不是這樣用的。以下載東西為例,作為一個進(jìn)度條,它本身并不知道下載了多少,它只會提供一個接口,在下載東西的時候,調(diào)用這個接口,然后將已經(jīng)下載好的比率作為參數(shù)傳給進(jìn)度條模塊,它會根據(jù)比率打印出對應(yīng)的進(jìn)度條樣式。

版本一

//processBar.h
#pragma once
#include <stdio.h>
#define NUM 102
#define STYLE '='
#define TOP 100
#define BODY '>'
extern void processbar(int ret);
//processBar.c
#include "processBar.h"
#include <string.h>
#include <unistd.h>
const char* lable = "|/-\\";
//V2版本
char bar[NUM] = {'\0'};//定義在全局避免每一次函數(shù)調(diào)用都會重現(xiàn)創(chuàng)建                         
void processbar(int ret){
	if(ret <0 || ret > 100){ 
		return;
	}
	if(ret == 0){ //當(dāng)比率為0的時候?qū)?shù)組全置為'\0'
		memset(bar, '\0', sizeof(bar));
	}
	int len = strlen(lable);
	printf("[%-100s][%d%%][%c]\r", bar, ret, lable[ret%len]);
	fflush(stdout);
	bar[ret++] = STYLE;
	if(ret < 100){
		bar[ret] = BODY;
	}
}
//main.c
int main(){                                                 
    int total = 1000;//假設(shè)總共要下載1000個G  
    int cur = 0;//當(dāng)前下載的  
    while(cur <= total) {                                                    
        processbar(cur * 100 / total);                   
        usleep(50000);//模擬下載花費(fèi)時間                 
        cur += 10;//循環(huán)下載了一部分,更新進(jìn)度           
    }                                                    
   return 0;   
}

版本二

//processBar.h
#pragma once
#include <stdio.h>
#define NUM 102
#define STYLE '='
#define TOP 100
#define BODY '>'
extern void processbar(int ret);
//processBar.c
#include "processBar.h"
#include <string.h>
#include <unistd.h>
#define NONE "\033[m"
#define RED "\033[0;32;31M"
#define GREEN "\033[0;32;32m"
#define LIGHT_BLUE "\033[1;34m"
#define LIGHT_PURPLE "\033[1;35m"
const char* lable = "|/-\\";
//V2版本
char bar[NUM] = {'\0'};
void processbar(int ret){
	if(ret <0 || ret > 100)//合理性判斷{
		return;
	}
	if(ret == 0)//當(dāng)比率為0的時候?qū)?shù)組全置為'\0'{
		memset(bar, '\0', sizeof(bar));
	}
	int len = strlen(lable);
	printf("["LIGHT_BLUE"%-100s"NONE"]""[%d%%][%c]\r", bar, ret, lable[ret%len]); 
	fflush(stdout);                                                        
	bar[ret++] = STYLE;
	if(ret < 100){
		bar[ret] = BODY;
	}
}
//main.c
#include "processBar.h"                                                     
#include <unistd.h>                                                         
typedef void (*callback_t) (int);                                             
//模擬一種安裝或者下載                                                           
void Downbload(callback_t ct) {                                           
	int total = 1000;//假設(shè)總共要下載1000個MB                                           
	int cur = 0;//當(dāng)前下載的                                                  
	while(cur <= total) {                                                      
		int rate = cur*100/total;
		ct(rate);       
		usleep(50000);//模擬下載花費(fèi)時間                            
		cur += 10;//循環(huán)下載了一部分,更新進(jìn)度 
	}                  
	printf("\n");                               
}                                                                                
int main(){                                     
	printf("Downbload 1:\n");                                 
	Downbload(processbar);                                                                                               
	printf("Downbload 2:\n");                     
	Downbload(processbar);                                                                                     
	printf("Downbload 3:\n");                                       
	Downbload(processbar);                                                                                                     
	printf("Downbload 4:\n"); 
	Downbload(processbar);
	return 0;
}

效果展示

在這里插入圖片描述

結(jié)語

在Linux環(huán)境中,掌握C語言的緩沖區(qū)管理和動態(tài)輸出功能是一項(xiàng)非常實(shí)用的技能。從回車換行的基礎(chǔ)概念到炫酷的進(jìn)度條展示,我們一步步地感受到了C語言的強(qiáng)大控制力以及其在終端交互中的無限潛力。希望本文能幫助你更好地理解Linux環(huán)境下C語言的這些核心知識點(diǎn),同時也為你的編程旅程增添更多的趣味與技巧!期待你在實(shí)踐中創(chuàng)造更多精彩!

以上就是基于Linux環(huán)境的進(jìn)度條實(shí)現(xiàn)方法的詳細(xì)內(nèi)容,更多關(guān)于Linux實(shí)現(xiàn)進(jìn)度條的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • LNMP環(huán)境下搭建yum的方法分析

    LNMP環(huán)境下搭建yum的方法分析

    這篇文章主要介紹了LNMP環(huán)境下搭建yum的方法,結(jié)合實(shí)例形式較為詳細(xì)的分析了LNMP環(huán)境下搭建yum的相關(guān)命令、配置與使用技巧,需要的朋友可以參考下
    2018-03-03
  • Linux輸入輸出重定向詳細(xì)使用說明

    Linux輸入輸出重定向詳細(xì)使用說明

    Linux標(biāo)準(zhǔn)輸入、輸出設(shè)備主要是鍵盤和顯示器,輸出重定向是改變程序運(yùn)行的輸入來源和輸出地點(diǎn)
    2018-03-03
  • linux服務(wù)器磁盤爆滿的處理方案

    linux服務(wù)器磁盤爆滿的處理方案

    文章描述了Linux服務(wù)器磁盤爆滿導(dǎo)致Redis服務(wù)無法訪問的問題,通過一系列命令查找并刪除大文件,解決了磁盤空間不足的問題,同時,文章介紹了如何配置Nacos以防止日志文件過大導(dǎo)致磁盤空間爆滿,需要的朋友可以參考下
    2025-02-02
  • centos中yum命令刪除還原的補(bǔ)救方法介紹

    centos中yum命令刪除還原的補(bǔ)救方法介紹

    Yum: 即Yellowdog Update Modifier,是一種基于rpm的包管理工具,這篇文章主要給大家介紹了關(guān)于在centos中yum命令刪除還原的補(bǔ)救方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • Trash-Cli:Linux上的命令行回收站工具

    Trash-Cli:Linux上的命令行回收站工具

    今天小編就為大家分享一篇關(guān)于Linux上的命令行回收站工具,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2018-09-09
  • centos8 使用yum 安裝 rabbitmq的教程

    centos8 使用yum 安裝 rabbitmq的教程

    這篇文章主要介紹了centos8 yum 安裝 rabbitmq的教程,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-11-11
  • 新版ubuntu20.04 使用root用戶登錄系統(tǒng)的詳細(xì)教程

    新版ubuntu20.04 使用root用戶登錄系統(tǒng)的詳細(xì)教程

    這篇文章主要介紹了新版ubuntu20.04 使用root用戶登錄系統(tǒng)的詳細(xì)教程,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • 自制YUM倉庫的步驟講解

    自制YUM倉庫的步驟講解

    今天小編就為大家分享一篇關(guān)于自制YUM倉庫的步驟講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • linux環(huán)境下的Oracle部署教程

    linux環(huán)境下的Oracle部署教程

    這篇文章主要介紹了linux環(huán)境下的Oracle部署方法,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價值,需要的朋友可以參考下
    2019-09-09
  • ubuntu16.10安裝docker17.03.0-ce并配置國內(nèi)源和加速器

    ubuntu16.10安裝docker17.03.0-ce并配置國內(nèi)源和加速器

    這篇文章主要介紹了ubuntu16.10安裝docker17.03.0-ce并配置國內(nèi)源和加速器,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05

最新評論