2012-06-11 30 views
5

que utilice las siguientes líneas a información progreso de salida de mi simulación en mi programa C++,eliminación de parpadeo del cursor en la terminal, ¿cómo?

double N=0; 
double percent=0; 
double total = 1000000; 
for (int i; i<total; ++i) 
{ 
    percent = 100*i/total; 
    printf("\r[%6.4f%%]",percent); 
} 

Trabaja muy bien!

Pero el problema es que veo que el cursor del terminal sigue parpadeando cíclicamente a través de los números, esto es muy molesto, ¿alguien sabe cómo deshacerse de esto?

He visto algunos programas como wget o ubuntu apt, usan la barra de progreso o porcentajes también, pero parece que no hay problema con el cursor parpadeante, me pregunto cómo lo hicieron?

Gracias!

Respuesta

10

Solo supongo: intente utilizar una cantidad adecuada de caracteres '\ b' (retroceso) en lugar de '\ r'.

== == EDITAR

No soy un mago shell de Linux, pero esto puede funcionar:

system("setterm -cursor off"); 
// ...display percentages... 
system("setterm -cursor on"); 

No se olvide de #include <cstdlib> o <iostream>.

+0

Desafortunadamente, no tiene éxito :( – Daniel

+0

¿Por qué necesita porcentajes? Simplemente puede escribir caracteres '#', uno tras otro. Por ejemplo, un '#' por cada 10% nuevo – kol

+0

OOPS, me encantan los números :) Bien, Intentaré # y le dejaré saber los resultados, pero de todos modos, solo un google, alguien dijo que wget no usó ncurses – Daniel

0

Esas aplicaciones probablemente estén usando ncurses. Ver mvaddstr

+0

wget y el FBI son dos ejemplos de programas que no usan ncurses, pero pueden ocultar completamente el cursor. –

16

Puede ocultar y mostrar el cursor utilizando el DECTCEM (cursor de texto modo Dec habilitar) el modo en DECSM y DECRM:

fputs("\e[?25l", stdout); /* hide the cursor */ 

fputs("\e[?25h", stdout); /* show the cursor */ 
+0

Quiere decir en el ciclo, después de este comando 'printf (" \ r [% 6.4f %%] ", porcentaje);' ? – Daniel

+0

donde sea que se requieran. Por lo general, oculta el cursor antes de cualquier actualización, realiza todas las actualizaciones y luego vuelve a mostrarlo al final. Incluso podría combinarlos todos en un solo 'printf' si lo desea. – LeoNerd

0

Una forma de evitar un cursor parpadeante es (como se sugiere) para ocultar el cursor temporalmente.

Sin embargo, eso es solo parte de la solución. Su programa también debe tener esto en cuenta:

  • después de ocultar el cursor y la modificación de la pantalla, antes de mostrando el cursor de nuevo movimiento de nuevo a la ubicación original.
  • ocultar/mostrar el cursor solo mantiene el cursor parpadeando notablemente cuando las actualizaciones toman solo una pequeña cantidad de tiempo. Si por casualidad mezcló esto con un proceso lento, su cursor parpadeará.

La solución sugerida que usa setterm no es portátil; es específico para la consola de Linux. Y ejecutar un ejecutable usando system no es realmente necesario. Pero incluso corriendo

system("tput civis"); 
... 
system("tput cnorm"); 

es una mejora sobre el uso de setterm.

Al verificar el código fuente de wget no se encuentran secuencias de escape que oculten el cursor. Lo que está viendo con su barra de progreso es que deja el cursor en más o menos el mismo lugar cada vez que hace algo que consume mucho tiempo. La salida al terminal lleva tan poco tiempo que no se nota la reescritura momentánea de la línea (imprimiendo un retorno de carro, luego escribiendo la mayor parte de la línea).Si fuera más lento, ocultar el cursor ayudaría a — hasta un punto.

Por cierto — esta técnica de ocultación de cursor se utiliza en los controladores de terminal para algunos editores (vim y vile).

+0

Creo que la razón por la cual 'wget' no tiene este problema es porque imprimen en' stderr' que está sin búfer, en lugar de 'stdout' que está almacenado. – santileortiz

-1

La razón por la que el cursor salta es porque stdout se almacena temporalmente, por lo que no se sabe realmente cuántos caracteres se imprimen en algún momento en el tiempo. El motivo wget no tiene un cursor saltado es que en realidad están imprimiendo en stderr. Pruebe lo siguiente:

fprintf(stderr,"\r[%6.4f%%]",percent); 

Esto también tiene la ventaja de no estorbar el archivo si va a guardar el resto de la salida de algún lugar utilizando una pipa como:

$ ./executable > log.data 
Cuestiones relacionadas