C语言/C++常见习题问答集锦(六十三) 之endl引发的思考

C语言/C++常见习题问答集锦(六十三) 之endl引发的思考

程序之美

在这里插入图片描述

C语言/C++开发的小伙伴们,对于endl,大家可能都不陌生吧,本文探讨一下C++中使用的时候加endl和不加endl的区别,为啥要探讨加与不加endl呢,这个的从头说起,CSDN问答中有小伙伴求救说,写了一个C++程序,如下:

#include <iostream>

#include <unistd.h>

using namespace std;

int main()
{
    cout<<"I like cats.";
    sleep(3);
    cout<<'\r';
	cout<<"I like dogs.";
    return 0;
}

在vscode里运行以上代码,不是像windows系统的DEV C++或Visual C++那样:先显示“I like cats.”,持续3秒后,原输出刷新成“I like dogs.”。而是只在等待3秒后显示最终的“I like dogs.”。(输出结果显示在Terminal)

而把输出表示不换行回到当前行首的’\r’删除后(如上所示),点击运行,一开始什么动静都没,在等待3s后同时输出了“I like cats.”和“I like dogs.”。

请问在vscode里应该怎样操作才能有第一段里DEV C++那样的效果呢?

初步验证

看到这里,不知道小伙伴们有没有验证过,或许,我们有时候发现这样不行,实习不了我们想要的功能,就换一种方式,解决问题就OK了,并没有真正的去思考下,为什么那样不行呢,这里我就带着大家一步一步解答下这个问题。

首先,我们先将代码复制到VSCode IDE中,运行下,看下效果,如下图:
在这里插入图片描述
正如小伙伴描述的一样,延迟大概三秒钟,直接就输出了一个“I like dogs.”,这个并不是我们预期的。那么该如何解决呢?

我们打开控制输入输出的接口,发现除了cout、cin,还有endl,定义如下:

  /**
   *  @brief  Write a newline and flush the stream.
   *
   *  This manipulator is often mistakenly used when a simple newline is
   *  desired, leading to poor buffering performance.  See
   *  https://gcc.gnu.org/onlinedocs/libstdc++/manual/streambufs.html#io.streambuf.buffering
   *  for more on this subject.
  */
  template<typename _CharT, typename _Traits>
    inline basic_ostream<_CharT, _Traits>&
    endl(basic_ostream<_CharT, _Traits>& __os)
    { return flush(__os.put(__os.widen('\n'))); }

大概这个就是我们想要的,赶快加上验证下:

#include <iostream>

#include <unistd.h>

using namespace std;

int main()
{
    cout<<"I like cats."<<endl;
    sleep(3);
    cout<<'\r';
	cout<<"I like dogs."<<endl;
    return 0;
}

运行结果如下:
在这里插入图片描述正是我们预期的,先输出"I like cats.",然后延迟了大概三秒钟,执行输出“I like dogs.”

这时,我们需要思考下,为啥endl就可以达到我们想要的结果呢,加endl和不加endl有啥区别呢?

深入剖析

首先,endl就是end line的区别,也就是“结束此行”,但实际上有两个操作

1 换行
2 对缓冲流进行冲刷,使得流中所有剩余字符被写入输出序列。正如函数注释的一样,Write a newline and flush the stream.

其实作用说白了就是加<<endl后会有一个换行。下次再用cout输出字符时就会在下一行开始输出,如果不加,就会跟在当前行的最后输出;加了endl会执行flash,将buffer中的内容进行输出。

原来是因为之前的cout的内容保存到buffer中,并没有执行真的输出,只有在执行endl后,才完成了真正的输出。那么是不是缓冲区的问题,我们可以进行如下验证,
1、将缓冲区填满,让其强制输出
2、执行输出其他内容,看之前的结果是否会被输出。

我们先来验证第二条:

#include <iostream>

#include <unistd.h>

using namespace std;

int main()
{
    cout<<"I like cats.";

	cout<<"force to flash.";

    sleep(3);
    cout<<'\r';
	cout<<"I like dogs."<<endl;
    return 0;
}

运行结果如下:
在这里插入图片描述并不满足我们的需求。

下面我们验证第一条:

#include <iostream>

#include <unistd.h>

using namespace std;

int main()
{
    cout<<"I like cats.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.force to flash.";

    sleep(3);
    cout<<'\r';
	cout<<"I like dogs."<<endl;
    return 0;
}

运行结果如下:
在这里插入图片描述

和我们预期的一样,先将长串输出后,延迟大概三秒,输出"I like dogs."

那么还有没有其他的方式也让cout执行刷新呢,这时我们想到了换行,下面我们进行验证:

#include <iostream>

#include <unistd.h>

using namespace std;

int main()
{
    cout<<"I like cats.";
	cout<<"\n";
    sleep(3);
    cout<<'\r';
	cout<<"I like dogs."<<endl;
    return 0;
}

运行结果如下:

在这里插入图片描述

和我们预期的一样,先将“I like cats.”输出后,延迟大概三秒,输出"I like dogs."

由此我们可以知道了,确实是flash的问题,Sleep之前的因为没有及时刷到屏幕上,三秒后被后面的冲掉了。

使用cout让输出内容及时刷新到屏幕上,一种方式是使用endl,另外一种方式就是输出"\n", 这两种方式都可以实现我们的预期,将缓冲区中的输出内容及时刷新到屏幕上。

好了,就说到这里吧,希望小伙伴们能在学习的过程中,多多提出疑问,这样是最快的学习和成长的方式,经过一段时间的坚持,你会有意想不到的收获,也希望小伙伴们多多关注我!!!

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五一编程

程序之路有我与你同行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值