如何在纯 C/C++ (cout/printf) 中显示进度指示器?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14539867/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:25:28  来源:igfitidea点击:

How to display a progress indicator in pure C/C++ (cout/printf)?

c++cuser-interfacec++11io

提问by xmllmx

I'm writing a console program in C++ to download a large file. I have known the file size, and I start a work thread to download. I want to show a progress indicator to make it look cooler.

我正在用 C++ 编写一个控制台程序来下载一个大文件。我已经知道文件大小,我开始了一个工作线程来下载。我想显示一个进度指示器,让它看起来更酷。

How to display different strings at different times, but at the same position, in cout or printf?

如何在不同的时间,但在相同的位置,在 cout 或 printf 中显示不同的字符串?

采纳答案by James Curran

You can use a "carriage return" (\r) without a line-feed (\n), and hope your console does the right thing.

您可以使用不带换行符 (\n) 的“回车符”(\r),并希望您的控制台能做正确的事情。

回答by leemes

With a fixed width of your output, use something like the following:

使用固定宽度的输出,使用如下所示的内容:

float progress = 0.0;
while (progress < 1.0) {
    int barWidth = 70;

    std::cout << "[";
    int pos = barWidth * progress;
    for (int i = 0; i < barWidth; ++i) {
        if (i < pos) std::cout << "=";
        else if (i == pos) std::cout << ">";
        else std::cout << " ";
    }
    std::cout << "] " << int(progress * 100.0) << " %\r";
    std::cout.flush();

    progress += 0.16; // for demonstration only
}
std::cout << std::endl;

http://ideone.com/Yg8NKj

http://ideone.com/Yg8NKj

[>                                                                     ] 0 %
[===========>                                                          ] 15 %
[======================>                                               ] 31 %
[=================================>                                    ] 47 %
[============================================>                         ] 63 %
[========================================================>             ] 80 %
[===================================================================>  ] 96 %

Note that this output is shownone line below each other, but in a terminal emulator (I think also in Windows command line) it will be printed on the same line.

请注意,此输出显示在一行下方,但在终端模拟器中(我认为也在 Windows 命令行中)它将打印在同一行上

At the very end, don't forget to print a newline before printing more stuff.

最后,不要忘记在打印更多内容之前打印换行符。

If you want to remove the bar at the end, you have to overwrite it with spaces, to print something shorter like for example "Done.".

如果要删除最后的栏,则必须用空格覆盖它,以打印更短的内容,例如"Done.".

Also, the same can of course be done using printfin C; adapting the code above should be straight-forward.

同样,当然可以printf在 C 中使用;修改上面的代码应该是直截了当的。

回答by razz

For a Csolution with an adjustable progress bar width, you can use the following:

对于C进度条宽度可调的解决方案,您可以使用以下方法:

#define PBSTR "||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||"
#define PBWIDTH 60

void printProgress(double percentage) {
    int val = (int) (percentage * 100);
    int lpad = (int) (percentage * PBWIDTH);
    int rpad = PBWIDTH - lpad;
    printf("\r%3d%% [%.*s%*s]", val, lpad, PBSTR, rpad, "");
    fflush(stdout);
}

It will output something like this:

它将输出如下内容:

 75% [||||||||||||||||||||||||||||||||||||||||||               ]

回答by John Bandela

Take a look at boost progress_display

看一下 boost progress_display

http://www.boost.org/doc/libs/1_52_0/libs/timer/doc/original_timer.html#Class%20progress_display

http://www.boost.org/doc/libs/1_52_0/libs/timer/doc/original_timer.html#Class%20progress_display

I think it may do what you need and I believe it is a header only library so nothing to link

我认为它可以做你需要的,我相信它是一个只有头文件的库所以没有链接

回答by Matt Kline

You can print a carriage return character (\r) to move the output "cursor" back to the beginning of the current line.

您可以打印回车符 ( \r) 将输出“光标”移回当前行的开头。

For a more sophisticated approach, take a look at something like ncurses (an API for console text-based interfaces).

对于更复杂的方法,请查看类似 ncurses(用于基于控制台文本的界面的 API)之类的东西。

回答by A J

Another way could be showing the "Dots" or any character you want .The below code will print progress indicator [sort of loading...]as dots every after 1 sec.

另一种方法可能是显示“点”或您想要的任何字符。下面的代码将在 1 秒后将进度指示器 [排序加载...] 打印为点。

PS : I am using sleep here. Think twice if performance is concern.

PS:我在这里使用睡眠。如果关注性能,请三思。

#include<iostream>
using namespace std;
int main()
{
    int count = 0;
    cout << "Will load in 10 Sec " << endl << "Loading ";
    for(count;count < 10; ++count){
        cout << ". " ;
        fflush(stdout);
        sleep(1);
    }
    cout << endl << "Done" <<endl;
    return 0;
}

回答by Flare Cat

I know I am a bit late in answering this question, but I made a simple class that does exactly what you want.(keep in mind that I wrote using namespace std;before this.):

我知道我回答这个问题有点晚了,但我做了一个简单的类,它完全符合你的要求。(请记住,我using namespace std;在此之前写过。):

class pBar {
public:
    void update(double newProgress) {
        currentProgress += newProgress;
        amountOfFiller = (int)((currentProgress / neededProgress)*(double)pBarLength);
    }
    void print() {
        currUpdateVal %= pBarUpdater.length();
        cout << "\r" //Bring cursor to start of line
            << firstPartOfpBar; //Print out first part of pBar
        for (int a = 0; a < amountOfFiller; a++) { //Print out current progress
            cout << pBarFiller;
        }
        cout << pBarUpdater[currUpdateVal];
        for (int b = 0; b < pBarLength - amountOfFiller; b++) { //Print out spaces
            cout << " ";
        }
        cout << lastPartOfpBar //Print out last part of progress bar
            << " (" << (int)(100*(currentProgress/neededProgress)) << "%)" //This just prints out the percent
            << flush;
        currUpdateVal += 1;
    }
    std::string firstPartOfpBar = "[", //Change these at will (that is why I made them public)
        lastPartOfpBar = "]",
        pBarFiller = "|",
        pBarUpdater = "/-\|";
private:
    int amountOfFiller,
        pBarLength = 50, //I would recommend NOT changing this
        currUpdateVal = 0; //Do not change
    double currentProgress = 0, //Do not change
        neededProgress = 100; //I would recommend NOT changing this
};

An example on how to use:

关于如何使用的示例:

int main() {
    //Setup:
    pBar bar;
    //Main loop:
    for (int i = 0; i < 100; i++) { //This can be any loop, but I just made this as an example
        //Update pBar:
        bar.update(1); //How much new progress was added (only needed when new progress was added)
        //Print pBar:
        bar.print(); //This should be called more frequently than it is in this demo (you'll have to see what looks best for your program)
        sleep(1);
    }
    cout << endl;
    return 0;
}

Note: I made all of the classes' strings public so the bar's appearance can be easily changed.

注意:我公开了所有类的字符串,以便可以轻松更改栏的外观。

回答by Kugel Blitz

Here is a simple one I made:

这是我制作的一个简单的:

#include <iostream>
#include <windows.h>

using namespace std;

int barl = 20;

int main() {
   system("color 0e");  
   cout << "[";     
   for (int i = 0; i < barl; i++) {         
      Sleep(100);       
      cout << ":";  
   }
   cout << "]";
}