Как откат строк от cout?

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

Я настаиваю на "нескольких", потому что \b выполняет задание для одной строки, но не стирает \n между строками.

Я попробовал std::cout.seekp(std::cout.tellp() - str.length());, но tellp() возвращает -1 (сбой).

Ответ 1

Вы можете сделать cout << '\r';, чтобы перейти к началу текущей строки, но перемещение вверх зависит от системы. Для Unix см. man termcap и man terminfo (и найдите cursor_up). На ANSI-совместимых терминалах (таких как большинство современных терминалов, доступных в Unix) это работает для продвижения вверх: cout << "\e[A";.

Не пытайтесь искать в cout, большую часть времени его невозможно найти (кроме случаев, когда он перенаправлен в файл).

Как упоминалось в других ответах, использование библиотеки ncurses (или сленга) обеспечивает хорошую абстракцию для терминального ввода-вывода в Unix.

Вместо заполнения пробелами (что подвержено ошибкам, поскольку не каждый терминал имеет ширину 80 символов), вы можете выполнить \r + clr_eol: std::cout << "\r\e[K" << std::flush.

Ответ 2

Используйте библиотеку форматирования вывода, такую ​​как ncurses, если можете; это значительно упрощает терминальные манипуляции.

Ответ 3

Ни C, ни С++ не определяют ничего подобного. Вам нужна явная манипуляция терминала. В Unix вы можете использовать curses. Не знаю, что там для Windows.

Ответ 4

Я знаю, что это старый пост, но принятый не распространяется на случаи, когда cout отправляется в программу или файл, и это верх моих поисковых запросов. Следующее будет обрабатывать как трубчатые, так и непигоризованные stdout с немного другим поведением.

#include <iostream>
#include <functional>
#include <stdio.h>

#ifdef _WIN32
#include <io.h>
#else
#include <unistd.h>
#define _isatty isatty
#define _fileno fileno
#endif

const std::function<void(const size_t&)> progress_printer(_isatty(_fileno(stdout)) == 1 ?
    [](const size_t& i) {
        std::cout << "\rNumber " << i << std::flush;
    } :
    [](const size_t& i) {
        static std::ios::off_type last(-1);
        if(last != -1)
            std::cout.seekp(last, std::ios::beg);
        last = std::cout.tellp();
        std::cout << "Number " << i << std::endl;
    }
);

Это не проверено на окнах, но должно работать. Что он делает, это определить, является ли дескриптор файла или является tty. Если это так, то он просто пишет '\ r', если pos не изменился с момента последнего его печати или новой строки. Если он не является символом новой строки, он ищет последнее место после печати. ​​

Он ведет себя по-разному для файлов, чем для tty. Для файла, если что-то выводит поток между отпечатками, он может перезаписать некоторые или все, что было написано даже после строк новой строки. Для ttys он просто перезаписывает символы в начале текущей строки.

Ответ 5

Надеюсь, это поможет;) [Это должно работать в Linux.]

// "\e[0K" Clear line from cursor to the end
cout << "\e[A\r\e[0K"<<what_you_want<<endl;

Ответ 6

Вы можете использовать первую систему (""); потому что вы можете использовать \e [A (Dev-С++) или \u001B [A (Visual Studio)

#include <iostream>
using namespace std;
int main()
{
    system(" ");
    string Input;
    do
    {
        cout << "[#][\e[s";
        cin >> Input;
        cout << "[\e[u" << Input << "]"<<endl;

    } while (2==2);
    return 0;
}

введите описание изображения здесь