目录
前言:
回车和换行有区别吗?
回车和换行的区别展示(这个我在Linux下演示)
为什么会消失呢?
回车和换行的区别
为什么'\r'和'\n'产生的效果不同?
打印进度条:
(1)打印字符串
(2)显示百分数
(3)完结撒花
前言:
在这里我要问大家一个问题,请问:
回车和换行有区别吗?
有些人的回答是:我感觉没区别啊,Enter键就是回车,我平时按了就换行了
有些人的回答是:有区别,但是我也具体说不出来,但是在C语言里,换行是'\n',但是回车却是'\r'
其实答案是:有区别
回车和换行的区别展示(这个我在Linux下演示)
但我们在一个test.c文件中写入如下代码时:
#include <stdio.h>#include <unistd.h>//注意头文件int main(){printf("Hello 努力的你\n"); sleep(3); return 0; }
会输出
Hello 努力的你
并且停顿三秒 (停顿时如下所示)
这并不稀奇,但是你将代码里的'\n'换为'\r'时,如下
#include <stdio.h>#include <unistd.h>//注意头文件int main(){printf("Hello 努力的你\r"); sleep(3); return 0; }
你同样会发现停顿了三秒,但并未输出任何东西(停顿时如下所示)
但当在sleep(3);之前加入
fflush(stdout);
{
关于fflush的原型的查看,C语言中我们右cplusplus,或者MSDN,但在Linux下,Linux自带了功能查询,我们可以在命令行中输入以下代码来查看相应功能(要退出,则输入:q
要上下翻:用键盘的上下键(千万不要用鼠标哦,自己可以试试看哦,在Linux下,鼠标大多是没用的))
man fflush
//man 命令:可以查看该命令的具体信息
将会出现如下信息
是不是和cplusplus和MSDN很像
这里我们看出fflush属于<stdio.h>这个文件
它的参数为一个文件指针(Linux内部,一切视为文件)
而我们这里需要把stdout(标准输出流)作为参数(后面会说为什么)
}
代码如下所示:
1 #include <stdio.h>2 #include <unistd.h>3 4 int main()5 {9 printf("Hello 努力的你\r");10 fflush(stdout); 11 sleep(3);14 return 0; 15 }
这时会显示出“Hello 努力的你”
细心的你可能会发现,这里的光标并不像往常一样在打印的这句话的最后,而是在开头
而这个代码 被执行 到 执行完 经历了以下过程:
先打印“Hello 努力的你”,再停顿3秒, “Hello 努力的你”再消失不见
为什么会消失呢?
这就回到了我们一开始的问题: 回车和换行有区别吗?
答案也公布了,是有的
回车和换行的区别
在一些键盘中,Enter键可能会是如下样子:
大家有没有思考过,明明是换行功能,它为什么还有个转折呢?
如果用画图来表示换行,那将是这个样子:
只是行变了,列并没有变
但是回车,就是如下样子:
行变了,而列回到了新一行的开头
(这也是为什么键盘的Enter键长那个样子的原因)
这就是换行和回车的不同
为什么'\r'和'\n'产生的效果不同?
*为什么'\r'时就不显示任何东西呢(没有fflush的情况下)
*这里要讲到缓冲区的概念
*因为在计算机内部,如果每次输出直接输出到屏幕,是非常慢的,因为它是外部设备,输出需要用到CPU的运行,但是一个计算机的快慢也满足短板原理,慢的步骤会决定整个步骤的快慢,
在计算机中速度由快到慢是:
CPU > 内存 > 磁盘
我们不能只要要输出就占用CPU资源,这就需要设置一个区域专门的区域来存储即将输出的数据,而内存就是一个比较高性价比的地方,速度不快不慢,价格也适中,这就有了缓冲区
而我们经常做的printf语句输出的内容通常并不是该语句执行完了就立马打印,而是先放在缓冲区再打印,但是为什么平时看起来是立马打印呢?😶😶😶
因为我们通常会在printf的语句的最后加上一个'\n',当遇到'\n'时,计算机会自动刷新缓冲区的内容到输出设备,而我们的printf就是输出到显示器,这就是为啥printf完就立马输出的原因(⊙o⊙)!!!me懂了
但是'\r'并不和'\n'一样具有刷新缓冲区的功能(●ˇ∀ˇ●),它将要打印的语句放进了缓冲区,当程序快结束时,再输出,但是'\r'会将光标移到一行的开头!!!!!!!!!.......Σ(っ °Д °;)っ哇哦,所以当要打印时,显示器上会显示光标前的内容,并清空缓冲区,但是光标已经在缓冲区的开头,所以没有输出任何东西ฅʕ•̫͡•ʔฅ
而fflush的作用是(⊙o⊙)????
这个也在之前的man fflush的文件中写了
翻译ヾ(≧▽≦*)o: 对于输出流,fflush()通过流的底层写函数强制为给定的输出或更新流写入所有用户空间缓冲数据。对于输入流,fflush()将丢弃从底层文件中获取但尚未被应用程序使用的任何缓冲数据。流的打开状态不受影响。
也就是说会打印缓冲区的内容,并刷新缓冲区
而我们的“Hello 努力的你”就在缓冲区里,所以被打印了出来,但是'\r'还是让光标回到了打印的语句的最开头,所以sleep三秒后,缓冲区的刷新,让“Hello 努力的你”这句话不见了
不知道到这里你看懂了吗?你可是看了快两千字了哦,太厉害了吧,夸夸自己(/≧▽≦)/,给你赞一个d=====( ̄▽ ̄*)b
现在就要讲各位心心念念的进度条的实现啦~~~
先看看效果啦~~(转gif失败了(哭哭){{{(>_<)}}})
首先进度条是一个字符串,因此,要设置一个字符串
char jin_du_tiao[150];
同时我们要控制它的进度条的#个数不断增加----->需要一个循环来给进度条不断增加字符----->不能无限循环,要有退出条件----->设置一个变量,当这个变量长度为100时就退出循环
while (cnt <= 100){jin_du_tiao[cnt++] = '#';}
打印进度条:
(1)打印字符串
while (cnt <= 100){printf("%s\n", jin_du_tiao);jin_du_tiao[cnt++] = '#';}
(2)显示百分数
在格式输出中,显示百分号用:
%%
while (cnt <= 100){printf("%s%d%%\n", jin_du_tiao, cnt);jin_du_tiao[cnt++] = '#';}
但是这样子打印出来的结果是😥:
0%
#1%
##2%
.
.
.################################################################100%
谁家进度条的进度跟着进度条走啊😣😣,何况进度条走那么快,谁看得清那个数字😫啊,而且 数字 和 # 紧紧挨在一起一点都不好看😡
这就用到了格式控制符 .......ε=ε=ε=(~ ̄▽ ̄)~
while (cnt <= 100){printf("[%-100s][%d%%]\n", jin_du_tiao, cnt);// -:左对齐 100:让后面的百分比不会跟着进度条跑 %%:显示百分号jin_du_tiao[cnt++] = '#';}
-:左对齐 100:让后面的百分比不会跟着进度条跑 %%:显示百分号
但是这样子打印出来的效果是:
[ ] [0%]
[#] [1%]
[##] [2%]
.
.
.
.
[#################################################################][100%]
没有左对齐时:
[ ] [0%]
[ #] [1%]
[ ##] [2%]
.
.
.
.
[#################################################################][100%]
谁家进度条一行一行的啊 ╰(‵□′)╯,进度条不应该在一行吗?
欸嘿,这里就用到了'\r'啦~~~~,'\r'起到了从头开始打印的效果
while (cnt <= 100){printf("[%-100s][%d%%]\r", jin_du_tiao, cnt);// -:左对齐 100:让后面的百分比不会跟着进度条跑 \r:有刷新的效果 %%:显示百分号jin_du_tiao[cnt++] = '#';fflush(stdout); //一定记得要fflush(stdout)}
但是这样你会发现,当你一执行就会显示完整的进度条 (。・・)ノ
[#################################################################][100%]
所以让它sleep一下下~~~~~,可是sleep就比较懒(。>︿<)_θ,很慢,这样子打印进度条就超慢,这样子使用者恨不得卸载软件啦 ~Σ(っ °Д °;)っ
那就换个勤快点的吧:usleep
sleep:以秒为单位
usleep:以微秒为单位
(3)完结撒花
int main()
{int cnt = 0;char jin_du_tiao[150];while (cnt <= 100){printf("[%100s][%d%%]\r", jin_du_tiao, cnt);// -:左对齐 100:让后面的百分比不会跟着进度条跑 \r:有刷新的效果 %%:显示百分号jin_du_tiao[cnt++] = '#';fflush(stdout); //一定记得要fflush(stdout)usleep(300000);//usleep(300000):以毫秒为单位 注意包含头文件:<unistd.h>}return 0;
}
哦吼吼,太酷了,你快看了四千字哦,给你大大的赞哦 👍,我也和这几千字合个影吧(写了快四个小时)✌😀✌