最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

前言

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

一、預(yù)備知識(shí)

1.1 回車換行

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

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

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

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

在這里插入圖片描述

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

1.2 緩沖區(qū)

先看一段代碼

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

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

在這里插入圖片描述

間隔兩秒后。

在這里插入圖片描述

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

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

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

在這里插入圖片描述

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

在這里插入圖片描述

情景分析

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

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

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

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

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

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

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

在這里插入圖片描述

Linux下一切皆文件,這三個(gè)流都是FILE*的指針,所以任何一個(gè)C語言程序運(yùn)行的時(shí)候,操作系統(tǒng)會(huì)幫我們打開以上三個(gè)文件。今天我們只需要關(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é)束也會(huì)刷新緩沖區(qū)。
  • fflush(stdout)可以手動(dòng)刷新緩沖區(qū)。

二、倒計(jì)時(shí)

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

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):

  • 每打印一個(gè)數(shù)字后緊跟著打印一個(gè)\r回車,讓光標(biāo)回到這一行最開始的位置,這樣新打印的數(shù)字就會(huì)去覆蓋掉老的數(shù)字。但是\r不會(huì)去刷新緩沖區(qū),因此在每打印完一個(gè)數(shù)字后,需要調(diào)用fflush(stdout)來刷新緩沖區(qū)。
  • 這里我們需要知道,往顯示器上打印整型10,本質(zhì)上是打印了字符1和字符0,由于這兩個(gè)字符是挨在一起的,我們看起來就像是整型10。因此打印10,會(huì)占用兩個(gè)字符,而打印0~9只需要一個(gè)字符,所以\r回車之后去覆蓋寫,只會(huì)覆蓋一個(gè)字符,對(duì)第二個(gè)字符0始終沒有影響,因此我們需要用%-2d來控制,每次打印兩個(gè)位寬的字符,-表示將這兩個(gè)字符左對(duì)齊。如果不進(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)橐还矔?huì)循環(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)度條并逐步延長(zhǎng)。
    • cnt代表當(dāng)前進(jìn)度百分比(從0到100)。
  2. 動(dòng)態(tài)旋轉(zhuǎn)提示:
    • lable是旋轉(zhuǎn)提示符,依次顯示|/-\,用來模擬動(dòng)態(tài)效果。
  3. 每次刷新屏幕:
    • 使用\r回到行首并覆蓋之前的內(nèi)容,fflush(stdout)刷新輸出緩沖區(qū),確保顯示即時(shí)更新。
    • 通過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)度條中的下一個(gè)字符
    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)容。
    • 動(dòng)態(tài)提示符從lable的第一個(gè)字符開始(|)。
  2. 每次循環(huán)中:
    • 動(dòng)態(tài)更新輸出:
      • 使用printf打印格式化輸出:
        • [%-100s]:打印一個(gè)左對(duì)齊的進(jìn)度條,長(zhǎng)度為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,在下一個(gè)位置設(shè)置占位符BODY(非滿狀態(tài)時(shí))。
    • 延遲:
      • usleep(100000)延遲0.1秒,控制進(jìn)度條更新的速度。
    • 覆蓋上一行:
      • 使用\r回到行首,使當(dāng)前輸出覆蓋上一行,達(dá)到刷新效果。
  3. 終止條件:
    • 當(dāng)cnt > TOP時(shí)退出循環(huán),表示進(jìn)度條已完成。

3.3 實(shí)際使用場(chǎng)景

上面的processBar.c中為了演示進(jìn)度條的原理,在里面寫了一個(gè)while循環(huán)來模擬,但實(shí)際上的進(jìn)度條并不是這樣用的。以下載東西為例,作為一個(gè)進(jìn)度條,它本身并不知道下載了多少,它只會(huì)提供一個(gè)接口,在下載東西的時(shí)候,調(diào)用這個(gè)接口,然后將已經(jīng)下載好的比率作為參數(shù)傳給進(jìn)度條模塊,它會(huì)根據(jù)比率打印出對(duì)應(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)用都會(huì)重現(xiàn)創(chuàng)建                         
void processbar(int ret){
	if(ret <0 || ret > 100){ 
		return;
	}
	if(ret == 0){ //當(dāng)比率為0的時(shí)候?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è)G  
    int cur = 0;//當(dāng)前下載的  
    while(cur <= total) {                                                    
        processbar(cur * 100 / total);                   
        usleep(50000);//模擬下載花費(fèi)時(shí)間                 
        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的時(shí)候?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個(gè)MB                                           
	int cur = 0;//當(dāng)前下載的                                                  
	while(cur <= total) {                                                      
		int rate = cur*100/total;
		ct(rate);       
		usleep(50000);//模擬下載花費(fèi)時(shí)間                            
		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ū)管理和動(dòng)態(tài)輸出功能是一項(xiàng)非常實(shí)用的技能。從回車換行的基礎(chǔ)概念到炫酷的進(jìn)度條展示,我們一步步地感受到了C語言的強(qiáng)大控制力以及其在終端交互中的無限潛力。希望本文能幫助你更好地理解Linux環(huán)境下C語言的這些核心知識(shí)點(diǎn),同時(shí)也為你的編程旅程增添更多的趣味與技巧!期待你在實(shí)踐中創(chuàng)造更多精彩!

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

相關(guān)文章

  • CentOS上安裝Jenkins的方法

    CentOS上安裝Jenkins的方法

    本篇文章主要介紹了CentOS上安裝 Jenkins的方法,Jenkins是開源的,使用Java編寫的持續(xù)集成的工具,在Centos上可以通過yum命令行直接安裝。
    2017-03-03
  • Centos5給/根分區(qū)擴(kuò)容

    Centos5給/根分區(qū)擴(kuò)容

    今天在調(diào)整VPS的時(shí)候發(fā)現(xiàn)自己的/分區(qū)的空間用光了.但是還剩下一個(gè)分區(qū)hda3沒動(dòng).于是乎.想調(diào)整到根下面去.但是由于本人新手一個(gè).又不太了解linux的分區(qū)機(jī)制.
    2010-06-06
  • Linux用戶建立腳本/猜字游戲/網(wǎng)卡流量監(jiān)控介紹

    Linux用戶建立腳本/猜字游戲/網(wǎng)卡流量監(jiān)控介紹

    大家好,本篇文章主要講的是Linux用戶建立腳本/猜字游戲/網(wǎng)卡流量監(jiān)控介紹,感興趣的同學(xué)趕快來看一看吧,對(duì)你有幫助的話記得收藏一下
    2021-12-12
  • shell腳本報(bào)錯(cuò):

    shell腳本報(bào)錯(cuò):"[: =: unary operator expected"解決辦法

    這篇文章主要介紹了shell腳本報(bào)錯(cuò):"[: =: unary operator expected"解決辦法的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • Linux 塊設(shè)備驅(qū)動(dòng)代碼編寫

    Linux 塊設(shè)備驅(qū)動(dòng)代碼編寫

    這篇文章主要介紹了Linux 塊設(shè)備驅(qū)動(dòng)代碼編寫,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-04-04
  • CentOS服務(wù)器離線部署DeepSeek用作AI本地知識(shí)庫

    CentOS服務(wù)器離線部署DeepSeek用作AI本地知識(shí)庫

    本文介紹了如何在CentOS服務(wù)器離線部署DeepSeek用作AI本地知識(shí)庫,首先,通過Ollama工具下載并安裝DeepSeek模型,根據(jù)硬件配置選擇合適的模型大小,然后使用Docker安裝AnythingLLM,并提供了建立知識(shí)庫的步驟,最后,對(duì)比了AnythingLLM、Dify和Open-WebUI的功能和適用場(chǎng)景
    2025-02-02
  • Linux內(nèi)核設(shè)備驅(qū)動(dòng)之系統(tǒng)調(diào)用筆記整理

    Linux內(nèi)核設(shè)備驅(qū)動(dòng)之系統(tǒng)調(diào)用筆記整理

    今天小編就為大家分享一篇關(guān)于Linux內(nèi)核設(shè)備驅(qū)動(dòng)之系統(tǒng)調(diào)用筆記整理,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2018-12-12
  • Linux操作系統(tǒng)下dump命令的使用及說明

    Linux操作系統(tǒng)下dump命令的使用及說明

    dump命令在Linux操作系統(tǒng)中用于備份文件系統(tǒng),支持全量和增量備份,可以將數(shù)據(jù)備份到多種存儲(chǔ)介質(zhì)
    2025-01-01
  • 如何創(chuàng)建Linux的swap交換分區(qū)文件的方法步驟

    如何創(chuàng)建Linux的swap交換分區(qū)文件的方法步驟

    這篇文章主要介紹了如何創(chuàng)建Linux的swap交換分區(qū)文件的方法步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2019-03-03
  • Linux實(shí)現(xiàn)免密登錄的配置方法

    Linux實(shí)現(xiàn)免密登錄的配置方法

    這篇文章主要介紹了Linux實(shí)現(xiàn)免密登錄的配置方法,實(shí)現(xiàn)的效果是,當(dāng)前服務(wù)器的test賬號(hào)可以免密登陸15服務(wù)器的test賬號(hào),需要的朋友可以參考下
    2024-04-04

最新評(píng)論

龙里县| 盘锦市| 郎溪县| 金平| 丹阳市| 白银市| 七台河市| 临城县| 抚远县| 乌恰县| 将乐县| 府谷县| 白城市| 个旧市| 昌平区| 泰宁县| 许昌市| 东方市| 凯里市| 正定县| 庆城县| 昭苏县| 武平县| 东宁县| 基隆市| 福贡县| 赤水市| 泗水县| 南靖县| 雷波县| 阿城市| 玛多县| 重庆市| 将乐县| 揭阳市| 淮南市| 巴林左旗| 宣威市| 朔州市| 岳西县| 武冈市|