Frage

In den meisten modernen Schalen können Sie die nach oben und unten Pfeile treffen und es wird gesagt, an der Eingabeaufforderung vorherigen Befehle, die Sie ausgeführt haben. Meine Frage ist, wie funktioniert das?!

Es scheint mir, dass die Schale irgendwie stdout manipuliert zu überschreiben, was er bereits geschrieben hat?

Ich stelle fest, dass Programme wie wget tun dies auch. Hat jemand eine Ahnung, wie sie es tun?

War es hilfreich?

Lösung

Es ist nicht stdout Manipulation -. Es die Zeichen ist überschreiben, die bereits durch das Terminal angezeigt wurde

Versuchen Sie folgendes:

#include <stdio.h>
#include <unistd.h>
static char bar[] = "======================================="
                    "======================================>";
int main() {
    int i;
    for (i = 77; i >= 0; i--) {
        printf("[%s]\r", &bar[i]);
        fflush(stdout);
        sleep(1);
    }
    printf("\n");
    return 0;
}

Das ist ziemlich nah an wget des Ausgang, nicht wahr? \r ist ein Wagenrücklauf, der das Terminal als „die Cursor zurück zu dem Anfang der aktuellen Zeile bewegen“ interpretiert.

Ihre Schale, wenn es bash ist, verwendet das GNU Readline-Bibliothek , die viel mehr bietet allgemeine Funktionalität, einschließlich der Erkennung Terminaltypen, Geschichte Management, programmierbare Tastenbelegungen, etc.

Eine weitere Sache -. Im Zweifelsfall die Quelle für Ihre wget, Shell, etc. sind alle verfügbaren

Andere Tipps

Um die aktuelle Standard-Ausgangsleitung (oder Teile davon) verwenden \r überschreiben (oder \b.) Der besonderen Charakter \r (Carriage Return) wird die Einfügemarke an den Anfang der Zeile zurückkehren, so dass Sie es zu überschreiben. Der besondere Charakter \b wird die Einfügemarke eine Position nach hinten nur bringen, so dass Sie das letzte Zeichen zu überschreiben, z.

#include <stdio.h>
#include <unistd.h>

int i;
const char progress[] = "|/-\\";

for (i = 0; i < 100; i += 10) {
  printf("Processing: %3d%%\r",i); /* \r returns the caret to the line start */
  fflush(stdout);
  sleep(1);
}
printf("\n"); /* goes to the next line */
fflush(stdout);

printf("Processing: ");
for (i = 0; i < 100; i += 10) {
  printf("%c\b", progress[(i/10)%sizeof(progress)]); /* \b goes one back */
  fflush(stdout);
  sleep(1);
}
printf("\n"); /* goes to the next line */
fflush(stdout);

Verwenden fflush(stdout); weil Standardausgabe in der Regel und die Information kann gepuffert sonst nicht unmittelbar auf der Ausgangsklemme oder

gedruckt

Zusätzlich r und \ b \, werfen Sie einen Blick auf ncurses für einige erweiterte Kontrolle über was auf dem Konsolenbildschirm. (Spalten Einschließlich, um willkürlich bewegen, etc).

Ein Programm in einem Text-Terminal läuft / console können den Text in seiner Konsole auf verschiedene Weise angezeigt manipulieren (Text fett machen, bewegen Sie den Cursor, klaren Bildschirm etc.). Dies wird durch den Druck speziellen Zeichenfolgen erreicht, die so genannte „Escape-Sequenzen“ (weil sie in der Regel mit Flucht beginnen , ASCII 27).

Wenn stdout an einen Terminal geht, die diese Escape-Sequenzen versteht, wird die Anzeige des Terminals entsprechend ändern.

Wenn Sie stdout in eine Datei umleiten, die Escape-Sequenzen in der Datei angezeigt werden (das ist in der Regel nicht, was Sie wollen).

Es gibt keinen vollständigen Standard für die Escape-Sequenzen, aber die meisten Terminals verwenden die eingeführten Sequenzen von VT100 , mit vielen Erweiterungen. Dies ist, was die meisten Terminals unter Unix / Linux (xterm, rxvt, konsole) und andere wie PuTTY verstehen.

In der Praxis würden Sie nicht direkt Escape-Sequenzen in Ihre Software codieren (obwohl man könnte), sondern eine Bibliothek verwenden sie, wie ncurses oder GNU readline- oben erwähnt. Dies ermöglicht die Kompatibilität mit verschiedenen Terminaltypen.

Es ist geschaffen mit der Readline- Bibliothek ... I‘ m nicht sicher, wie es hinter den Kulissen funktioniert, aber ich glaube nicht, dass irgendetwas mit stdout oder Streams zu tun hat. Ich vermute, Readline- verwendet irgendeine Art von kryptischen (für mich zumindest) Terminal-Befehle - das heißt, arbeitet es mit dem Terminal-Programm, das die Shell-Sitzung tatsächlich anzeigt. Ich weiß nicht, dass Sie Readline- ähnliches Verhalten bekommen kann nur durch Ausgabe gedruckt wird.

(Denken Sie darüber nach. Stdout in eine Datei umgeleitet werden kann, aber der Auf- / Ab-Pfeiltasten Trick funktioniert nicht auf Dateien)

Sie können Wagenrücklauf verwenden, um dies zu simulieren.

#include <stdio.h>

int main(int argc, char* argv[])
{
    while(1)
    {
        printf("***********");
        fflush(stdout);
        sleep(1);
        printf("\r");
        printf("...........");
        sleep(1);
    }

    return 0;
}

Das Programm tut dies durch Sonderzeichen drucken möchten, in das Terminal in besonderer Weise interpretiert. Die einfachste Version davon ist (auf den meisten Linux / Unix-Terminals) ‚\ r‘ (Carriage Return) zum normalen stdout zu drucken, die die Cursor-Position auf das erste Zeichen in der aktuellen Zeile zurücksetzt. Also das, was Sie als nächstes schreiben wird überschreiben Sie die Zeile, die Sie vorher geschrieben haben. Dies kann für einfache Statusanzeigen verwendet werden, zum Beispiel.

int i = 0;
while (something) {
  i++;
  printf("\rprocessing line %i...", i);
  ...
}

Aber es gibt kompliziertere Escape-Zeichen-Sequenzen, die auf verschiedene Weise interpretiert werden. Alle möglichen Dinge können mit diesem fertig werden, wie Sie den Cursor an einer bestimmten Position auf dem Bildschirm oder die Einstellung der Textfarbe. Wenn oder wie diese Zeichenfolge interpretiert werden, hängt von Ihrem Terminal, sondern eine gemeinsame Klasse unterstützt von den meisten Terminals ist

Der einfachste Weg ist, zu drucken, das Wagenrücklaufzeichen ( '\ r') nach stdout.

wird der Cursor an den Anfang der Zeile bewegt werden, so dass Sie den Inhalt zu überschreiben.

scroll top