北冰洋以北 发表于 2024-12-27 01:57:07

【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语言标准库中的printf、scanf、fgets、fputs等函数通常会自动处置惩罚行竣事符,以顺应不同的操纵体系。例如,当使用printf输出一个字符串并包罗一个换行符\n时,在Windows体系上,标准输出库函数会将其转换为\r\n(如果输出到控制台或文件),而在Unix/Linux/macOS体系上,则只会输出\n。
2、行缓冲区

我们先来看三个个征象:
征象一:
https://i-blog.csdnimg.cn/direct/9f0e1dfd70644a92886d502740283b8a.png
先打印并换行。 
https://i-blog.csdnimg.cn/direct/79a2854b5ec2496981cf57bd580e5e36.png 征象二:
https://i-blog.csdnimg.cn/direct/96d2daeb3aa54e019a56bf681d894c18.png
https://i-blog.csdnimg.cn/direct/d176bdc87e6c4632878ca701edecc88a.png 征象三:
https://i-blog.csdnimg.cn/direct/871b213a19df44ffa894577d78a9d868.png
先打印不回车换行。
https://i-blog.csdnimg.cn/direct/7ff3005ab4394057ba174530217ba265.png
第一个题目:为什么我们在基于征象一后将源文件中的\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;
    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);
      fflush(stdout);
      buffer = STYLE;
      usleep(50000);
      cnt++;
   }
    printf("\n");
}

结果演示: 
https://i-blog.csdnimg.cn/direct/ba3c3c4ac7e84101b52563c0cb6bf49c.png
4、进度条version2(模拟下载环境)

第一个版本我们只是将进度条的运行结果演示乐成了,在现实步伐下载的过程中我们不可能直接将上面的步伐当做进度条,不然很大可能,我们的步伐还没有下载完,而进度条就已经跑完了,这是不合理的!
以是,在现实场景中,我们要根据下载的总量和当前的下载量,来决定进度条的进度!
详细如何操纵,大家看下面的代码就完全可以看懂啦!(非常简朴的)
https://i-blog.csdnimg.cn/direct/350cb1c95be0496c8d7c5e08bd1972df.png
process.c
#include"process.h"

void process(double total, double cur)
{
    //改函数会被下载的任务频繁调用,所以cnt设为静态
    static int cnt = 0;
    char buffer;
    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 = STYLE;
    }
    //不再循环打印,直接根据当前下载进度打印出进度条
    printf("[%-100s][%.1f%%][%c]\r",
            buffer, cur / total * 100, lable);
    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;
} 结果演示: 
https://i-blog.csdnimg.cn/direct/815dbb41627f4afc858b61b482f10f9d.png

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 【Linux庖丁解牛】—Linux第一个体系步伐—进度条!