2009-10-02 5 views
41

Come posso cancellare la riga della console stampata corrente in C? Sto lavorando su un sistema Linux. Ad esempio -Cancellare la riga della console stampata corrente

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

Voglio stampare ciao sulla stessa riga al posto di ciao.

+0

La libreria ncurses probabilmente fare questo.Non lo conosco abbastanza bene da fornire una risposta, ma qui ci sono i collegamenti a [docs] (http://linux.die.net/man/3/clrtoeol) e [una domanda correlata] (http: // stackoverflow .com/domande/5.072.881). Questo commento è basato sulla risposta di Wil Shipley del 2009, che potrebbe essere cancellata. –

risposta

48

È possibile utilizzare VT100 escape codes. La maggior parte dei terminali, incluso xterm, sono consapevoli del VT100. Per cancellare una riga, questo è ^[[2K. In C:

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

Questo non riporta il cursore all'inizio della riga (almeno nel mio terminale), quindi '\ r' è ancora richiesto. Si noti che l'uso di '% c' non è necessario. Alternativa: 'printf (" \ 33 [2K \ r ");' – Stephan202

+3

Solo una piccola nota che la formattazione ANSI non è supportata in Windows ([ANSI escape code] (http://en.wikipedia.org/wiki/ANSI_escape_code)). Ma è ancora possibile usare 'printf (" \ r ");'. – CocoaBob

+2

@CocoaBob che ha [modificato] (http://www.nivot.org/blog/post/2016/02/04/Windows-10-TH2- (v1511) -Console-Host-Enhancements) a partire da Windows 10 aggiornamento TH2. – Hydranix

50

È possibile utilizzare un \r (carriage return) per restituire il cursore all'inizio della riga:

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

questo stampa bye sulla stessa linea. Tuttavia, non cancellerà i caratteri esistenti e poiché ciao è più breve di ciao, si finirà con byelo. Per cancellare lo potete fare la vostra nuova stampa più tempo per sovrascrivere i caratteri extra:

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

Oppure, prima cancellarlo con pochi spazi, quindi stampare la vostra nuova stringa:

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

che stamperà ciao, quindi vai all'inizio della riga e sovrascrivi con spazi, quindi torna di nuovo all'inizio e stampa ciao.

3

Di solito quando si ha un '\ r' alla fine della stringa, viene stampato solo il ritorno a capo senza alcuna nuova riga. Se si dispone quanto segue:

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

l'uscita sarà:

barooo 

Una cosa che può suggerire (forse una soluzione) è quello di avere un NULL stringa terminata dimensione fissa che viene inizializzato a tutto lo spazio caratteri, che termina con un '\ r' (ogni volta prima della stampa), quindi usa strcpy per copiare la stringa in essa (senza la nuova riga), quindi ogni stampa successiva sovrascriverà la stringa precedente. Qualcosa di simile a questo:

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

si può fare il controllo degli errori in modo che my_string è sempre almeno uno di meno di lunghezza di str, ma si ottiene l'idea di base.

3

Si potrebbe eliminare la linea usando \ b

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

Non sposta il cursore indietro di un carattere? I personaggi saranno ancora lì. Immagino che potresti fare qualcosa come "\ b \ b". –

+0

Sulla mia macchina Linux la riga viene cancellata. Forse il comportamento è diverso su altre piattaforme. –

2

i itera attraverso le parole di array di caratteri. j tiene traccia della lunghezza della parola. "\b \b" cancella la parola mentre esegue il backup su linea.

#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

Questo script è hardcoded per il tuo esempio.

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

Fare clic qui per source.

16

alcune sottigliezze vale la pena ...

\33[2K cancella l'intera linea il cursore è attualmente in

\033[A sposta il cursore su una riga, ma nel stessa colonna cioè non l'inizio del linea

\r porta il cursore all'inizio della riga (r è per il riavvolgimento), ma non cancellazione di

In xterm in particolare, ho provato le risposte di cui sopra e l'unico modo in cui ho trovato per cancellare la riga e ricominciare all'inizio è la sequenza (dal commento sopra postato da @ Stephan202 come pure @vlp e @mantal) \33[2K\r

su una nota implementazione, per farlo funzionare correttamente, ad esempio in uno scenario di conto alla rovescia dal momento che non stavo usando un carattere di nuova riga '\n' alla fine di ogni fprintf(), così ho dovuto fflush() il flusso di volta in volta (per darti un po 'di contesto, ho avviato xterm usando un fork su una macchina Linux senza reindirizzare lo stdout, stavo semplicemente scrivendo sul puntatore FILE bufferizzato fdfile con un descrittore di file non bloccante che avevo seduto o n l'indirizzo pseudo terminale che nel mio caso era /dev/pts/21):

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

Notare che ho usato sia la [2K sequenza \ 33 per cancellare la linea seguita dalla sequenza \r riavvolgimento per riposizionare il cursore all'inizio della linea. Ho dovuto fflush() dopo ogni fprintf() perché non ho un carattere di nuova riga alla fine '\n'. Lo stesso risultato senza bisogno fflush() richiederebbe la sequenza aggiuntiva a salire una linea:

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

Si noti che se si ha qualcosa sulla riga immediatamente sopra la linea che si desidera scrivere su, otterrà sovra- scritto con il primo fprintf(). Si dovrebbe lasciare una linea supplementare di cui sopra per consentire il primo movimento di una riga:

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' è l'abbreviazione di" carriage return ", non" rewind ", ed è una reliquia di vecchie vecchie macchine da scrivere, che aveva operazioni separate per" spostare il cursore sulla prima colonna "(' \ r') e "pagina precedente" alla riga successiva "(' \ n'). – ijustlovemath

0

esiste un semplice trucco è possibile lavorare qui, ma hanno bisogno di preparazione prima di stampare, devi mettere che cosa mai si vuole stampare in una variabile e quindi stampare in modo da conoscere la lunghezza per rimuovere la stringa. C'è un esempio.

#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

Ho appena trovato questo thread precedente, cercando una qualche sequenza di escape per cancellare la riga effettiva.

È piuttosto divertente a nessuno è venuta l'idea (o mi è sfuggita) che printf restituisca il numero di caratteri scritti. Quindi, stampa "\ r" + quanti caratteri vuoti restituiti da printf e rimuoveresti esattamente il testo scritto in precedenza.

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

Come ho cant utilizzare VT100, a quanto pare devo attaccare con quella soluzione