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

新手上路,请多包涵

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

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

原文由 xmllmx 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 970
2 个回答

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

 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

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

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

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

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

此外,当然可以在 C 中使用 printf 来完成相同的操作;修改上面的代码应该是直截了当的。

原文由 leemes 发布,翻译遵循 CC BY-SA 3.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;
}

原文由 WENDYN 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题