当前位置: 首页 > news >正文

Linux基础开发工具(编写一个简易进度条)

目录

1.回车换行

2.缓冲区问题

那么在我们休眠3秒期间hello world!在哪里?

程序会默认打开三个输入输出流 FILE*类型

3.倒计时程序

1.初版 2.第二版 3.终版

理解显示

4.进度条

想实现的进度条

1.第一版

1.初步 2.process.c

2.第二版


继上节的make/Makefile篇,我们这节来完成一个命令行版的简易的进度条

1.回车换行

回车 \r 换行 \n

回车换行 \r\n

一般\n被自动解析成\r\n

  • 回车\r:将光标移动到当前行的开头(水平移动)。

  • 换行\n:将光标移动到下一行的同一列(垂直移动)。

2.缓冲区问题

今天先简单讲一下缓冲区,先理解为一段内存块

myproc.c

1 #include<stdio.h> 2 #include<unistd.h> 3 4 int main() 5 { 6 printf("hello world!\n"); 7 sleep(3); 8 return 0; 9 }

sleep

先等3秒之后退出。

然后把myproc.c的\n去掉

1 #include<stdio.h> 2 #include<unistd.h> 3 4 int main() 5 { 6 //printf("hello world!\n"); 7 printf("hello world!"); 8 sleep(3); 9 return 0; 10 }

发现是先休眠3秒在打印hello world!

不要以为第二个是先执行sleep再printf。

程序执行永远是从前往后执行的,先执行printf再执行printf

一定把printf执行完了!但是显示器上没有显示,

那么在我们休眠3秒期间hello world!在哪里?

在缓冲区里面

我们往显示器上打印称为行刷新

如果没有\n就不会刷新,那么为什么最终还是有打印出来呢?

是因为程序退出,会自动刷新缓冲区!

小知识点

fprintf

1 #include<stdio.h> 2 #include<unistd.h> 3 4 int main() 5 { 6 //printf("hello world!\n"); 7 fprintf(stdout,"hello world!\n"); 8 sleep(3); 9 return 0; 10 }

这里两个一样

如果想让它立马刷新呢?

可以使用fflush

1 #include<stdio.h> 2 #include<unistd.h> 3 4 int main() 5 { 6 printf("hello world!"); 7 fflush(stdout); 8 //printf("hello world!\n"); 9 //fprintf(stdout,"hello world!\n"); 10 sleep(3); 11 return 0; 12 }

程序会默认打开三个输入输出流 FILE*类型

extern FILE *stdin; 键盘 extern FILE *stdout; 显示器 extern FILE *stderr; 显示器

printf实际上是往stdout上打

3.倒计时程序

1.初版

myproc.c

1 #include<stdio.h> 2 #include<unistd.h> 3 4 int main() 5 { 6 int i = 9; 7 while (i >= 0) 8 { 9 10 printf("%d\n", i); 11 i--; 12 } 13 return 0; 14 }

我们想要让9876543210在同一个位置打印

2.第二版

myproc.c

1 #include<stdio.h> 2 #include<unistd.h> 3 int main() 4 { 5 int i = 9; 6 while (i >= 0) 7 { 8 9 printf("%d\r", i); 10 i--; 11 sleep(1); 12 } 13 return 0; 14 }

\r是回车符(Carriage Return),其作用是将光标移动到当前行的开头,不换行

结果我们发现,因为没有\n没有刷新缓冲区。

所以对应的信息没有显示出来

3.终版

myproc.c

1 #include<stdio.h> 2 #include<unistd.h> 3 int main() 4 { 5 int i = 9; 6 while (i >= 0) 7 { 8 9 printf("%d\r", i); 10 fflush(stdout); 11 i--; 12 sleep(1); 13 } 14 printf("\n"); 15 return 0; 16 }

显示效果成功(因为是动态不好演示,可以自行尝试)

理解显示

但如果这里给10

1 #include<stdio.h> 2 #include<unistd.h> 3 4 int main() 5 { 6 int i = 10; 7 while (i >= 0) 8 { 9 10 printf("%d\r", i); 11 fflush(stdout); 12 i--; 13 sleep(1); 14 } 15 printf("\n"); 16 return 0; 17 }

会发现是两位,并不会从两位变成一位的

显示器只认字符!---字符设备

因此改成

myproc.c

1 #include<stdio.h> 2 #include<unistd.h> 3 4 int main() 5 { 6 int i = 10; 7 while (i >= 0) 8 { 9 10 printf("%-2d\r", i); 11 fflush(stdout); 12 i--; 13 sleep(1); 14 } 15 printf("\n"); 16 return 0; 17 }

第十行,改成 printf("%-2d\r", i);

2d两个字符,"-"向左对齐。

从而实现成功

4.进度条

接下来,我们就开始进度条的操作

想实现的进度条

[## ][53%][/]

每过一个百分点多一个#号,53%那个会动,/处会旋转。

ctrl+ww,可以使光标移动到另一端 切换

1.第一版

前置准备

[user1@iZ5waahoxw3q2bZ 26-4-15.2]$ mkdir processbar [user1@iZ5waahoxw3q2bZ 26-4-15.2]$ cd processbar [user1@iZ5waahoxw3q2bZ processbar]$ touch process.h [user1@iZ5waahoxw3q2bZ processbar]$ touch process.c [user1@iZ5waahoxw3q2bZ processbar]$ touch main.c [user1@iZ5waahoxw3q2bZ processbar]$ ll total 0 -rw-rw-r-- 1 user1 user1 0 Apr 15 22:16 main.c -rw-rw-r-- 1 user1 user1 0 Apr 15 22:16 process.c -rw-rw-r-- 1 user1 user1 0 Apr 15 22:16 process.h

Makefile

1 SRC=$(wildcard *.c) 2 OBJ=$(SRC:.c=.o) 3 BIN=processbar 4 5 $(BIN):$(OBJ) 6 gcc -o $@ $^ 7 %.o:%.c 8 gcc -c $< 9 10 .PHONY: 11 clean: 12 rm -f $(OBJ) $(BIN)

1.初步

process.h

1 #pragma once 2 3 #include<stdio.h> 4 5 void process_v1();

process.c

1 #include"process.h" 2 3 void process_v1() 4 { 5 printf("hello world!\n"); 6 }

main.c

1 #include"process.h" 2 3 int main() 4 { 5 process_v1(); 6 return 0; 7 }

make

[user1@iZ5waahoxw3q2bZ processbar]$ make gcc -c process.c gcc -o processbar main.o process.o [user1@iZ5waahoxw3q2bZ processbar]$ ll total 36 -rw-rw-r-- 1 user1 user1 68 Apr 15 22:33 main.c -rw-rw-r-- 1 user1 user1 1368 Apr 15 22:36 main.o -rw-rw-r-- 1 user1 user1 137 Apr 15 22:21 Makefile -rwxrwxr-x 1 user1 user1 8512 Apr 15 22:38 processbar -rw-rw-r-- 1 user1 user1 73 Apr 15 22:38 process.c -rw-rw-r-- 1 user1 user1 211 Apr 15 22:36 process.h -rw-rw-r-- 1 user1 user1 1504 Apr 15 22:38 process.o [user1@iZ5waahoxw3q2bZ processbar]$ ./processbar hello world!

2.process.c

#include "process.h" #include <stdio.h> #include <string.h> #include <unistd.h> #define NUM 101 #define STYLE '#' void process_v1() { char buffer[NUM]; memset(buffer, 0, sizeof(buffer)); const char* lable = "|/-\\"; int len = strlen(lable); int cnt = 0; while (cnt <= 100) { printf("[%-100s][%d%%][%c]\r", buffer, cnt, lable[cnt % len]); fflush(stdout); buffer[cnt] = STYLE; cnt++; usleep(50000); // 50ms } printf("\n"); }

2.第二版

process.c

#include "process.h" #include <stdio.h> #include <unistd.h> #define BAR_WIDTH 50 void FlushProcess(double total, double current) { double percent = (current / total) * 100; int bar_len = (int)((current / total) * BAR_WIDTH); // 保证不超出范围 if (bar_len > BAR_WIDTH) bar_len = BAR_WIDTH; printf("\r["); for (int i = 0; i < BAR_WIDTH; ++i) { if (i < bar_len) printf("#"); else printf(" "); } printf("] %.2lf%%", percent); fflush(stdout); } typedef void (*callback_t)(double total, double current); double total = 1024.0; double speed = 1.0; void DownLoad(callback_t cb) { double current = 0; while (current <= total) { cb(total, current); usleep(3000); // 模拟下载数据 current += speed; } printf("\ndownload %.2lfMB Done\n", current); } void UpLoad(callback_t cb) { double current = 0; while (current <= total) { cb(total, current); usleep(3000); // 模拟上传数据 current += speed; } printf("\nupload %.2lfMB Done\n", current); } int main() { DownLoad(FlushProcess); UpLoad(FlushProcess); return 0; }

今天我们的学习就到此结束,期待我们下次再见!!!

http://www.jsqmd.com/news/647621/

相关文章:

  • 哈佛教授获诺奖的研究:你看到的不是全部,用心看才是真的看
  • Redis怎样实现短链接映射_通过String类型存储Key-Value对
  • 2026年抗老面霜终极排雷榜:拆开配方表,谁在真抗老,谁在收智商税
  • 发布计划管理化技术版本规划与依赖管理
  • C语言条件编译精讲
  • AI大模型-6:MCP原理和开发
  • Web前端技术第四次作业:表单实验报告
  • CANopen | 网络管理NMT实战 - 从命令解析到自主状态控制
  • 突破传统化学研究的终极AI助手:深度解析ChemBERTa如何实现分子智能预测的革命
  • awk以及ansible
  • 多模态大模型云端协同部署的“隐性成本黑洞”:带宽错配、冷启动惩罚、跨AZ语义一致性丢失(独家压测报告)
  • Sunshine终极配置指南:如何搭建专业级游戏串流服务器
  • 前后端连通性测试以及前端页面总体设计
  • 第一阶段:Java入门基础
  • 模型并行不是万能药,但这次是:详解MoE+CLIP架构下跨模态梯度同步失效的5大陷阱及修复补丁
  • 慧视项目的图片上传与前后端联通实现
  • WindowResizer技术解密:打破Windows窗口限制的数字助手
  • 验收检测报告怎么写才靠谱
  • 爱依克KF-05C可视电子签名板重磅来袭
  • 【多模态大模型监控告警体系构建指南】:20年SRE专家亲授5大核心模块、7类典型失效场景与实时拦截SOP
  • 区块链隐私保护技术
  • 16.修正 LangGraph Agent 的路由层,让 Router 真正只负责选工具
  • 跨境电商商品采集skill来了,可部署openclaw,不用Python也能搞定爬虫
  • 为什么Redis的KEYS命令在生产环境是禁止使用的?
  • 运维工程师最后的护城河正在崩塌?:多模态大模型自动解析监控截图、语音工单、异常堆栈的3层可信推理机制
  • 网络运维Windows Server管理
  • 计算机毕业设计:Python全国降水数据采集与预警平台 Flask框架 数据分析 可视化 大数据 AI 大模型 爬虫 数据大屏(建议收藏)✅
  • 便携式综合气象观测仪
  • NLP学习笔记03:文本分类——从 TF-IDF 到 BERT
  • 嵌入式学习day3:数组与结构体