【Linux庖丁解牛】—Linux第一个系统程序—进度条!

目录

前言:

1、回车与换行

历史背景

不同操作系统中的使用

标准输入输出函数

2、行缓冲区

3、进度条version1

4、进度条version2(模拟下载环境)


前言:

在实现进度条之前,这里我们要先铺垫两个概念——回车换行与行缓冲区。

1、回车与换行

在计算机科学和文本处理中,“回车”(Carriage Return,简称 CR,ASCII 码为 13)和“换行”(Line Feed,简称 LF,ASCII 码为 10)是两个不同的概念,但在实际使用中,它们经常联系在一起,用于表示文本行的结束和新行的开始。

历史背景

  • 回车(Carriage Return, CR, \r):在早期的打字机或电传打字机中,回车操作会使打印头移动到当前行的最左端(即回到行首)。
  • 换行(Line Feed, LF, \n):换行操作会使打印头移动到下一行的同一位置(即向下移动一行)。

不同操作系统中的使用

  • Unix/Linux/macOS:这些系统使用 LF(\n)作为行结束符。
  • Windows:Windows 系统最初使用 CR+LF(\r\n)作为行结束符,这是从早期的 DOS 系统继承下来的。这种组合最初是为了兼容当时的打印机和终端。
  • 经典 Mac OS(9 及更早版本):这些系统使用 CR(\r)作为行结束符。

在C语言中,处理文本行结束符时,同样需要考虑到不同操作系统中回车(Carriage Return, CR, \r)和换行(Line Feed, LF, \n)的差异。然而,C语言标准库提供了一些函数和宏,可以帮助程序员处理这些差异,而无需过多关注底层细节。

标准输入输出函数

C语言标准库中的printfscanffgetsfputs等函数通常会自动处理行结束符,以适应不同的操作系统。例如,当使用printf输出一个字符串并包含一个换行符\n时,在Windows系统上,标准输出库函数会将其转换为\r\n(如果输出到控制台或文件),而在Unix/Linux/macOS系统上,则只会输出\n

2、行缓冲区

我们先来看三个个现象:

现象一:

先打印并换行。 

 现象二:

 现象三:

先打印不回车换行。

第一个问题:为什么我们在基于现象一后将源文件中的\n去掉后会出现现象二呢?

难道是程序先执行sleep函数,再执行printf函数吗?答案是否定的,在我们学习C语言时就知道,程序从main函数开始从上至下执行代码。所以,这里一定是先执行printf函数,再执行sleep函数。

那原因到底是什么呢?

这里我们就要引入行缓冲区的概念了:

在C语言中,行缓冲区(line-buffered)是三种类型的输入/输出缓冲区之一,另外还有全缓冲区(fully-buffered)和无缓冲区(unbuffered)。行缓冲区的行为取决于所使用的标准I/O函数和流(stream)。

行缓冲区的特点:当遇到换行符(\n)或者缓冲区满时,缓冲区内容会被刷新(即写入到目标设备)。

解释:当printf函数执行完后,其内容并没有打印到显示器上,而是在缓冲区里面(没有遇到换行符(\n)或者缓冲区满)。然后执行完sleep函数后,程序结束会自动刷新缓冲区,最后才打印出内容“Hello Linux!”。

第二个问题:现象三为什么会先打印后休眠?

这里我们就介绍一下fflush函数:

  • fflush(FILE *stream):刷新指定流的缓冲区。即使缓冲区没有满或没有遇到换行符,调用这个函数也会强制将缓冲区内容写入目标设备。

3、进度条version1

#include"process.h"

#define NUM 101
#define STYLE '='

void processbar()
{
//buffer数组模拟进度条
    char buffer[NUM];
    memset(buffer, 0, sizeof(buffer));
    //lable字符串模拟旋转效果
    const char* lable = "\\-|/";
    int size = strlen(lable);
    int cnt = 0;
    while (cnt <= 100)
    {
        printf("[%-100s][%d%%][%c]\r", buffer, cnt, lable[cnt % size]);
        fflush(stdout);
        buffer[cnt] = STYLE;
        usleep(50000);
        cnt++;
     }
    printf("\n");
}

效果演示: 

4、进度条version2(模拟下载环境)

第一个版本我们只是将进度条的运行效果演示成功了,在实际程序下载的过程中我们不可能直接将上面的程序当做进度条,不然很大可能,我们的程序还没有下载完,而进度条就已经跑完了,这是不合理的!

所以,在实际场景中,我们要根据下载的总量和当前的下载量,来决定进度条的进度!

具体如何操作,大家看下面的代码就完全可以看懂啦!(非常简单的)

process.c

#include"process.h"

void process(double total, double cur)
{
    //改函数会被下载的任务频繁调用,所以cnt设为静态
    static int cnt = 0;
    char buffer[NUM];
    memset(buffer, 0, sizeof(buffer));
    
    //模拟旋转效果
    const char* lable = "\\-|/";
    int len = strlen(lable);
   
    //找到当前进度的位置
    int num = (int)(cur * 100) / total;
    int i = 0;
    for (; i < num; i++)
    {
        buffer[i] = STYLE;
    }
    //不再循环打印,直接根据当前下载进度打印出进度条
    printf("[%-100s][%.1f%%][%c]\r",
            buffer, cur / total * 100, lable[cnt % len]);
    fflush(stdout);
    cnt++;
}

main.c

#include"process.h"

double total = 1024.0;
double speed = 1.0;//加载速度
//该函数用于模拟程序的下载
void DownLoad()
{
    double cur = 0;
    while (cur <= total)
    {
        process(total, cur);
        usleep(3000);
        cur += speed;
    }
    printf("\n");
}



int main()
{
    DownLoad();
    DownLoad();
    DownLoad();
    DownLoad();
    return 0;
}

效果演示: 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

支付域——支付路由设计

摘要 本文深入探讨了支付路由系统的背景、核心作用、设计原则以及业界常见形态。文章详细解析了支付方式咨询、渠道咨询和渠道路由的概念&#xff0c;并介绍了支付路由的规则种类、交易参数、通道属性和常见筛选规则。进一步讨论了基于规则的渠道路由设计、自动化开关的渠道路…

Windows内核开发环境配置

SDK 软件开发工具包 r3用到的win32api 就是SDK WDK 驱动内核 r0用到的包 Previous WDK versions and other downloads - Windows drivers | Microsoft Learn sdk版本必须和wdk版本一致 驱动环境部署 #include <ntifs.h>NTSTATUS DriverUnload(PDRIVER_OBJECT pDriver) …

高强度螺栓等级划分

高强度螺栓的等级划分主要依据其性能等级&#xff0c;常见的等级有8.8级和10.9级。这些等级标号由两部分数字组成&#xff0c;分别表示螺栓材料的公称抗拉强度值和屈强比值。 8.8级高强度螺栓&#xff1a;表示螺栓杆的抗拉强度不小于800MPa&#xff0c;屈强比&#xff08;屈服强…

【VMware虚拟机】安装win10系统教程双机可ping通

目录 1、下载1.1、点击链接下载媒体创建工具&#xff1a;1.2、下载后得到MediaCreationTool_22H2.exe&#xff1a;1.3、获取ISO镜像 2、安装3、显示4、配置网络4.1、配置4.2、排查4.2.1、关闭防火墙4.2.2、增加路由 1、下载 Windows10微软官网下载链接: https://www.microsoft…

Jetson xavier 刷机安装教程

在对Jetson进行刷机过程&#xff0c;浏览了很多的相关教程&#xff0c;大部分教程并不全&#xff0c;而且按照步骤执行会出现许多奇奇怪怪的错误&#xff0c;为了避免大家踩坑&#xff0c;这里给出了完整的解决方法&#xff0c;希望能够提供帮助&#xff01; 首先大家需要准备…

41 stack类与queue类

目录 一、简介 &#xff08;一&#xff09;stack类 &#xff08;二&#xff09;queue类 二、使用与模拟实现 &#xff08;一&#xff09;stack类 1、使用 2、OJ题 &#xff08;1&#xff09;最小栈 &#xff08;2&#xff09;栈的弹出压入序列 &#xff08;3&#xf…

申请腾讯混元的API Key并且使用LobeChat调用混元AI

申请腾讯混元的API Key并且使用LobeChat调用混元AI 之前星哥写了一篇文章《手把手教拥有你自己的大模型ChatGPT和Gemini等应用-开源lobe-chat》搭建的开源项目&#xff0c;今天这篇文章教大家如何添加腾讯云的混元模型&#xff0c;并且使用LobeChat调用腾讯混元AI。 申请腾讯混…

物理层知识要点

文章目录 物理层接口的四大特性通信基础编码和调制&#xff08;1&#xff09;数字数据编码为数字信号&#xff08;2&#xff09;模拟数据编码为数字信号&#xff08;3&#xff09;常见调制方式&#xff08;3&#xff09;信道的极限容量 多路复用技术数据传输方式物理层下的传输…

第十五章 C++ 数组

C 支持数组数据结构&#xff0c;它可以存储一个固定大小的相同类型元素的顺序集合。数组是用来存储一系列数据&#xff0c;但它往往被认为是一系列相同类型的变量。 数组的声明并不是声明一个个单独的变量&#xff0c;比如 number0、number1、...、number99&#xff0c;而是声…

LabVIEW开发需要懂那些数学知识?

LabVIEW开发是一种图形化编程方法&#xff0c;广泛应用于工程和科学领域。在开发过程中&#xff0c;数学知识是不可或缺的&#xff0c;它不仅是分析和设计复杂系统的基础&#xff0c;还能提升开发效率和系统性能。下面将从应用需求、案例分析、介绍LabVIEW开发中所需的数学知识…

QT的前景与互联网岗位发展

qt是用来干什么的 --》桌面应用开发&#xff08;做电脑的应用程序&#xff0c;面对客户端&#xff09;。 主要用于开发跨平台的应用程序和用户界面&#xff08;UI&#xff09;。它是一个全面的C库集合&#xff0c;提供了构建软件应用所需的各种工具和功能。 客户端开发的重…

奇异值分解在图像压缩中的应用

奇异值分解&#xff08;SVD&#xff09;定理 奇异值矩阵 和A的大小相同都是mn主对角线元素&#xff1a;从大到小排列&#xff0c;称为奇异值其他位置0 例&#xff1a; 在这里&#xff0c;第1个矩阵和第3个矩阵为正交矩阵 中间的矩阵奇异值矩阵&#xff0c;奇异值7.7&#xf…

【vue】圆环呼吸灯闪烁效果(模拟扭蛋机出口处灯光)

效果图先发&#xff1a; 页面部分&#xff1a; <div ref"round" class"round"><div class"light" ref"light"/><div class"box"></div></div>js部分(控制圆环生成&#xff09;; setRound…

Python(二)str、list、tuple、dict、set

string name abcdefprint(name[0]) #a # 切片&#xff1a;取部分数据 print(name[0:3]) # 取 下标为0,1,2的字符 abc print(name[2:]) # 取 下标为2开始到最后的字符 cdef print(name…

EasyExcel停更,FastExcel接力

11月6日消息&#xff0c;阿里巴巴旗下的Java Excel工具库EasyExcel近日宣布&#xff0c;将停止更新&#xff0c;未来将逐步进入维护模式&#xff0c;将继续修复Bug&#xff0c;但不再主动新增功能。 EasyExcel以其快速、简洁和解决大文件内存溢出的能力而著称&#xff0c;官方…

项目实战——高并发内存池

一.项目介绍 本项目——高并发内存池&#xff0c;是通过学习并模仿简化 google 的一个开源项目 tcmalloc &#xff0c;全称 Thread-Caching Malloc&#xff0c;即线程缓存的malloc&#xff0c;模拟实现了一个自己的高并发内存池&#xff0c;用于高效的多线程内存管理&#xff…

结合实例从HCI层分析经典蓝牙连接和配对过程

我们知道&#xff0c;经典蓝牙BREDR的link key协商是在LMP层做的&#xff0c;那么蓝牙Host在鉴权的过程中&#xff0c;会跟BT SOC有哪些交互&#xff1a; 首次配对 在HCI Inuqiry找到想要配对的设备后&#xff0c;Host会调用HCI Create Connection命令去连接对方设备&#xf…

java全栈day20--Web后端实战(Mybatis基础2)

一、Mybatis基础 1.1辅助配置 配置 SQL 提示。 默认在 mybatis 中编写 SQL 语句是不识别的。可以做如下配置&#xff1a; 现在就有sql提示了 新的问题 产生原因&#xff1a; Idea 和数据库没有建立连接&#xff0c;不识别表信息 解决方式&#xff1a;在 Idea 中配置 MySQL 数…

RK356x-11:在win11的WSL中开发SDK

我拿到的SDK建议开发的系统是Ubuntu22.04&#xff08;在SDK-docs中的文档有说明&#xff09;&#xff0c;因此&#xff0c;WSL中要先安装好它。由于PC机上WSL本身不支持aarch64架构&#xff0c;所以&#xff0c;进行ARM64的RK356X开发&#xff0c;需要手动加入支持。用到的支持…

【unity c#】深入理解string,以及不同方式构造类与反射的性能测试(基于BenchmarkDotNet)

出这篇文章的主要一个原因就是ai回答的性能差异和实际测试完全不同&#xff0c;比如说是先获取构造函数再构造比Activator.CreateInstance(type)快&#xff0c;实际却相反 对测试结果的评价基于5.0&#xff0c;因为找不到unity6确切使用的net版本&#xff0c;根据c#9推测是net5…