在命令行C ++上显示进度

时间:2013-09-02 08:14:05

标签: c++

我有以下代码在用C ++编写的命令行应用程序中运行

std::string filename = m_arguments[1];
unsigned long long size = stoll(m_arguments[2]);
char character = m_arguments[3].c_str()[1]; 

FILE *pFile;
if( (pFile = fopen(filename.c_str(), "wb")) != NULL)
{
  for(int i = 0; i<size; i++)
  {
    fputc(character, pFile);
    unsigned long long  per = 100*i/size;
    if(per % 10 == 0) { cout<<"\r"<<per<<"%"<<flush; }
  }
  fclose(pFile);
}
cout<<endl;

命令行上的百分比闪烁。我尝试使用if(per%10 == 0)减少闪烁,但没有任何变化。我该怎么做才能阻止这种闪烁?

2 个答案:

答案 0 :(得分:3)

你能做的最好的事情就是只显示自上次循环以来它发生变化的百分比。这样可以最大限度地减少您对控制台的输出量,这也会使您的速度降低很多,因为效率非常低。 还修复了循环变量类型。

    std::string filename = m_arguments[1];
    unsigned long long size = stoll(m_arguments[2]);
    char character = m_arguments[3].c_str()[1]; 

    FILE *pFile;
    if( (pFile = fopen(filename.c_str(), "wb")) != NULL)
    {
      int last_per = -1;
      for(unsigned long long i = 0; i<size; i++)
      {
        fputc(character, pFile);
        int  per = (int)(100*i/size);
        if(last_per != per) { cout<<"\r"<<per<<"%"<<flush; last_per = per; }
      }
      fclose(pFile);
    }
    cout<<endl;

答案 1 :(得分:0)

只是玩,但是:

int i = 0;
while ( i != 100 ) {
    i += 10;
    std::cout << '\r' << std::setw(2) << i << '%' << std::flush;
    Sleep( 2000 );
}
std::cout << "\rDone" << std::endl;

我看不到任何闪烁。

您的案例中的问题是您唯一的测试是per % 10 == 0。如果文件很大,您最终会输出每个值 在你传输的每个字节之后,很多次。 如果文件是100KB(不是很大),这将输出 0到999之间的每个字节,然后是10000之间的每个字节 和10999,等等。

这个也不应该闪烁,但是我做了一些试验 一个标准的Windows控制台窗口显示它确实如此。乃至 如果没有闪烁,它会大大减慢速度。您 但是,应该记住最后一个输出 输出时更改:

int lastOutput = -1;
for ( ... ) {
    //  ...
    if ( per % 10 == 0 ) {
        int toOutput = 100LL * i / size;
        if ( toOutput != lastOutput ) {
            std::cout << '\r' << toOutput << '%' << std::flush;
            lastOutput = toOutput;
        }
    }
}

然而,这可以更有效地完成。只有十个 输出,我可能会创建一个包含十个条目的表, 指示我想要输出的i的值,以及 检查一下。