2009-08-26 11 views
37

Quiero hacer una barra de progreso para mi aplicación de terminal que podría funcionar algo así como:de cómo actualizar un mensaje impreso en el terminal sin volver a imprimir (Linux)

[XXXXXXX  ] 

lo que daría una indicación visual de la cantidad de tiempo queda antes de que el proceso se complete.

Sé que puedo hacer algo como imprimir más y más de X mediante su inclusión en la cadena y luego simplemente printf, pero que se vería así:

[XXXXXXX  ] 
[XXXXXXXX  ] 
[XXXXXXXXX  ] 
[XXXXXXXXXX ] 

o algo así (obviamente, se puede jugar con el espaciado). Pero esto no es visualmente estético. ¿Hay alguna manera de actualizar el texto impreso en una terminal con texto nuevo sin reimprimir? Esto es todo bajo linux, C++.

Respuesta

40

intente utilizar \r en lugar de \n al imprimir la nueva "versión".

for(int i=0;i<=100;++i) printf("\r[%3d%%]",i); 
printf("\n"); 
+0

funciona como un amuleto, gracias – ldog

8

Yo diría que una biblioteca como ncurses se usaría para tales cosas. curses ayuda a mover el cursor por la pantalla y dibujar texto y tal.

NCurses

+6

Suena como una exageración aquí. –

+1

Sí, probablemente ... solo una sugerencia si alguien quiere ser más elegante en el futuro;) – KFro

+3

Sí ... podría haber un juego de PONG mientras esperamos la barra de progreso. : D – kjfletch

6

Algo como esto:

std::stringstream out; 
for (int i = 0; i< 10; i++) 
{ 
    out << "X"; 
    cout << "\r" << "[" << out.str() << "]"; 
} 

El bit astuto es el carácter de retorno de carro "\ r", que hace que el cursor se mueva al inicio de la línea sin tener que pasar a la siguiente línea.

1

'\ r' realizará un retorno de carro. Imagine una impresora que realiza un retorno de carro sin un salto de línea ('\ n'). Esto devolverá el punto de escritura al comienzo de la línea ... y luego volverá a imprimir su estado actualizado sobre la línea original.

1

Es un idioma diferente, pero this question podría ser de ayuda para usted. Básicamente, el carácter de escape \ (retorno de carro, en lugar de \ n Nueva línea) lo mueve de vuelta al principio de su línea impresa actual para que pueda sobrescribir lo que ya ha impreso.

1

Otra opción es simplemente imprimir un carácter a la vez. Por lo general, la salida estándar está tamponada línea, por lo que tendrá que llamar fflush (stdout) -

for(int i = 0; i < 50; ++i) { 
    putchar('X'); fflush(stdout); 
    /* do some stuff here */ 
} 
putchar('\n'); 

Pero esto no tiene la buena terminación "]" que indica la finalización.

3

Otros ya han señalado que puede usar \r para volver al comienzo de la línea actual y sobrescribir toda la línea.

Otra posibilidad es utilizar el carácter de retroceso ("\ b") para borrar algunos espacios y sobrescribir solo esos espacios. Esto puede tener un par de ventajas. Primero, obviamente evita tener que regenerar todo en la línea, lo que a veces puede ser levemente doloroso (aunque eso es bastante inusual). En segundo lugar, puede evitar algunos problemas al mostrar datos que (por ejemplo) se reducen en tamaño a medida que lo escribe; por ejemplo, si visualiza una cuenta regresiva de 100 a 0, con \r, debe tener cuidado con sobrescribiendo la longitud anterior completa, o su cuenta regresiva irá desde (por ejemplo) 100 a 990 (es decir, dejando el "0" anterior intacto).

Tenga en cuenta, sin embargo, que aunque el espacio posterior dentro de una línea normalmente funciona, un retroceso al comienzo de una línea puede o no mover la posición del cursor/escritura a una línea anterior. Para la mayoría de los propósitos prácticos, solo puede moverse dentro de una sola línea.

Cuestiones relacionadas