【问题标题】:std::this_thread::sleep_for() freezing the programstd::this_thread::sleep_for() 冻结程序
【发布时间】:2022-01-09 17:14:07
【问题描述】:

我正在制作一个加载类型的函数,所以我想做的是暂停我的程序几秒钟,然后在循环内恢复执行,使其看起来像一个加载过程。在网上查找我发现我可以使用std::this_thread::sleep_for() 来实现这一点(我在linux上这样做)。我面临的问题是,我无法使用\r 或任何其他方式覆盖最后输出的百分比,因为程序一执行就冻结,但是它与\n 完美配合,仅此而已令人困惑的是为什么它可以使用换行符序列而不是\r

我在下面发布示例代码,有人可以告诉我我做错了什么吗?

#include<iostream>
#include<chrono>
#include<thread>

int main()
{
    for (int i = 0; i<= 100; i++)
    {
        std::cout << "\r" << i;
        std::this_thread::sleep_for(std::chrono::seconds(rand()%3));
    }
    return 0;
}

我对这个话题有点陌生,经过一番挖掘后,我发现我在搞乱线程。但仍然不确定为什么会发生这种行为。

【问题讨论】:

  • 你可以只刷新流吗? cout 被缓冲。见stackoverflow.com/questions/22026751/…
  • 程序未冻结。如果设置断点,您将看到std::cout &lt;&lt; "\r" &lt;&lt; i; 确实每隔几秒运行一次。问题是您没有刷新输出,因此结果仍在缓冲区中等待打印。它适用于\n,因为在打印\n 时会自动刷新。但是\r 没有这个特殊属性。
  • 非常感谢您的回复,添加 std::flush 完成了这项工作,但现在我无法理解的是为什么会这样?我的意思是我第一次用\r 打电话给 cout 时,它仍然应该打印一些东西,对吗?但如果我不刷新流,它根本不会打印任何东西。它与std::this_thread::sleep_for 或只是cout 函数有关吗?我在这里错过了什么吗?也许执行图表或类似的东西会很有用,或者对该主题进行进一步的阐述。并再次感谢您为我解决这个问题。 :)
  • @RaymondChen 请将您的评论移至答案。

标签: c++


【解决方案1】:

这在我的机器上运行良好(Windows 10):

#include <iostream>
#include <chrono>
#include <thread>
#include <cstdlib>
#include <ctime>


int main( )
{
    std::srand( std::time( 0 ) );

    for ( std::size_t i { }; i < 100; ++i )
    {
        std::cout << '\r' << i;
        std::this_thread::sleep_for( std::chrono::seconds( std::rand( ) % 3 ) );
    }
}

我建议你写'\r'而不是"\r",因为这里你只想打印\r字符,而"\r"实际上打印两个字符(\r\0)。
此外,最好在调用之前使用srand 播种rand

但是,它在某些环境中可能无法按预期工作,因此您可能需要刷新输出序列,如下所示:

std::cout << '\r' << i << std::flush;

或者像这样:

std::cout << '\r' << i;
std::cout.flush( );

这些是等价的。

有关flush 的更多信息,请参阅here

【讨论】:

  • 如果不刷新cout,即使这个也无法工作。我什至刚刚在一些在线编译器以及 linux g++ 上尝试过。一旦我添加std::flush,它就可以正常工作,否则它会停止。程序的执行流程现在让我很困惑。还有你所说的使用srand 播种我一定会尝试一下:) 这是一个很好的建议。
  • @Jiaar 你在哪一行添加了std::flush
  • 我用std::cout &lt;&lt; '\r' &lt;&lt; i &lt;&lt; std::flush;代替了for循环中的std::cout &lt;&lt; '\r' &lt;&lt; i;,它开始按预期工作。我认为这是添加它的正确位置,它与我使用 \ncout 相同,即我使用的是 std::cout &lt;&lt; '\n' &lt;&lt; i;,一切正常,但我得到了新线路,但事实并非如此为我准备的。
  • "\r" actually prints two characters (\r and \0) 为假。 std::cout &lt;&lt; '\r'std::cout &lt;&lt; "\r" 做同样的事情。
  • "\r" 是一个包含两个字符的缓冲区 确实如此。 我可能在打印方面错了确实,你是。
猜你喜欢
  • 1970-01-01
  • 2011-05-25
  • 1970-01-01
  • 2020-10-19
  • 2021-12-25
  • 2020-10-07
  • 2020-10-15
  • 1970-01-01
  • 2016-08-31
相关资源
最近更新 更多