0

我正在尝试此答案中的示例代码。

#include <iostream>
#include <thread>
#include <chrono>

void drawProgressBar(int, double);

int main() {

    drawProgressBar(30, .25);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    drawProgressBar(30, .50);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    drawProgressBar(30, .75);
    std::this_thread::sleep_for(std::chrono::seconds(1));
    drawProgressBar(30, 1);

    return 0;
}

void drawProgressBar(int len, double percent) {
    std::cout << "\x1B[2K"; // Erase the entire current line.
    std::cout << "\x1B[0E"; // Move to the beginning of the current line.
    std::string progress;
    for (int i = 0; i < len; ++i) {
        if (i < static_cast<int>(len * percent)) {
            progress += "=";
        } else {
            progress += " ";
        }
    }
    std::cout << "[" << progress << "] " << (static_cast<int>(100 * percent)) << "%" << std::flush;
}

预期的行为是这样的进度条:

[=======                       ] 25%

这将在同一行更新三次,最终为:

[==============================] 100%

3 秒后。

虽然每个进度条都按预期擦除,但下一个进度条会向下绘制一条线,而不是像我期望的那样在同一条线上。

答案(Wikipedia)中链接的文档说CSI n E( ESC[nE) wheren是一个整数:

将光标移动到第 n 行(默认为 1)行的开头。

所以我希望CSI 0 E( ESC[0E) 将光标移动到当前行的开头(0行向下)。

为什么不呢?另外,我怎样才能实现预期的行为?


Terminal.app在 OS X 上使用来运行这个程序。

4

1 回答 1

1

嗯,试试:

std::cout << "\r";

代替:

std::cout << "\x1B[2K"; // Erase the entire current line.
std::cout << "\x1B[0E"; // Move to the beginning of the current line.

这是一个回车,它应该将光标重新定位在行首。

(顺便说一句,感谢您评论您的代码。当人们在这里这样做时喜欢它:))

于 2014-08-18T03:51:45.980 回答