【Linux 學習計劃】-- 倒計時、進度條小程序

目錄

\r 、\n、fflush

倒計時

進度條

進度條進階版

結語


\r 、\n、fflush

首先我們先來認識這三個東西,這將會是我們接下來兩個小程序的重點之一

首先是我們的老演員\n,也就是回車加換行

這里面其實包含了兩個操作,一個叫做回車,一個叫做換行

而單純的回車就是指,我們現在的光標,回到當前行的最前面

而換行 + 回車就是來到下一行的最前面

而我們的 \r 就是單純的回車,回到當前行的最前面

但是我們還有一個緩沖區的概念

也就是,當我們使用了\n之后就會自動刷新緩沖區,但是\r不會

我們不想用\n是因為不想出現下面這樣的情況:

所以我們只想回到第一行然后從頭開始覆蓋式地進行寫入

但是如果是\r的話,就會出現一個情況就是,我們會等到程序結束之后才會把最后一次的結果打印出來,這時因為緩沖區不會因為\r刷新

所以我們這時候就需要fflush(stdout),這樣就能在不回車的前提下達到提前刷新緩沖區的效果了

至于stdout,這就是系統默認打開的標準輸出文件,其實我們這里可以粗淺的看作就是顯示器,我們需要刷新緩沖區才能讓顯示器上顯示結果

倒計時

至于倒計時,其實相當簡單,我們只需要知道,這是在不停地打印數字,并且會在同一個位置打印,這就需要用到回車(\r)回到最前面,然后覆蓋掉前面的結果以達到原地變化的效果

但是由于\r不會刷新緩沖區,所以我們就需要使用fflush刷新,這樣,我們的倒計時就寫好了

代碼如下:

void time_count_down(int total)
{int cnt = total;while(cnt >= 0){printf("倒計時: %2d\r", cnt);fflush(stdout);cnt--;usleep(300000);}printf("\n");
}

進度條

首先,我們需要知道的是,進度條的本質和倒計時是一樣的,就是\r移動光標,通過覆蓋式寫入達到變化的效果

我們先來看看成品的樣子:

分析一下,首先我們需要預留出一百個空間,表現出遞進的效果

這一步我們可以直接建一個數組,然后一個循環,每循環一次,就打印出當前數組里面的內容,并且在當前數組最后一個 “ = ” 后面再加一個等號,這樣,我們就達到了循環遞進的效果

但是,我們需要注意的是,這期間我們需要一直使用 \r 和 fflush,如下:

#define LENGTH 101
#define STYLE '='void ProcessBar()
{char bar[LENGTH];memset(bar, '\0', sizeof bar);int cnt = 0;while(cnt <= 100){printf("[%-100s]\r", bar);fflush(stdout);bar[cnt++] = STYLE;usleep(10000);}printf("\n");
}

注意,上面的 “%-100d” 中,100就代表默認留出100個位置,-100則代表左對齊

接著,我們可以看到,進度條后面還有兩個東西:

這兩個,一個是實時顯示當前加載進度的數字顯示,還有一個是想通過 |/-\ 這四個字符,達成一條線在不停旋轉的動態效果,也就是在提醒用戶,可能用戶看到進度條不動了以為是網卡了,但其實還在下載,只是進度比較慢,暫時卡住了而已,動態的話就是為了避免這個問題

首先來解決第一個

這個其實我們只需要把數字填進去就可以了,只是后面的%需要寫兩個而已,寫一個顯示不出來

而最后一個就是,我們先寫一個數組:

const char* label = "|/-\\";

我們只需要不停的從左往右選擇即可,但是由于會越界,所以我們就需要%一個數組大小,這樣才不會越界

而其中 \\ 有兩個是因為只寫一個不顯示

比如,我現在數組大小是4,如果當前數字大小是4,4%4 = 0,那么就會直接回到第一個數組下標位置,5%4就是1,代表第二個位置,依此類推

總代碼如下:

#define LENGTH 101
#define STYLE '='
const char* label = "|/-\\";void ProcessBar()
{char bar[LENGTH];memset(bar, '\0', sizeof bar);int len = strlen(label);int cnt = 0;while(cnt <= 100){printf("[%-100s][%3d%%][%c]\r", bar, cnt, label[cnt % len]);fflush(stdout);bar[cnt++] = STYLE;usleep(10000);}printf("\n");
}

進度條進階版

現實中,我們的進度條都是搭配了任務一起的

比如我們可以寫一個下載的任務,影響下載的因素這里假設只有帶寬,他就相當于下載速度吧在這里

然后我們只需要提供一個文件總大小,模擬這個過程即可

代碼如下(模擬下載任務的代碼):

#define bandwidth 1024*1024*1.0;void download(double file_size)
{double current = 0.0;while(current <= file_size){//調用進度條ProcessBar(file_size, current);current += bandwidth;usleep(20000);}printf("\n");
}

這時候我們的進度條文件就需要更改一下了

由于會被頻繁調用,所以我們的進度條在這里,每一次調用都代表那一瞬間的狀態

所以我們在進度條那里的循環可以只是循環添加 =

接著,我們的進度這次就是按照百分比來算的了

所以進度條需要一個總的文件大小,以及現在文件加載到哪里了,這樣我們將兩個文件除出來之后再乘100,就是當前文件加載的百分比進度:

double rate = current*100.0/total;

接下來的都是小小修改一下而已,代碼如下:

#define LENGTH 101
#define STYLE '='
const char* label = "|/-\\";void ProcessBar(double total, double current)
{char bar[LENGTH];memset(bar, '\0', sizeof bar);int len = strlen(label);double rate = current*100.0/total;int loop_count = (int)rate;int cnt = 0;while(cnt <= loop_count){bar[cnt++] = STYLE;}printf("[%-100s][%.1lf%%][%c]\r", bar, rate, label[cnt % len]);fflush(stdout);
}

最后,我們還可以再來一個小優化

試想一下,我們以后如果有了圖形化界面,或者就是單純更好的進度條,對于這個下載任務而言,如果我們只是用一個函數指針的話,到時候我們只需要修改指針即可,這樣的話,修改起來就很方便,當我們有了更好的進度條的時候

如下,我們可以先在 .h 文件里面定義一個函數指針:

typedef void (*pb)(double, double);

接著,我們的下載任務里面,就可以直接加上這個參數了:

#define bandwidth 1024*1024*1.0;void download(double file_size, pb procbar)
{double current = 0.0;while(current <= file_size){procbar(file_size, current);current += bandwidth;usleep(20000);}printf("\n");
}int main()
{download(100.0*1024*1024, ProcessBar);return 0;
}

結語

這篇文章到這里就結束啦!!~( ̄▽ ̄)~*

如果覺得對你有幫助的,可以多多關注一下喔

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/907361.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/907361.shtml
英文地址,請注明出處:http://en.pswp.cn/news/907361.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

從零實現wss通信示例(WebSocket SSL)

客戶端和服務端代碼框架跟上一篇一致,僅增加了ssl的證書部分用于加密通信,明文通信(ws協議)見上一篇【https://blog.csdn.net/suoxd123/article/details/148093934】 1. 證書創建 1. 安裝openssl 【官網地址】:https://slproweb.com/products/Win32OpenSSL.html 1.2 …

mysql 索引失效有哪些

InnoDB存儲引擎根據索引類型不同&#xff0c;分為聚簇索引和二級索引 聚簇索引&#xff1a;葉子節點存放的是實際數據 二級索引&#xff1a;存放的是主鍵值&#xff0c;不是實際數據 1.對索引使用左或者左右模糊匹配 select * from t_user where name like %林‘&#xff1b…

LabVIEW通用測控平臺設計

基于 LabVIEW 圖形化編程環境&#xff0c;設計了一套適用于工業自動化、科研測試領域的通用測控平臺。通過整合研華、NI等品牌硬件&#xff0c;實現多類型數據采集、實時控制及可視化管理。平臺采用模塊化架構&#xff0c;支持硬件靈活擴展&#xff0c;解決了傳統測控系統開發周…

華為OD機試真題——智能駕駛(2025A卷:200分)Java/python/JavaScript/C/C++/GO最佳實現

2025 A卷 200分 題型 本專欄內全部題目均提供Java、python、JavaScript、C、C++、GO六種語言的最佳實現方式; 并且每種語言均涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、3個測試用例以及綜合分析; 本文收錄于專欄:《2025華為OD真題目錄+全流程解析+備考攻略+經驗分…

速賣通,國際站測評補單,如何平衡效率和安全

測評能夠幫助賣家讓平臺更喜歡自己的產品&#xff0c;給予更好排名的同時也讓后續進入店鋪的買家更容易認可自己的產品。這是進行真實交易后形成的評價&#xff0c;而不是通過機器軟件生成&#xff0c;形成虛擬數據后&#xff0c;那種刷評形式產生的評論。它符合任何電商平臺的…

學習路之PHP--easyswoole3.3入門及文件熱加載

學習路之PHP--easyswoole入門 一、框架說明二、常用命令三、文件熱加載 一、框架說明 目錄結構 目錄結構 project 項目部署目錄 ├─App 應用目錄(可以有多個) │ ├─HttpController 控制器目錄 │ │ └─Index.php …

設計模式26——解釋器模式

寫文章的初心主要是用來幫助自己快速的回憶這個模式該怎么用&#xff0c;主要是下面的UML圖可以起到大作用&#xff0c;在你學習過一遍以后可能會遺忘&#xff0c;忘記了不要緊&#xff0c;只要看一眼UML圖就能想起來了。同時也請大家多多指教。 解釋器模式&#xff08;Interp…

第三屆寧波技能大賽網絡安全賽項樣題

2025 第三屆寧波技能大賽網絡安全賽項樣題 模塊A: 網絡安全事件響應、數字取證調查和應用安全任務一:應急響應任務二:操作系統取證任務三:網絡數據包分析任務四:代碼審計 模塊B:CTF 奪旗-攻擊模塊C:CTF 奪旗-防御需要環境培訓可以私信博主&#xff01;&#xff01;&#xff01;…

GO語言進階:掌握進程OS操作與高效編碼數據轉換

&#x1f49d;&#x1f49d;&#x1f49d;歡迎蒞臨我的博客&#xff0c;很高興能夠在這里和您見面&#xff01;希望您在這里可以感受到一份輕松愉快的氛圍&#xff0c;不僅可以獲得有趣的內容和知識&#xff0c;也可以暢所欲言、分享您的想法和見解。 推薦&#xff1a;「storms…

IO進程(進程 Process)

什么是進程&#xff1f; 1.概念 程序&#xff1a;編譯好的可執行文件&#xff0c;存放在磁盤上的指令和數據的有序集合。 由此可見程序是靜態的&#xff0c;沒有執行的概念。 進程&#xff1a;是程序的一次執行的過程&#xff0c;是一個可調度的任務&#xff0c;也是執行一…

CSS傳統布局與定位詳解與TDK三大標簽SEO優化

一、傳統布局基礎 1. 文檔流布局 瀏覽器默認的文檔流布局方式遵循以下規則&#xff1a; 塊級元素&#xff08;如<div>、<p>、<h1>&#xff09;&#xff1a; 獨占一行寬度默認100%可以設置寬高、內外邊距 div {width: 500px;height: 200px;margin: 10px …

【GraphQL】深入解析 Apollo Client:從架構到實踐的一站式 GraphQL 解決方案

深入解析 Apollo Client&#xff1a;從架構到實踐的一站式 GraphQL 解決方案 1. 引言 GraphQL 作為現代 API 開發的核心技術&#xff0c;其靈活性和高效性正在重塑數據交互模式。Apollo Client 作為 GraphQL 生態中最受歡迎的客戶端庫&#xff0c;憑借強大的緩存機制、框架集…

docker學習基本使用教程

docker是一款用于開發部署和運行容器化平臺&#xff0c;能將應用及其依賴打包成輕量級、可移植的容器&#xff0c;實現一次構建&#xff0c;隨處運行。docker是cs架構程序&#xff08;客戶端和服務端&#xff09;&#xff0c;docker客戶端向docker守護進程發送請求&#xff0c;…

萬字詳解RTR RTSP SDP RTCP

目錄 1 RTSP1.1 RTSP基本簡介1.2 RSTP架構1.3 重點內容分析 2 RTR2.1 RTR簡介2.2 RTP 封裝 H.2642.3 RTP 解封裝 H.2642.4 RTP封裝 AAC2.5 RTP解封裝AAC 3 SDP3.1 基礎概念3.2 SDP協議示例解析3.3 重點知識 4 RTCP4.1 RTCP基礎概念4.2 重點 5 總結 1 RTSP 1.1 RTSP基本簡介 一…

唯一原生適配鴻蒙電腦的遠程控制應用,向日葵正式上線

近日&#xff0c;華為正式發布鴻蒙電腦新品&#xff0c;標志著HarmonyOS在PC端生態的進一步拓展。作為遠程控制領域的先行者&#xff0c;貝銳科技旗下的向日葵遠程控制軟件也在第一時間完成了對鴻蒙電腦系統的原生適配&#xff0c;并已正式上線華為鴻蒙電腦應用市場&#xff0c…

vue2中,codemirror編輯器的使用

交互說明 在編輯器中輸入{時&#xff0c;會自動彈出選項彈窗&#xff0c;然后可以選值插入。 代碼 父組件 <variable-editorv-model"content":variables"variables"placeholder"請輸入模板內容..."blur"handleBlur" />data…

Kafka自定義分區策略實戰避坑指南

文章目錄 概要代碼示例小結 概要 kafka生產者發送消息默認根據總分區數和設置的key計算哈希取余數&#xff0c;key不變就默認存放在一個分區&#xff0c;沒有key則隨機數分區&#xff0c;明顯默認的是最不好用的&#xff0c;那kafka也提供了一個輪詢分區策略&#xff0c;我自己…

WPF 全屏顯示實現(無標題欄按鈕 + 自定義退出按鈕)

WPF 全屏顯示實現&#xff08;無標題欄按鈕 自定義退出按鈕&#xff09; 完整實現代碼 MainWindow.xaml <Window x:Class"FullScreenApp.MainWindow"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"http://schemas…

sqli_labs第二十九/三十/三十一關——hpp注入

一&#xff1a;HTTP參數污染&#xff1a; hpp&#xff08;http parameter pollution)注入中&#xff0c;可以通過在hppt的請求中注入多個同名參數來繞過安全過濾 原理&#xff1a;php默認只取最后一個同名參數 比如在這一關里&#xff0c;可能對第一個id參數進行消毒處理&a…

【STM32】按鍵控制LED 光敏傳感器控制蜂鳴器

&#x1f50e;【博主簡介】&#x1f50e; &#x1f3c5;CSDN博客專家 &#x1f3c5;2021年博客之星物聯網與嵌入式開發TOP5 &#x1f3c5;2022年博客之星物聯網與嵌入式開發TOP4 &#x1f3c5;2021年2022年C站百大博主 &#x1f3c5;華為云開發…