【Linux系統編程】進度條的編寫

目錄

一,進度條的必備知識

1,緩沖區的粗略介紹

2,回車與換行

二,進度條的初步制作

1,進度條的初步礦建

2,進度條的版本一

3,進度條的版本二


一,進度條的必備知識

1,緩沖區的粗略介紹

? ? ? ??緩沖區是內存的一部分空間,用于臨時存儲輸入和輸出的數據。它可分為輸入緩沖區和輸出緩沖區。每當我們輸入數據時都是往輸入緩沖區中存放數據,當刷新緩沖區時,數據將會從緩沖區中拿出輸入到某個變量中。每當我們輸出數據時,系統將會把數據輸出到輸出緩沖區中,當刷新輸出緩沖區時,數據將會從輸出緩沖區輸出到指定地方。

? ? ? ? 其中,緩沖區的刷新時機是不同的。行緩沖會在遇到換行符時刷新,全緩沖會在緩沖區寫滿時刷新,而無緩沖則沒有緩沖區,代表是系統調用。在C/C++中,通常用 fflush(FILE* stream) 來強制刷新指定流的緩沖區。

? ? ? ? C/C++中類似于sleep函數功能控制的就是緩沖區,當系統調用到sleep是,將會被緩沖區暫時保存起來,一旦sleep運行完畢之后緩沖區才刷新。進度條有時控制的就是緩沖區的刷新時間。

2,回車與換行

? ? ? ? “ 回車 ” 是把光標從當前位置直接指向最開頭位置。“ 換行?” 是把光標從當前位置直接指向下一行同一列的位置。我們在C語言階段常用的 “ \n?” 指的是?換行?+ 回車。而 “ \r ” 只表示回車。


二,進度條的初步制作

1,進度條的初步礦建

? ? ? ? 首先,我們先來編寫進度條的簡單倒計時程序,這就需要運用回車和sleep來控制程序的運行。

#include <iostream>
#include <iomanip> //setw的頭文件
#include <unistd.h> //usleep()的頭文件,對應參數單位為微秒? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
#include <cstdio>
using namespace std;
int main()
{
? ? int n = 10;
? ? while (n >= 0) {
?? ??? ?cout << left << setw(2) << n << '\r'; //跟C語言中printf("%-2d\r", n)效果一樣
? ? ? ? fflush(stdout); ? //強制刷新輸出緩沖區
? ? ? ? n--;
? ? ? ? usleep(500000); ? ?//這里我們控制緩沖時間為0.5秒
?? ?}
? ? cout << endl;
? ? return 0;
}

? ? ? ? 下一步,要思考進度條的框架設計。這里的進度條將外圍用 " = " 表示進度的加載,外圍設置了百分比顯示加載數據。用 "|/-\" 來表示其中的加載,即順時針旋轉。

2,進度條的版本一

? ? ? ? 首先,外面設置一個頭文件 "process.h" 進行必要的設置

#include <iostream>
#include <string>
#include <unistd.h>
#include <iomanip>
#include <cstdio>
using namespace std;

#define Body '='? ?//使用body來表示進度
#define Head '>'? ?//Head表示目前加載的終點,這里用 ' > ' 表示

void process1();? //進度條函數

? ? ? ? 下面,進行進度功能的編寫。這里使用 usleep 功能來控制進度的的運行,這里需注意的是輸出緩沖區的刷新。

void process1()
{

? ? //用lable表示進度條的加載
? ? string lable("|/-\\");??
? ? string nums;
? ? int count = 0;
? ? int lablesize = lable.size();
? ? nums.push_back(Head);
? ? while (count <= 100)
? ? {
? ? ? ? cout << "[" << left << setw(100) << nums << "]";
? ? ? ? cout << "[" << "%" << count << "]";
? ? ? ? cout << "[" << lable[count % lablesize] << "]" << '\r';
? ? ? ? fflush(stdout);
? ? ? ? nums.clear();
? ? ? ? count++;
? ? ? ? nums.append(count, Body);
? ? ? ? if (count < 100)
? ? ? ? {
? ? ? ? ? ? nums.push_back(Head);
? ? ? ? }

????????//這里我們設置每0.6秒加載一次
? ? ? ? usleep(60000);?
? ? }
? ? cout << endl;
}

運行最終結果:

[====================================================================================================][%100][|]

3,進度條的版本二

? ? ? ? 進度條一般都是運用在一種應用上,表示應用的加載過程。很顯然,版本一的進度條只是無腦運行,不知道程序進度是多少,即沒有依附應用進度,比如下載程序,這時的進度條需依附于下載進度來跟進。

? ? ? ? 頭文件 "process.h" 添加如下:

#include <iostream>
#include <string>
#include <unistd.h>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
using namespace std;

#define Body '='
#define Head '>'
#define Max 103
#define FileSize 1024*1024*1024? //設置FileSize文件內存為1G,表示下載程序的總大小

typedef void (*callback_t)(double);? //利用函數指針來進行封裝進度運用


void download(callback_t);? //模擬一種下載進度
void process2(double rate); //進度條跟進程序

? ? ? ? 這里,在設置download下載時要將每一次的下載進度傳遞給進度條讓其顯示百分比。

void download(callback_t cb)? ?//利用回調函數的形式設置進度
{
? ? srand(time(0)*1024);
? ? int total = FileSize;
? ? while (total)
? ? {
? ? ? ? //下面表示一次下載動作
? ? ? ? usleep(10000);
? ? ? ? int one = rand() % (1024 * 1024 * 5);
? ? ? ? total -= one;
? ? ? ? if (total < 0)?
? ? ? ? {
? ? ? ? ? ? total = 0;
? ? ? ? }
? ? ? ? //表示當前的進度
? ? ? ? int download = FileSize - total;
? ? ? ? double rate = (download * 1.0 / (FileSize)) * 100.0;
? ? ? ? cb(rate); //每一次進度條的傳遞
? ? }
}

進度條設置時要說明以下幾點:

????????1,我們使用?"|/-\\" 表示進度跟進時是根據下載進度進行的,與當前的進度無關。

????????2,進度條的總設置需與下載程序緊緊聯系。比如當程序加載完時,“ > ” 進度條中表示進? ? ? ? ? 度運行的就要停止,即刪除。

????????3,在輸出進度運行過程,我們可添加其色彩表示美觀,鏈接:色彩文本的增添

void process2(double rate)
{

? ??//用lable表示下載任務一直在跟進
? ? string lable("|/-\\");?

? ??//注意,這里要保留之前的進度,需設置靜態
? ? static char buffer[Max] = { 0 };
? ? static int cnt = 0;
? ? if (rate <= 1.0)
? ? {
? ? ? ? buffer[0] = Head;
? ? }
? ? printf("\033[1;31;46m[%-100s]\033[0m[%.1lf%%][%c]\r", buffer, rate, lable[cnt % lable.size()]);? //設置色彩,這里我們設置高亮/加粗,青色背景,紅色字體的色彩

? ? fflush(stdout);

? ? //下面控制進度的跟進
? ? buffer[(int)rate] = Body;
? ? if ((int)rate + 1 < 100)
? ? {
? ? ? ? buffer[(int)(rate + 1)] = Head;
? ? }
? ? if (rate >= 100.0)
? ? {
? ? ? ? cout << endl;
? ? }
? ? cnt++;
? ? cnt %= lable.size();
}

總代碼如下:

#include "process.h"
//版本一
void process1()
{string lable("|/-\\");string nums;int count = 0;int lablesize = lable.size();nums.push_back(Head);while (count <= 100){cout << "[" << left << setw(100) << nums << "]";cout << "[" << "%" << count << "]";cout << "[" << lable[count % lablesize] << "]" << '\r';fflush(stdout);nums.clear();count++;nums.append(count, Body);if (count < 100){nums.push_back(Head);}usleep(60000);}cout << endl;
}
//版本二
void download(callback_t cb)
{srand(time(0) * 1024);int total = FileSize;while (total){usleep(10000);int one = rand() % (1024 * 1024 * 5);total -= one;if (total < 0){total = 0;}int download = FileSize - total;double rate = (download * 1.0 / (FileSize)) * 100.0;cb(rate);}
}
void process2(double rate)
{static string lable("|/-\\");static char buffer[Max] = { 0 };static int cnt = 0;if (rate <= 1.0){buffer[0] = Head;}printf("\033[1;31;46m[%-100s]\033[0m[%.1lf%%][%c]\r", buffer, rate, lable[cnt % lable.size()]);fflush(stdout);buffer[(int)rate] = Body;if ((int)rate + 1 < 100){buffer[(int)(rate + 1)] = Head;}if (rate >= 100.0){cout << endl;}cnt++;cnt %= lable.size();
}
int main()
{//process1(); //使用進度條粗略版本一download(process2); //使用進度條進化版本二return 0;
}

????????最后,要說明的是,以上程序都是在Linux系統下運行進行的,在VS或其它編譯器下可能會出現錯誤消息,這時因為不同平臺支持的C標準或系統設置不同而造成的差異。

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

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

相關文章

詳細了解STM32----GPIO

提示&#xff1a;永遠支持免費開源知識文檔&#xff0c;喜歡的點個關注吧&#xff01;謝謝&#xff01; 文章目錄 一、什么是GPIO&#xff1f;二、GPIO基本結構三、GPIO的輸入輸出模式1、推挽輸出2、開漏輸出3、復用推挽4、復用開漏1、浮空輸入2、上拉輸入&#xff13;、下拉輸…

FastAPI之嵌套模型

請求體 - 嵌套模型 使用 FastAPI&#xff0c;你可以很隨意的實現模型的嵌套、定義、校驗、記錄文檔&#xff0c;并使用任意深度嵌套的模型&#xff0c;這其實都是FastAPI的核心模塊P一單提成進行做的。。 List 字段 from fastapi import FastAPI from pydantic import BaseM…

基于JavaWeb+SSM+Vue童裝商城小程序系統的設計和實現

基于JavaWebSSMVue童裝商城小程序系統的設計和實現 源碼獲取入口Lun文目錄前言主要技術系統設計功能截圖訂閱經典源碼專欄Java項目精品實戰案例《500套》 源碼獲取 源碼獲取入口 Lun文目錄 目 錄 摘 要 III Abstract 1 1 系統概述 2 1.1 概述 3 1.2課題意義 4 1.3 主要內容 5…

BearPi Std 板從入門到放棄 - 先天篇(1)(階段 : 智慧城市 - 智慧路燈)

簡介 對前面幾篇整合, 做個小小匯總試驗, 使用BearPi E53_SC1擴展板主芯片: STM32L431RCT6串口: Usart1擴展板與主板連接: I2C : I2C1 (光照強度傳感器&#xff1a;BH1750)LED: PB9步驟 創建項目 參考 BearPi Std 板從入門到放棄 - 引氣入體篇&#xff08;1&#xff09;(由零創…

【測試人生】數據同步和遷移的變更注意事項

數據同步或者遷移操作也算是線上數據變更的一種類型。由于涉及的數據量非常大&#xff0c;一旦發生故障&#xff0c;會直接影響線上業務&#xff0c;并且較難止損。從變更風險管控的角度考慮&#xff0c;數據同步或遷移操作也需要走合理的發布窗口&#xff0c;并且在操作前也需…

淺談Google Play ASO 優化

什么是ASO ASO即APP Store Optimization&#xff0c;是用于提高APP在應用市場排名的工具&#xff0c;其實也就是移動產品的SEO工作。 ASO是為了提高該產品的搜索結果成績&#xff0c;提升APP的下載量&#xff0c;針對Google Play來說&#xff0c;ASO就是優化APP頁面。 為什么…

Linux升級nginx版本

處于漏洞修復目的服務器所用nginx是1.16.0版本掃出來存在安全隱患&#xff0c;需要我們升級到1.17.7以上。 一般nginx默認在 /usr/local/ 目錄&#xff0c;這里我的nginx是自定義的路徑安裝在 /app/weblogic/nginx 。 1.查看生產環境nginx版本 cd /app/weblogic/nginx/sbin/…

Redis基礎入門

第1章&#xff1a;引言 大家好&#xff01;我是小黑&#xff0c;今天咱們來聊聊Redis。Redis&#xff0c;這個名字你可能在不少地方聽過&#xff0c;尤其是在后端開發領域&#xff0c;它可是個大名鼎鼎的角色。&#xff0c;Redis是一個開源的內存中數據結構存儲系統&#xff0…

放棄原生SQL:Python中更優雅的數據庫操作

概要 在Python中&#xff0c;通過原生SQL語句進行數據庫操作是一種傳統的方式&#xff0c;但現代的Python開發中&#xff0c;使用ORM&#xff08;Object-Relational Mapping&#xff09;工具和數據庫連接庫可以更加高效和優雅地進行增刪改查操作。本文將詳細介紹Python中放棄原…

解決IDEA中多個項目不在同一窗口下顯示的問題和添加新的git的URL

以上是添加顯示多個項目 以下是給新添加的項目添加git

LeetCode算法題解(單調棧)|LeetCode84. 柱狀圖中最大的矩形

一、LeetCode84. 柱狀圖中最大的矩形 題目鏈接&#xff1a;84. 柱狀圖中最大的矩形 題目描述&#xff1a; 給定 n 個非負整數&#xff0c;用來表示柱狀圖中各個柱子的高度。每個柱子彼此相鄰&#xff0c;且寬度為 1 。 求在該柱狀圖中&#xff0c;能夠勾勒出來的矩形的最大…

做外貿很多時候還是要學會隨機應變

馬上又要到年底了&#xff0c;相信已經有一部分小伙伴開啟了催單模式&#xff0c;希望客戶盡量在春節前將訂單落實下來&#xff0c;自然也有很多客戶會在春節前的這一段時間開始陸續拜訪自己觀望了很久的工廠。 其實對于貿易公司來說&#xff0c;對于來看工廠的客戶&#xff0…

ChatGPT,作為一種強大的自然語言處理模型,具備顯著優勢,能夠幫助您在各個領域取得突破

2023年隨著OpenAI開發者大會的召開&#xff0c;最重磅更新當屬GPTs&#xff0c;多模態API&#xff0c;未來自定義專屬的GPT。微軟創始人比爾蓋茨稱ChatGPT的出現有著重大歷史意義&#xff0c;不亞于互聯網和個人電腦的問世。360創始人周鴻祎認為未來各行各業如果不能搭上這班車…

Kotlin 作用域函數:理解 apply, let, 和 with

Kotlin提供了幾個作用域函數來優化和簡化代碼的結構。 本文將對比分析 apply, let, 和 with 三個函數。 一、對比分析&#xff1a; apply&#xff1a;在其接收者的上下文中執行代碼塊&#xff0c;并返回接收者對象。let&#xff1a;在其接收者的上下文中執行代碼塊&#xff…

Kotlin:內置函數let、also、with、run、apply

前言 在Kotlin中&#xff0c;有一些用于擴展 & 方便開發者編碼的內置函數&#xff0c;能大大提高開發者的開發效率。今天&#xff0c;我將主要講解的是&#xff1a; let函數also函數with函數run函數apply函數 基礎知識&#xff1a;接口回調中Lambda使用 在Kotlin中可使用…

棧和隊列的互相實現

用隊列實現棧 OJ鏈接 請你僅使用兩個隊列實現一個后入先出&#xff08;LIFO&#xff09;的棧&#xff0c;并支持普通棧的全部四種操作&#xff08;push、top、pop 和 empty&#xff09;。 實現 MyStack 類&#xff1a; void push(int x) 將元素 x 壓入棧頂。int pop() 移除并返…

Mybatis XML增刪操作(結合上文)

先來"增"操作 在UserInfoXMLMapper.xml里面寫 <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <…

nginx多端口部署

1.配置nginx.conf文件 有幾個端口需要部署就寫幾個server&#xff0c;我這里只部署了兩個端口分別為80和81端口&#xff0c;所以有兩個server文件。80端口項目入口在根目錄的test文件中&#xff0c;81端口項目入口在根目錄的test1文件夾中。 2.準備項目文件html文件 在/test1…

Dockerfile部署Java項目掛載使用外部配置文件

Dockerfile部署Java項目掛載使用外部配置文件 技術博客 http://idea.coderyj.com/ 需求是由于java項目使用的是nacos 而且每次部署nacos服務器ip不一樣導致要重新打包,想引入外部配置文件進行打包 1.需求是由于java項目使用的是nacos 而且每次部署nacos服務器ip不一樣導致要重新…

數據結構和算法專題---5、調度算法與應用

本章我們會對調度算法做個簡單介紹&#xff0c;包括常用的調度算法&#xff08;FCFS、SJF、RR、HPF&#xff09;的概述、實現方式、典型場景做個說明。 什么是調度算法 調度算法常見于操作系統中&#xff0c;因為系統資源有限&#xff0c;當有多個進程&#xff08;或多個進程…