0

我有以下代码在用 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)但没有任何变化。我能做些什么来阻止这种闪烁?

4

2 回答 2

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;
于 2013-09-02T08:25:18.123 回答
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我想要输出的值,并对此进行检查。

于 2013-09-02T09:02:12.817 回答