Индикатор прогресса консоли C ++ - PullRequest
7 голосов
/ 15 сентября 2009

Каким будет простой способ реализации индикатора прогресса на консоли для выполняемой задачи, но я не могу предвидеть, сколько времени это займет?

Раньше я делал это обратно, когда кодировал в Clipper, и это был только вопрос перебора символов '/', '-', '\', '|' и расположив их там же.

Любой способ / ссылки / библиотеки для этого (или что-то подобное) в C ++?

Цель для этого - * nix environment.

Правки:

  • изменил название на более связное и общее;
  • добавлена ​​целевая среда.

Ответы [ 4 ]

23 голосов
/ 15 сентября 2009

Очень простой способ сделать это - распечатать строку, за которой следует символ '\r'. Это возврат каретки сам по себе, и на большинстве консолей он возвращает курсор в начало строки, не перемещаясь вниз. Это позволяет перезаписать текущую строку.

Если вы пишете в stdout или cout или clog, не забудьте fflush или std :: flush поток, чтобы он немедленно выводил строку. Если вы пишете в stderr или cerr, тогда поток небуферизован, и весь вывод является немедленным (и неэффективным).

Более сложный способ сделать это - использовать библиотеку экранных рисунков, таких как curses. У консолей Windows есть несколько других способов настроить их для прямой записи на экран, но я не знаю, каковы они.

9 голосов
/ 15 сентября 2009

Вы можете попробовать что-то вроде:

void
spinner(int spin_seconds) {
    static char const spin_chars[] = "/-\\|";
    unsigned long i, num_iterations = (spin_seconds * 10);
    for (i=0; i<num_iterations; ++i) {
        putchar(spin_chars[i % sizeof(spin_chars)]);
        fflush(stdout);
        usleep(100000);
        putchar('\b');
    }
}

Конечно, это нестандартно из-за доли секунды usleep(), и я не уверен, есть ли какая-либо гарантия, что \b удалит символ или нет, но это работает на большинстве платформ. Вы также можете попробовать \r вместо этого, если \b не сработает. В противном случае попробуйте найти версию curses .

Редактировать (пример проклятия)

Это должно помочь вам начать:

#include <curses.h>
#include <unistd.h>

void spinner(int spin_seconds) {
    static char const spin_chars[] = "/-\\|";
    unsigned long i, num_iterations = (spin_seconds * 10);
    for (i=0; i<num_iterations; ++i) {
        mvaddch(0, 0, spin_chars[i & 3]);
        refresh();
        usleep(100000);
    }
}

int main() {
    initscr();    /* initializes curses */
    spinner(10);  /* spin for 10 seconds */
    endwin();     /* cleanup curses */
    return 0;
}

Не забудьте связать с -lcurses или -lncurses. Это должно работать на любом UNIX так же.

1 голос
/ 01 октября 2009

Boost имеет библиотеку прогресса, которая может помочь некоторым из этих вещей

0 голосов
/ 15 сентября 2009

Wow, clipper, может быть, вы говорите о вещах @ row, col, встроенных в язык? (Только риторический вопрос ...)

Вы можете делать простые индикаторы выполнения с помощью printf: вы можете пропустить завершающий перевод строки. Очевидно, что вы можете начинать или заканчивать строку с \ b, чтобы печатать символы. Это легко сделать традиционным - \ | / kind таким образом.

Напоминаю, что в руководящих принципах Eclipse UI рекомендуются индикаторы прогресса независимо от того, сколько вы смогли рассказать о реальном прогрессе. Я думаю, что теория заключалась в том, что все лучше, чем ничего, и просто стараться изо всех сил.

Единственный трюк, который вам, вероятно, понадобится, - потенциально победить буферизацию строки. Обязательно fflush(stdout) после каждой операции вывода. (Или ostream :: flush ())

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...