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

100

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

如何在 cout 或 printf 中同一位置不同时显示不同的字符串?


2
请查看 PDCurses 库 http://pdcurses.sourceforge.net/ - Lefteris
2
C++控制台进度指示器可能会有所帮助。 - David L.
3
不能生成一个wget进程? - Alexandre C.
[tag:curses] ... [tag:ncurses][tag:curses]...[tag:ncurses] - hippietrail
可能是将std :: cout倒回到行的开头的重复问题。 - kiranpradeep
只是好奇,你是如何下载文件的?你使用了哪些库或其他工具? - Flare Cat
12个回答

0
简单,你可以直接使用字符串的填充构造函数
#include <iostream> //for `cout`
#include <string>   //for the constructor
#include <iomanip>  //for `setprecision`

using namespace std;

int main()
{
    const int cTotalLength = 10;
    float lProgress = 0.3;
    cout << 
        "\r[" <<                                            //'\r' aka carriage return should move printer's cursor back at the beginning of the current line
            string(cTotalLength * lProgress, 'X') <<        //printing filled part
            string(cTotalLength * (1 - lProgress), '-') <<  //printing empty part
        "] " <<
        setprecision(3) << 100 * lProgress << "%";          //printing percentage
    return 0;
}

这将打印出:

[XXX-------] 30%

如果您需要使用纯C,并且希望能够在运行时自定义大小和填充字符:
#include <stdio.h>  //for `printf`
#include <stdlib.h> //for `malloc`
#include <string.h> //for `memset`

int main()
{
    const int cTotalLength = 10;
    char* lBuffer = malloc((cTotalLength + 1) * sizeof *lBuffer); //array to fit 10 chars + '\0'
    lBuffer[cTotalLength] = '\0'; //terminating it
    
    float lProgress = 0.3;

    int lFilledLength = lProgress * cTotalLength;
    
    memset(lBuffer, 'X', lFilledLength); //filling filled part
    memset(lBuffer + lFilledLength, '-', cTotalLength - lFilledLength); //filling empty part
    printf("\r[%s] %.1f%%", lBuffer, lProgress * 100); //same princip as with the CPP method

    //or you can combine it to a single line if you want to flex ;)
    //printf("\r[%s] %.1f%%", (char*)memset(memset(lBuffer, 'X', lFullLength) + lFullLength, '-', cTotalLength - lFullLength) - lFullLength, lProgress * 100);

    free(lBuffer);

    return 0;
}

但如果您不需要在运行时自定义它:

#include <stdio.h>  //for `printf`
#include <stddef.h> //for `size_t`

int main()
{
    const char cFilled[] = "XXXXXXXXXX";
    const char cEmpty[]  = "----------";
    float lProgress = 0.3;
    
    size_t lFilledStart = (sizeof cFilled - 1) * (1 - lProgress);
    size_t lEmptyStart  = (sizeof cFilled - 1) * lProgress;

    printf("\r[%s%s] %.1f%%",
        cFilled + lFilledStart, //Array of Xs starting at `cTotalLength * (1 - lProgress)` (`cTotalLength * lProgress` characters remaining to EOS)
        cEmpty  + lEmptyStart,  //Array of -s starting at `cTotalLength * lProgress`...
        lProgress * 100 //Percentage
    );

    return 0;
}

0

我需要创建一个进度条,这里的一些答案会导致进度条闪烁或在完成时显示不到100%的百分比。这是一个版本,除了模拟CPU工作的循环之外,没有其他循环,只有在下一个进度单元增加时才打印。

#include <iostream>
#include <iomanip> // for setw, setprecision, setfill
#include <chrono>
#include <thread> // simulate work on cpu

int main()
{
    int batch_size = 4000;
    int num_bars = 50;
    int batch_per_bar = batch_size / num_bars;

    int progress = 0;

    for (int i = 0; i < batch_size; i++) {
        if (i % batch_per_bar == 0) {    
            std::cout << std::setprecision(3) <<
                      // fill bar with = up to current progress
                      '[' << std::setfill('=') << std::setw(progress) << '>'
                      // fill the rest of the bar with spaces
                      << std::setfill(' ') << std::setw(num_bars - progress + 1)
                      // display bar percentage, \r brings it back to the beginning
                      << ']' << std::setw(3) << ((i + 1) * 100 / batch_size) << '%'
                      << "\r";
            progress++;
        }
        
        // simulate work
        std::this_thread::sleep_for(std::chrono::nanoseconds(1000000));
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接