对缓冲区的初步认识——制作进度条小程序

对缓冲区的初步认识--进度条小程序

  • 前言
  • 预备知识
    • 回车和换行的区别
    • 输出缓冲区
      • /n 有清空输出缓冲区的作用
      • stdout是什么?
      • 验证一切皆文件
      • 为什么是\n行刷新?
    • 倒计时程序
      • 原理
    • 代码实现
    • 为什么这里要强制刷新?没有会怎样?
    • 为什么是输出的是格式是%2d?正常的行不行?
  • 进度条程序
    • 数组长度为什么是102
    • 为什么我们要初始化数组?
    • 旋转的指针怎么实现的?
    • vison1完整代码
    • vison2
      • 构造场景
    • 效果
    • 稍微改进一下download函数
  • 最终效果
  • 谢谢观看

前言

这个小程序最好还是在Linux环境下实验,更能体现缓冲区作用

预备知识

回车和换行的区别

我们经常把回车换行连起来说,但他们是一样的吗?
换行:只有竖直方向改变
在这里插入图片描述
回车:只有横轴方向改变
在这里插入图片描述
回车换行:从第一行的末尾到第二行的起始位置
在这里插入图片描述
老式键盘的回车键 就是这个横竖造型

在这里插入图片描述
在c语言中\r是回车 \n是回车换行

输出缓冲区

我们暂且把缓冲区只是认为是内存的一块空间
为什么要有缓冲区呢?如果没有缓冲区 cup要更多次访问硬件设备
举个例子就像是我们宿舍扔垃圾总是攒得有点多了才开始扔,而不是有一点就扔

/n 有清空输出缓冲区的作用

例子:

这里有两个小程序 唯一的区别就是 第5句是否加了\n

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

这两个程序执行的结果是 第二个程序直接打印了,第一个程序快结束时才打印 这是为什么呢?

QQ2024229-164212

是因为第一个程序的sleep先执行吗?不是的 没有多线程的情况都是从上到下执行的。答案是 \n是作为情况缓冲区的标志
没有\n的时候hello word还在缓冲区了 程序结束了才释放
怎么解决这个问题呢?
我们在后面加fflush(stdout)
有个问题这个参数好奇怪

stdout是什么?

在这里插入图片描述
是一种文件类型的变量用于控制显示器的 ,我们在c语言阶段也学过File的指针来操作文件的读写。为什么能把显示器也看成文件呢?因为在Linux下一切皆文件

验证一切皆文件

我们在/dev/pts/ 1 中写的文件 却在另一个终端显示了!
在这里插入图片描述

为什么是\n行刷新?

因为如果只追求效率 全部内容到缓冲区才刷新 这样会爆发式的内容增多,人来不及看。一行一行的刷新符合人的习惯。

倒计时程序

原理

我们写1的时候光标到下一个格子,然后又返回来写2把1覆盖,同一个位置不停的刷新
在这里插入图片描述

代码实现

#include <stdio.h>                                                                                 
#include<unistd.h> // linux环境 如果windos <windows.h>int main(){int cnt = 10;while(cnt >= 0){printf("%2d\r",cnt);// 如果不加2 长度不统一 覆盖不完全 fflush(stdout);sleep(1);cnt--;}printf("\n"); // 这里的作用是避免命令提示符覆盖return 0;}

为什么这里要强制刷新?没有会怎样?

我们先把fflush屏蔽了 看看会发生什么
在这里插入图片描述
在这里插入图片描述

只输出个0,为什么呢?
因为我们写一个字符串到缓冲区里,光标就回车了,然后再写就被覆盖了直到写到最后一个0没有东西能覆盖它了,于是就只把0从缓冲区输出到屏幕了。

为什么是输出的是格式是%2d?正常的行不行?

我们在屏幕上输出123是数字还是字符串呢?答案其实是字符串
如果我们就%d输出 看看会发什么
从10一下就到90了 这是因为 9只有一位 而10 有两位 只能覆盖一位所以显示就是90只把1覆盖了
在这里插入图片描述
在这里插入图片描述

我们已经了解了预备知识那么进入正题吧

进度条程序

我们要做的程序

QQ202431-214911

我们顶一个字符型数组bar长度为102用来存放进度#

数组长度为什么是102

因为我们用100个#来表示完全下载好 但是字符串结束的标准是’\0’所以我们至少要多用一个空间 但是为了保险再加一些也没关系

然后我们初始化数组

为什么我们要初始化数组?

因为数组不初始化放的都是随机值,我们等下按字符串输出时会出现乱码,最好以‘/0’初始化因为字符串输出遇到’/0‘结束!

 memset(bar, '\0', sizeof(bar)); 

之后我们在定义一个变量cnt表示进度到哪了?
每下载好一个bar[cnt] =‘#’ bar数组就存放一个字符 然后cnt++
直到 cnt <= 100

旋转的指针怎么实现的?

我们固定了输出的字符串长度为100在相当于长度为101的位置不停的写 |/-\ 覆盖着写形成了动画效果就像连环画一样
用一个字符数组储存|/-\ ,进度+1 就打印一个数组里面的内容 arr[p]
为了不越界 p 还要模4

vison1完整代码

但是这个版本就是空架子,没有和具体的场景联系起来

 void processbar(){char bar[length];int cnt = 0;memset(bar, '\0', sizeof(bar)); while (cnt < length) {printf("[%-100s] [%3d%%] [%c]\r", bar,cnt, lable[cnt%4]); //-100左对齐:长度一百   %%:百分号bar[cnt++] = '#';fflush(stdout); // 如果不强制刷新的话屏幕不显示结果Sleep(50); // 毫秒为单位}printf("\n");
}

vison2

对于我们下载应用这个场景,我们的进度条函数应该知道文件的大小,和当前已经下载了多少时实的更新。所以我们考虑对进度条函数加两个参数 1个total 和 1currnt 代表总的大小 和已经下了的大小

 void processbar(double total, double current){char bar[length];int cnt = 0;memset(bar, '\0', sizeof(bar)); double rate = (current*100.0) / total;int loop = (int)rate;while (cnt <= loop){printf("[%-100s] [%.1lf%%] [%c]\r", bar, rate, lable[cnt % 4]); //-100左对齐:长度一百   %%:百分号bar[cnt++] = '#';fflush(stdout); // 如果不强制刷新的话屏幕不显示结果Sleep(50); // 毫秒为单位}printf("\n");}

构造场景

void loaddown() 
{double filesize = 100 * 1024 * 1024 * 1.0; // 100Mdouble bandwidth = 10 * 1024 * 1024 * 1.0; //1M/Sdouble current = 0.0;printf("download begin, current: %lf\n", current);while (current <= filesize) {processbar(filesize, current);current += bandwidth;Sleep(100);}printf("\ndownload completed\n");
}

我们稍微调整一下进度条函数 调整了两个地方
1.把sleep函数关闭了 因为我们每次都是从零打印的有sleep函数这个卡顿就明显了
2.把printf提在循环外面了因为loaddown多次调用进度条函数在循环里面每次重零打印会卡

 void processbar(double total, double current){char bar[length];int cnt = 0;memset(bar, '\0', sizeof(bar)); double rate = (current*100.0) / total;int loop = (int)rate;while (cnt <= loop){//printf("[%-100s] [%.1lf%%] [%c]\r", bar, rate, lable[cnt % 4]); //-100左对齐:长度一百   %%:百分号bar[cnt++] = '#';// Sleep(50); // 毫秒为单位}printf("[%-100s] [%.1lf%%] [%c]\r", bar, rate, lable[cnt % 4]); //-100左对齐:长度一百   %%:百分号fflush(stdout); // 如果不强制刷新的话屏幕不显示结果}

效果

QQ202431-231356

稍微改进一下download函数

♥1:每个文件的大小并不是一样的,我们要根据实际情况传参数。
♥2:我们把进度条函数当作download的回调函数。这样做有什么好处呢?
我们以后修改进度条函数的时候可以不用修改download函数

void loaddown(double filesize,callback_t cb) 
{double current = 0.0;printf("download begin, current: %lf\n", current);while (current <= filesize) {cb(filesize, current);current += bandwidth;Sleep(100);}printf("\ndownload completed\n");
}

最终效果

QQ202431-233851

谢谢观看

谢谢观看

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/715760.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ安装及使用

系列文章目录 文章目录 系列文章目录前言一、下载二、安装三、插件安装四、配置五、权限六、集群模式 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&…

【MATLAB源码-第154期】基于matlab的OFDM系统多径信道下块状和梳妆两种导频插入方式误码率对比仿真。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 OFDM&#xff08;Orthogonal Frequency Division Multiplexing&#xff0c;正交频分复用&#xff09;是一种高效的无线信号传输技术&#xff0c;广泛应用于现代通信系统&#xff0c;如Wi-Fi、LTE和5G。OFDM通过将宽带信道划分…

RK3568 Android12 适配抖音 各大APP

RK3568 Android12 适配抖音 各大APP SOC RK3568 system:Android 12 平台要适配抖音和各大APP 平台首先打开抖音发现摄像头预览尺寸不对只存在右上角,我将抖音APP装在手机上预览,发现是全屏 一开始浏览各大博客 给出的解决方法是修改framework 设置为全屏显示: framewo…

Tomcat基础及与Nginx实现动静分离,搭建高效稳定的个人博客系统

目录 引言 一、TOMCAT基础功能 &#xff08;一&#xff09;自动解压war包 &#xff08;二&#xff09;状态页 1.登录状态页 2.远程登录 &#xff08;三&#xff09;服务管理界面 &#xff08;四&#xff09;Host虚拟主机 1.设置虚拟主机 2.建立站点目录与文件 二、实…

使用QEMU搭建U-Boot+LinuxKernel+busybox+NFS嵌入式开发环境

目录 0.课程大纲1.为什么要使用QEMU学习嵌入式QEMU简介使用QEMU可以做哪些事情?当前嵌入式行业现状如何适应这种变化使用QEMU学习嵌入式有哪些好处?驱动开发技能为什么要学习Linux 2.搭建嵌入式开发基本环境2.1.安装u-boot-tools2.2.安装交叉编译工具什么是ABI和EABI 3.QEMU安…

三、基准时钟、生成时钟、虚拟时钟的约束和意义

**前言&#xff1a;**前面从理论角度出发学习了时序分析的基本原理&#xff0c;本篇从设计的角度学习如何合理添加时钟约束。 文章目录 一、基准时钟&#xff08;base clock&#xff09;和生成时钟(generate clock)二、基准时钟的约束1.完成综合&#xff08;run implementatio…

linux的通信方案(SYSTEM V)

文章目录 共享内存(Share Memory)信号队列&#xff08;Message Queue&#xff09;信号量(semaphore) 进程间通信的核心理念&#xff1a;让不同的进程看见同一块资源 linux下的通信方案&#xff1a; SYSTEM V 共享内存(Share Memory) 特点&#xff1a;1.共享内存是进程见通信最…

排序(4)——堆排序

目录 堆排序&#xff08;回顾&#xff09; 基本思路 代码实现 向下调整排序 AdjustDown 建堆排序 时间复杂度 特性总结 堆排序&#xff08;回顾&#xff09; 重点回顾戳&#x1f449;堆排序 基本思路 堆排序(Heapsort)是指利用堆积树&#xff08;堆&#xff09;这种数…

鸿蒙系统开发适配注意事项

鸿蒙操作系统&#xff08;HarmonyOS&#xff09;的软件适配涉及到一些特定的注意事项&#xff0c;以确保应用程序在该操作系统上的正常运行和最佳性能。以下是适配鸿蒙软件时需要注意的一些关键问题&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的…

MySQL篇—执行计划介绍(第二篇,总共三篇)

☘️博主介绍☘️&#xff1a; ✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ ✌✌️擅长Oracle、MySQL、SQLserver、Linux&#xff0c;也在积极的扩展IT方向的其他知识面✌✌️ ❣️❣️❣️大佬们都喜欢静静的看文章&#xff0c;并且也会默默的点赞收藏加关注❣…

Python 编辑工具 Jupyter notebook

Jupyter notebook Jupyter Notebook是基于网页的用于交互计算的应用程序。其可被应用于全过程计算&#xff1a;开发、文档编写、运行代码和展示结果。——Jupyter Notebook官方介绍 官网&#xff1a;Project Jupyter | Home Jupyter Notebook 是一个开源的交互式计算环境&#…

网页版图像处理软件开发服务:助您项目在市场竞争中脱颖而出

在当今数字化时代&#xff0c;图像处理在各个行业中扮演着重要的角色&#xff0c;虎克专注于提供定制化的网页版图像处理软件开发服务&#xff0c;为您的项目保驾护航。 1.网页版图像处理软件的定制化需求 1.1行业特定功能 针对不同的业务需求&#xff0c;深入了解行业特点&…

springboot基于web的酒店客房管理系统论文

基于web的酒店客房管理系统 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了酒店客房管理系统的开发全过程。通过分析酒店客房管理系统管理的不足&#xff0c;创建了一个计算机管理酒店客房管理系统的方案。文…

springboot网站开发-idea开发环境下无法开启调试Debug模式

springboot网站开发-idea开发环境下无法开启调试Debug模式的解决办法。 近期在写后端代码的时候&#xff0c;发现&#xff0c;无法开启调试模式。网上查询了一下资料&#xff0c;发现需要做如下修改即可开启调试模式。 如图所示&#xff0c;把里面的选项&#xff0c;都放弃勾选…

SQLPro Studio:数据库管理的革命性工具 mac版

SQLPro Studio是一款强大的数据库管理和开发工具&#xff0c;它旨在提供高效、便捷和安全的数据库操作体验。无论是数据库管理员、开发人员还是数据分析师&#xff0c;SQLPro Studio都能满足他们在数据库管理、查询、设计和维护方面的需求。 SQLPro Studio mac版软件获取 首先…

B树系列(详解)

目录 一、B-树 二、B树 三、B*树 四、时间复杂度 五、Mysql与B树系列 一、B-树 首先再说B树的性质以及其他的之前&#xff0c;先要说一声&#xff0c;好多人都把这个树叫B减树&#xff0c;其实不是&#xff0c;他就叫B树&#xff0c;至于原因我觉的没必要再这个名字上纠结…

docker 转为docker-compose(composerize 命令)

可以使用Composerize将Docker命令转换为Docker Compose文件。 例如&#xff1a;将docker run命令转换为Docker Compose格式&#xff0c;只需用Composerize运行它&#xff0c;如下所示&#xff1a; composerize docker run -d -p 9000:9000 -v /var/run/docker.sock:/var/run/…

【JavaSE】异常

异常概述 异常指的是程序在执行的过程中&#xff0c;出现的非正常情况&#xff0c;如果不处理最终会导致JVM的非正常停止。 在Java中&#xff0c;使用不同的类来表示不同的异常&#xff08;正所谓万物皆对象&#xff0c;因此异常也使用类来表示&#xff09;。一旦程序出现某种…

【HTML】HTML基础5(特殊字符)

目录 特殊字符的作用 常用的特殊字符 使用效果 特殊字符的作用 例如 当我在两个文字间打出空格时 <p>“银河护卫队”系列 在漫威电影宇宙中一直是异数般的存在&#xff0c;不仅因为影片主角是一群反英雄&#xff0c;<strong>与超级英雄相比显得格格不入<…

LeetCode 刷题 [C++] 第347题.前 K 个高频元素

题目描述 给你一个整数数组 nums 和一个整数 k &#xff0c;请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。 题目分析 据题意可知&#xff0c;我们需要先遍历整个数组&#xff0c;并统计每个数字出现的次数&#xff0c;保存在哈希表中&#xff1b;对元素…