2010-07-18 22 views
7

Estoy codificando un monitoreo de tareas, que actualiza el progreso de las tareas usando cout. Me gustaría mostrar un progreso de la tarea por línea, por lo tanto, tengo que deshacer varias líneas de la consola.Cómo revertir líneas desde cout?

Insisto en "varios" porque \b hace el trabajo para una línea, pero no borra \n entre líneas.

Intenté std::cout.seekp(std::cout.tellp() - str.length()); pero tellp() devuelve -1 (error).

+2

No puedes. 'cout' no representa la consola. Representa una secuencia de salida. Eso significa que puede escribir en él, pero no puede hacer nada con respecto a lo que ya se ha escrito. 'cout' es para imprimir el resultado a cualquier dispositivo de salida que use la plataforma (por ejemplo, pero no necesariamente, una ventana de consola). Si necesita manipular la consola específicamente, debe usar una biblioteca específica del sistema operativo que conozca la ventana de la consola. – jalf

+1

¿Por qué quieres borrar la lista de tareas completadas? Simplemente imprima un elemento de progreso de la tarea por línea, y se reproducirá mejor si alguien ejecuta su programa y canaliza stdout a un archivo de registro. – jamesdlin

+0

Lo sé, pero habrá MUCHAS líneas, no quiero ahogar al usuario en infos, simplemente darle el estado y el porcentaje de progreso de cada tarea que obtuve. –

Respuesta

16

Puede hacer cout << '\r'; para saltar al principio de la línea actual, pero moverse hacia arriba es específico del sistema. Para Unix, vea man termcap y man terminfo (y busque cursor_up). En terminales compatibles con ANSI (como la mayoría de los terminales modernos disponibles en Unix), esto funciona para subir: cout << "\e[A";.

No intente buscar en cout, es desechable la mayor parte del tiempo (excepto cuando se redirige a un archivo). ( o argot) biblioteca

Como se ha mencionado en otras respuestas, utilizando los ncurses proporciona una buena abstracción para el terminal de E/S en Unix.

+0

Gracias, dejé de monitorear varias líneas, y usé \ r - fill 79 espacios - \ r en su lugar. –

8

Utilice una biblioteca de formato de salida como ncurses si puede; esto simplifica significativamente la manipulación del terminal.

5

Ni C ni C++ definen algo así. Necesitas manipulación de terminal explícita. En Unix puede usar curses. No tengo idea de lo que hay para Windows.

1

Sé que esta es una publicación anterior, pero la aceptada no cubre los casos en que cout se canaliza a un programa o archivo y esta es la parte superior de mis búsquedas en Google. Lo siguiente manejará tanto stdout con y sin tubería con un comportamiento ligeramente diferente.

#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; 
    } 
); 

Esto no se ha probado en Windows, pero debería funcionar. Lo que hace es detectar si el descriptor de archivo o es un tty. Si es así, simplemente escribe '\ r' si la posición no ha cambiado desde la última vez que se imprimió o una nueva línea. Si no es una línea nueva, busca el último lugar después de que se imprimió.

Se comporta de manera diferente para los archivos que para tty. Para un archivo, si algo sale a la secuencia entre las impresiones, entonces puede sobrescribir parte o todo lo que se escribió incluso después de las nuevas líneas. Para ttys, simplemente sobrescribe los caracteres al principio de la línea actual.

+0

viejo pero aún dorado – LRP