2009-10-02 23 views
41

¿Cómo puedo borrar la línea de la consola impresa actual en C? Estoy trabajando en un sistema Linux. Por ejemplo -Borrar la línea de la consola actual impresa

printf("hello"); 
printf("bye"); 

Quiero imprimir bye en la misma línea en lugar de hola.

+0

La librería ncurses probablemente lo hará.No lo conozco lo suficiente como para proporcionar una respuesta, pero aquí hay enlaces a [documentos] (http://linux.die.net/man/3/clrtoeol) y [una pregunta relacionada] (http: // stackoverflow .com/questions/5072881). Este comentario se basa en la respuesta de Wil Shipley de 2009, que puede eliminarse. –

Respuesta

48

Puede utilizar VT100 escape codes. La mayoría de los terminales, incluido xterm, son conscientes de VT100. Para borrar una línea, esto es ^[[2K. En C esto da:

printf("%c[2K", 27); 
+29

Esto no restablece el cursor al comienzo de la línea (en mi terminal, al menos), por lo que '\ r' todavía es necesario. Tenga en cuenta que el uso de '% c' no es necesario. Alternativa: 'printf (" \ 33 [2K \ r ");' – Stephan202

+3

Una pequeña nota de que el formato ANSI no es compatible con Windows ([código de escape ANSI] (http://en.wikipedia.org/wiki/ANSI_escape_code)). Pero aún es posible usar 'printf (" \ r ");'. – CocoaBob

+2

@CocoaBob que ha [cambiado] (http://www.nivot.org/blog/post/2016/02/04/Windows-10-TH2- (v1511) -Console-Host-Enhancements) a partir de la actualización de Windows 10 TH2. – Hydranix

50

Puede utilizar un \r (carriage return) para devolver el cursor al principio de la línea:

printf("hello"); 
printf("\rbye"); 

Esto imprimirá bye en la misma línea. Sin embargo, no borrará los caracteres existentes, y porque bye es más corto que hola, terminará con byelo. Para borrarlo puede hacer que su nueva impresión ya sobrescribir los caracteres adicionales:

printf("hello"); 
printf("\rbye "); 

O, primera borrarlo con unos espacios, a continuación, imprimir su nueva cadena:

printf("hello"); 
printf("\r   "); 
printf("\rbye"); 

que imprimirá hola, luego vaya al comienzo de la línea y sobrescríbalo con espacios, luego regrese al principio e imprima bye.

3

Normalmente, cuando aparece una '\ r' al final de la cadena, solo se imprime el retorno de carro sin ninguna nueva línea. Si usted tiene lo siguiente:

printf("fooooo\r"); 
printf("bar"); 

la salida será:

barooo 

Una cosa que puede sugerir (tal vez una solución) es tener una cadena terminada en nulo de tamaño fijo que se inicializa a todo el espacio caracteres, que terminan en '\ r' (cada vez antes de la impresión), y luego usan strcpy para copiar su cadena en él (sin la nueva línea), por lo que cada impresión subsiguiente sobrescribirá la cadena anterior. Algo como esto:

char str[MAX_LENGTH];   
// init str to all spaces, NULL terminated with character as '\r' 
strcpy(str, my_string);  // copy my_string into str 
str[strlen(my_string)] = ' '; // erase null termination char 
str[MAX_LENGTH - 1] = '\r'; 
printf(str); 

Usted puede hacer la comprobación de errores para que my_string es siempre al menos uno menos en longitud que str, pero se entiende la idea básica.

3

podría eliminar el uso de la línea \ b

printf("hello"); 
int i; 
for (i=0; i<80; i++) 
{ 
    printf("\b"); 
} 
printf("bye"); 
+4

¿No \ b solo mueve el cursor hacia atrás un carácter? Los personajes todavía estarán allí. Supongo que podrías hacer algo como "\ b \ b". –

+0

En mi caja de Linux, la línea se elimina. Tal vez el comportamiento sea diferente en otras plataformas. –

2

i itera a través de palabras matriz de caracteres. j realiza un seguimiento de la longitud de la palabra. "\b \b" borra palabra mientras retrocede sobre la línea.

#include<stdio.h> 

int main() 
{ 
    int i = 0, j = 0; 

    char words[] = "Hello Bye"; 

    while(words[i]!='\0') 
    { 
     if(words[i] != ' ') { 
      printf("%c", words[i]); 
     fflush(stdout); 
     } 
     else { 
      //system("ping -n 1 127.0.0.1>NUL"); //For Microsoft OS 
      system("sleep 0.25"); 
      while(j-->0) { 
       printf("\b \b"); 
      } 
     } 

     i++; 
     j++; 
    } 

printf("\n");     
return 0; 
} 
1

Este script está codificado para su ejemplo.

#include <stdio.h> 

int main() 
{ 

    //write some input 
    fputs("hello\n",stdout); 

    //wait one second to change line above 
    sleep(1); 

    //remove line 
    fputs("\033[A\033[2K",stdout); 
    rewind(stdout); 

    //write new line 
    fputs("bye\n",stdout); 

    return 0; 
} 

Haga clic aquí para source.

16

algunas sutilezas que valgan la pena ...

\33[2K borra toda la línea el cursor se encuentra actualmente en

\033[A mueve el cursor una línea hacia arriba, pero en la misma columna es decir, no al comienzo de la línea de

\r lleva el cursor al principio de la línea (r está para rebobinar), pero no borrar nada

En xterm específicamente, probé las respuestas mencionadas anteriormente y la única forma que encontré para borrar la línea y comenzar de nuevo al principio es la secuencia (del comentario anterior publicado por @ Stephan202 y @vlp y @mantal) \33[2K\r

en una nota de aplicación, para conseguir que funcione correctamente, por ejemplo, en un escenario de cuenta atrás ya que no estaba usando un carácter de nueva línea '\n' al final de cada fprintf(), así que tuve que fflush() la corriente cada vez (para darle un poco de contexto, comencé xterm usando un tenedor en una máquina Linux sin redireccionar stdout, solo estaba escribiendo en el puntero de archivo FILE fdfile con un descriptor de archivo no bloqueante que tenía n la dirección de la pseudo terminal que en mi caso era /dev/pts/21):

fprintf(fdfile, "\33[2K\rT minus %d seconds...", i); 
fflush(fdfile); 

Nota que he utilizado tanto el \ 33 [2K secuencia para borrar la línea seguida por la secuencia de \r de rebobinado para volver a colocar el cursor en el comienzo de la línea. Tuve que fflush() después de cada fprintf() porque no tengo un nuevo carácter de línea al final '\n'. El mismo resultado sin necesidad de fflush() requeriría la secuencia adicional para subir una línea:

fprintf(fdfile, "\033[A\33[2K\rT minus %d seconds...\n", i); 

Tenga en cuenta que si tiene algo en la línea inmediatamente por encima de la línea que desea escribir, se obtendrá exceso escrito con el primer fprintf(). Usted tendría que salir de una línea adicional superior para permitir el primer movimiento hacia arriba una línea:

i = 3; 
fprintf(fdfile, "\nText to keep\n"); 
fprintf(fdfile, "Text to erase****************************\n"); 
while(i > 0) { // 3 second countdown 
    fprintf(fdfile, "\033[A\33[2KT\rT minus %d seconds...\n", i); 
    i--; 
    sleep(1); 
} 
+0

'\ r' es la abreviatura de" retorno de carro ", no" rebobinado ", y es una reliquia de buenas máquinas de escribir antiguas, que tenían operaciones separadas para" mover el cursor a la primera columna "(' \ r') y "avanzar página a la siguiente fila "(' \ n'). – ijustlovemath

0

hay un sencillo truco se puede trabajar aquí, pero necesita preparación antes de imprimir, usted tiene que poner lo que nunca quiere imprimir en una variable y luego imprimir para saber la longitud para eliminar la cadena. Aquí hay un ejemplo.

#include <iostream> 
#include <string> //actually this thing is not nessasory in tdm-gcc 

using namespace std; 

int main(){ 

//create string variable 

string str="Starting count"; 

//loop for printing numbers 

    for(int i =0;i<=50000;i++){ 

     //get previous string length and clear it from screen with backspace charactor 

     cout << string(str.length(),'\b'); 

     //create string line 

     str="Starting count " +to_string(i); 

     //print the new line in same spot 

     cout <<str ; 
    } 

} 
0

Acabo de encontrar este hilo viejo, buscando algún tipo de secuencia de escape para poner en blanco la línea real.

Es bastante divertido que nadie haya llegado a la idea (o me la haya perdido) de que printf devuelve la cantidad de caracteres escritos. Tan solo imprima '\ r' + tantos caracteres en blanco como printf devuelto y exactamente vaciará el texto previamente escrito.

int BlankBytes(int Bytes) 
{ 
       char strBlankStr[16]; 

       sprintf(strBlankStr, "\r%%%is\r", Bytes); 
       printf(strBlankStr,""); 

       return 0; 
} 

int main(void) 
{ 
       int iBytesWritten; 
       double lfSomeDouble = 150.0; 

       iBytesWritten = printf("test text %lf", lfSomeDouble); 

       BlankBytes(iBytesWritten); 

       return 0; 
} 

Como no puedo utilizar VT100, parece que tengo que seguir con esa solución

Cuestiones relacionadas