目录
前言:
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、行缓冲区
我们先来看三个个征象:
征象一:
先打印并换行。
征象二:
征象三:
先打印不回车换行。
第一个题目:为什么我们在基于征象一后将源文件中的\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;
- }
复制代码 结果演示:
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |