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

【Linux系统】Linux入门系统程序−进度条

文章目录

  • 一、铺垫知识
    • 1.回车符 和 换行符的区别
    • 2.用户缓冲区问题
  • 二、进度条程序初版(含视频演示效果)
  • 三、进度条程序(加入使用场景)


一、铺垫知识

1.回车符 和 换行符的区别

回车符’\r’ 的效果(让光标回到当前行开头) 和 换行符’\n’ 理论上的效果(把光标移动到下一行同一位置):
在这里插入图片描述
但实际上单纯的换行作用意义不大,所以在语言层面上,当你单独使用 ‘\n’ 时,它会同时执行回车 + 换行的效果。结论,在语言层面上,使用 ‘\n’ 或 "\r\n"的效果一模一样。
在这里插入图片描述

2.用户缓冲区问题

  1. 执行以下代码观察现象:
#include <stdio.h>
#include <unistd.h>int main()
{printf("hello world");sleep(2);return 0; 
}

现象:大约2s后,“hello world” 才被打印到屏幕上。
为什么会出现这种奇怪的现象,代码不是按顺序执行的吗?不应该是先执行printf函数打印,再执行sleep函数休眠吗?

分析:代码肯定是按顺序执行的,出现这种现象实际与用户缓冲区有关。在打印函数与显示器文件之间有一个缓冲区,叫用户缓冲区,printf函数实际上也并不什么打印函数,更确切的说它应该是一种拷贝函数,它会把字符串内容拷贝到用户缓冲区,而当用户缓冲区刷新的时候,用户缓冲区中的内容才会被拷贝到显示器文件(内容被拷贝到显示器文件,用户就能看到内容被打印到显示器的效果)。

用户缓冲区的刷新策略(一般来说是按照行刷新):
(1)遇到 ‘\n’,就会把 ‘\n’ 前的所以内容刷新到显示器文件
(2) 程序结束时,会把用户缓冲区的所有内容刷新到显示器文件

现象解释:printf函数把 “hello world” 拷贝到用户缓冲区中,接着执行sleep函数休眠2s后程序结束,程序结束时用户缓冲区中的所有内容会被刷新到显示器文件。

补充:
sleep函数:让程序休眠指定秒数再向后执行

在这里插入图片描述

  1. 验证第一种用户缓冲区刷新策略:
#include <stdio.h>
#include <unistd.h>int main()
{printf("hello world\n"); // 在结尾加上'\n'换行符sleep(2);return 0; 
}

现象:“hello world\n” 瞬间被打印到屏幕上,大约等待2s后程序结束。

结论:字符串结尾加上’\n’之后,字符串内容瞬间就刷新到显示器文件,而不是等待2s程序结束时才刷新,这证明了第一种刷新策略是正确有效的。

  1. 实际上除了前面两种用户缓冲区的刷新策略之外,系统还为用户提供了一种强制刷新缓冲区的函数:
    在这里插入图片描述

fflush函数可以强制将用户缓冲区中的内容刷新到显示器文件,
使用方法:fflush(stdout)

C程序在启动的时候,默认打开了3个流:
• stdin - 标准输入流,指键盘文件
• stdout - 标准输出流,指显示器文件
• stderr - 标准错误流

代码验证:

#include <stdio.h>
#include <unistd.h>int main()
{printf("hello world"); // 字符串结尾没加 '\n'fflush(stdout);sleep(2);return 0; 
}

现象:“hello world\n” 瞬间被打印到屏幕上,大约等待2s后程序结束。

结论:字符串结尾没加’\n’,字符串内容还是能瞬间就刷新到显示器文件,这证明fflush函数可以强制将用户缓冲区中的内容刷新到显示器文件。

二、进度条程序初版(含视频演示效果)

main.c:

#include "progress.h"int main()
{progress();return 0;
}

progress.h:

#pragma once
#include <stdio.h>
#include <unistd.h>void progress();

progress.c(进度条函数实现):

#include "progress.h"void progress()
{char bar[101] = {'\0'};const char* cnt = "|/-\\"; // '\\'是一个转义字符,⽤于表示⼀个反斜杠,防止它被解释为⼀个转义序列符int count = 0;while(count<=100){printf("[%-100s][%-3d%%][%c]\r",bar,count,cnt[count%4]);fflush(stdout);usleep(50000);bar[count] = '#';count++;}printf("\n");
}

视频演示进度条程序初版代码运行效果(链接: 进度条初版)

补充:
usleep函数:让程序休眠指定微秒数再向后执行
这里是引用

三、进度条程序(加入使用场景)

main.c(模拟下载软件的使用场景:下载函数):

#include "progress.h"void download(double total,double speed) // total:软件总大小;speed:下载速度
{double current_total = 0.0;while(current_total<=total){progress(current_total,total);usleep(10000); // 每隔10000微秒进行一次下载current_total += speed; // 每次下载,进度增加一个下载速度}printf("\n");
}int main()
{printf("程序下载中:\n");download(1024.0,2.0);return 0;
}

progress.h:

#pragma once
#include <stdio.h>
#include <unistd.h>void progress(double,double);

progress.c(进度条函数:进度条不会一次性走完,每次调用进度条函数会打印出当前下载进度):

#include "progress.h"void progress(double current,double total) 
{double cur_progress = current/total*100; // 计算出当前进度char bar[101] = {'\0'};int bar_count = (int)cur_progress;for(int i = 0;i < bar_count;i++)bar[i] = '#';const char* cnt = "|/-\\";static int count = 0;printf("[%-100s][%.1lf%%][%c]\r",bar,cur_progress,cnt[count%4]);fflush(stdout);count++;
}

http://www.xdnf.cn/news/7383.html

相关文章:

  • 【esp32 控制台】-命令
  • 抽奖相关功能测试思路
  • Python学习之Flask框架(二)
  • 【达梦数据库】过程、函数、包头和包体详解零基础
  • Linux串口绑定
  • 佰力博与您探讨绝缘材料介电性能测试的方法。
  • Linux权限练习题
  • C++:因子问题
  • 基于SpringBoot的小型民营加油站管理系统
  • 【JAVA】使用javax.mail发送qq邮件
  • Notepad++ 学习(三)使用python插件编写脚本:实现跳转指定标签页(自主研发)
  • [Linux排查] “Permission Denied“?一文解决Linux文件/目录权限不足问题
  • 头歌之软件工程-用例设计
  • 《中国智算中心市场发展研究报告》:算力政策与AI技术双重驱动下的供需两旺
  • 2025年即时通讯APP如何抵御DDoS攻击?全链路防御方案与实战解析
  • 10、底层注解-@Conditional条件装配
  • 绿幕抠图与虚拟背景:直播美颜SDK开发前沿技术探索
  • Keil 调试模式下拷贝Flash,RAM中的数据
  • 双周报Vol.72:字段级文档注释支持、视图类型现为值类型,减少内存分配
  • 实战手册--如何针对衡石分析平台的数据集成详解
  • 配电房值守难题终结者:EdgeView智能监控的7×24小时守护
  • ICU库交叉编译
  • 软件设计师关系代数和元组演算(关联、笛卡尔积、除、映射、分段等问题)考点分析——求三连
  • MCP与通讯模式:理论篇
  • 云服务器开发软件操作步骤
  • 微机系统第二章-题目整理
  • 数据治理进阶:精读45页深入浅出数据治理培训教材【附全文阅读】
  • Nginx基础知识
  • 学习BI---QuickBI介绍
  • 【find / -name “xxx“】为什么有时候搜索范围扩大之后,就无法找到