it-swarm.com.de

Löschen Sie die aktuell gedruckte Konsolenzeile

Wie kann ich die aktuelle gedruckte Konsolenzeile in C löschen? Ich arbeite an einem Linux-System. Zum Beispiel - 

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

Ich möchte anstelle von hallo auf Wiedersehen in derselben Zeile drucken.

51
Peter

Sie können VT100-Escape-Codes verwenden . Die meisten Terminals, einschließlich xterm, sind VT100-fähig. Zum Löschen einer Zeile ist dies ^[[2K. In C ergibt sich:

printf("%c[2K", 27);
54
mouviciel

Sie können einen \r ( carriage return ) verwenden, um den Cursor an den Anfang der Zeile zu bringen:

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

Dadurch wird bye in derselben Zeile gedruckt. Die vorhandenen Zeichen werden jedoch nicht gelöscht. Da bye kürzer als hello ist, landen Sie bei byelo. Um es zu löschen, können Sie den neuen Ausdruck verlängern, um die zusätzlichen Zeichen zu überschreiben:

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

Oder löschen Sie ihn zuerst mit ein paar Leerzeichen und drucken Sie dann Ihre neue Zeichenfolge:

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

Das wird hello drucken, dann zum Anfang der Zeile gehen und es mit Leerzeichen überschreiben, dann wieder zum Anfang zurückgehen und bye drucken.

52
Andre Miller

Einige lohnende Feinheiten ...

\33[2K löscht die gesamte Zeile, in der sich der Cursor gerade befindet

\033[A bewegt den Cursor um eine Zeile nach oben, jedoch in der gleichen Spalte d. h. nicht an den Zeilenanfang

\r bringt den Cursor an den Anfang der Zeile (r ist für Rücklauf), aber löscht nichts löscht nichts

Insbesondere in xterm habe ich die oben genannten Antworten ausprobiert. Die einzige Möglichkeit, die Zeile zu löschen und am Anfang neu zu beginnen, ist die Reihenfolge (aus dem Kommentar von @ Stephan202 sowie @vlp und @mantal). \33[2K\r

In einem Implementierungshinweis, damit er beispielsweise in einem Countdown-Szenario ordnungsgemäß funktioniert, da ich kein neues Zeilenzeichen '\n'at am Ende jeder fprintf() verwendet habe, also musste ich den Stream jedes Mal fflush() (geben) Sie etwas Kontext, ich begann Xterm mit einer Gabel auf einem Linux-Rechner ohne stdout umzuleiten, ich schrieb nur in den gepufferten FILE-Zeiger fdfile mit einem nicht-blockierenden Dateideskriptor, den ich auf der Pseudo-Terminaladresse saß, die in meinem Fall /dev/pts/21 :

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

Beachten Sie, dass ich sowohl die\33 [2K-Sequenz verwendet habe, um die Zeile zu löschen, als auch die \r-Rückspulsequenz, um den Cursor am Anfang der Zeile zu positionieren. Ich musste fflush() nach jeder fprintf(), da am Ende '\n' kein neues Zeilenzeichen vorhanden ist. Dasselbe Ergebnis ohne fflush () würde die zusätzliche Sequenz erfordern, um eine Zeile nach oben zu gehen:

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

Wenn Sie etwas in der Zeile direkt über der Zeile haben, auf die Sie schreiben möchten, wird diese mit dem ersten fprintf () überschrieben. Sie müssten eine zusätzliche Zeile oben lassen, um die erste Bewegung um eine Zeile zu ermöglichen:

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);
}
25
J-a-n-u-s

Sie können die Zeile mit\b löschen

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

Wenn Sie am Ende der Zeichenfolge ein '\ r' haben, wird normalerweise nur ein Wagenrücklauf ohne Zeilenvorschub gedruckt. Wenn Sie folgendes haben:

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

die Ausgabe wird sein:

barooo

Eine Sache, die ich vorschlagen kann (möglicherweise eine Problemumgehung), besteht darin, eine NULL-terminierte Zeichenfolge mit fester Größe zu haben, die mit allen Leerzeichen initialisiert wird und mit einem "\ r" endet (jedes Mal vor dem Drucken). Anschließend können Sie Ihre Zeichenfolge mit strcpy kopieren it (ohne Newline), so dass bei jedem nachfolgenden Druck die vorherige Zeichenfolge überschrieben wird. Etwas wie das:

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

Sie können eine Fehlerprüfung durchführen, so dass my_string immer mindestens eine kürzere Länge hat als str, Sie erhalten jedoch die Grundidee.

3
Ashwin

i durchläuft Char-Array-Wörter. j verfolgt die Wortlänge. "\b \b" löscht Word, während über die Leitung zurückgesetzt wird.

#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;
}
2
Paul T

Dieses Skript ist für Ihr Beispiel fest codiert.

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

Klicken Sie hier für source .

1
vlp

es gibt einen einfachen Trick, den Sie hier bearbeiten können, aber es muss vor dem Drucken vorbereitet werden. Sie müssen das, was Sie drucken möchten, in eine Variable einfügen und dann drucken, damit Sie wissen, wie lang die Zeichenfolge ist.

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

}
1
Aylian Craspa

unter Windows 10 können Sie den VT100-Stil verwenden, indem Sie den VT100-Modus in der aktuellen Konsole aktivieren und die folgenden Escape-Sequenzen verwenden:

#include <windows.h>
#include <iostream>

#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#define DISABLE_NEWLINE_AUTO_RETURN  0x0008

int main(){

  // enabling VT100 style in current console
  DWORD l_mode;
  HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
  GetConsoleMode(hStdout,&l_mode)
  SetConsoleMode( hStdout, l_mode |
            ENABLE_VIRTUAL_TERMINAL_PROCESSING |
            DISABLE_NEWLINE_AUTO_RETURN );

  // create a waiting loop with changing text every seconds
  while(true) {
    // erase current line and go to line begining 
    std::cout << "\x1B[2K\r";
    std::cout << "wait a second .";
    Sleep(1);
    std::cout << "\x1B[2K\r";
    std::cout << "wait a second ..";
    Sleep(1);
    std::cout << "\x1B[2K\r";
    std::cout << "wait a second ...";
    Sleep(1);
    std::cout << "\x1B[2K\r";
    std::cout << "wait a second ....";
 }

}

siehe folgenden Link: Windows VT1

0
user2019716

Ich habe gerade diesen alten Thread gefunden und nach einer Art Escape-Sequenz gesucht, um die eigentliche Zeile auszublenden. 

Es ist schon komisch, dass niemand auf die Idee kam (oder ich habe es versäumt), dass printf die Anzahl der geschriebenen Zeichen zurückgibt. Drucken Sie einfach '\ r' + so viele Leerzeichen, wie printf zurückgegeben hat, und Sie werden den zuvor geschriebenen Text genau ausschneiden.

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

Da ich VT100 nicht verwenden kann, muss ich mich an diese Lösung halten

0
David
echo -e "hello\c" ;sleep 1 ; echo -e "\rbye  "

Was der obige Befehl bewirkt:

  1. Es wird Hallo gedruckt und der Cursor bleibt auf "o" (mit\c)

  2. Dann wartet es 1 Sek. (Schlaf 1)

  3. Dann wird hallo durch tschüss ersetzt. (Mit\r)

NOTE : Using ";", We can run multiple command in a single go.

0
Ayush Mahajan