Liebes Forum,
ich bin seit heute hier neu und versuche folgendes in einem Konsolenprogramm mit der Crt Unit zu programmieren:
Mit write eine Variable auf die Konsole ausgeben, um dann mit den Pfeiltasten und der Backspacetaste die Variable zu korrigieren und sie dann neu einzulesen, also wie bei einem TEdit. Ich krieg aber den Cursor nicht bewegt.
Hier der Beispielcode:
begin
readln(variable);
write(variable); //um mit den Pfeiltasten das falsche Zeichen anzusteuern und es zu löschen.
// Geht aber nicht. Wie programmiert man so was?
...
Danke für Eure Hilfe
[gelöst]Variable in einem Konsolenprogramm korrigieren
[gelöst]Variable in einem Konsolenprogramm korrigieren
Zuletzt geändert von Seppel am Sa 28. Okt 2023, 12:29, insgesamt 1-mal geändert.
- fliegermichl
- Lazarusforum e. V.
- Beiträge: 1354
- Registriert: Do 9. Jun 2011, 09:42
- OS, Lazarus, FPC: Lazarus Fixes FPC Stable
- CPU-Target: 32/64Bit
- Wohnort: Echzell
Re: Variable in einem Konsolenprogramm korrigieren
Man kann mit ReadKey einen Tastendruck einlesen.
Die Backspacetaste hat dabei den Wert #8. Mit Write(^h) kann man den Cursor eins nach links versetzen.
Hier ein kleines Beispiel:
Die Backspacetaste hat dabei den Wert #8. Mit Write(^h) kann man den Cursor eins nach links versetzen.
Hier ein kleines Beispiel:
Code: Alles auswählen
program Project1;
uses crt;
var s : string;
c : char;
begin
ReadLn(s);
Write(s);
repeat
c := ReadKey;
if (c = #8) then
begin
Delete(s, Length(s), 1);
Write(^h, ' ', ^h);
end else
if (c <> #13) then
begin
s := s + c;
write(c);
end;
until c = #13;
WriteLn('Am Ende ist ', s);
ReadLn;
end.
-
- Beiträge: 1878
- Registriert: Di 23. Sep 2014, 17:46
- OS, Lazarus, FPC: Win10 | Linux
- CPU-Target: x86_64
Re: Variable in einem Konsolenprogramm korrigieren
Das Problem, wenn du möchtest das sich die Konsole wie ein Edit verhält ist, das sich die Konsole in keiner weise wie ein Edit verählt.
ReadLn liest nicht einfach ein Was auf der Konsole steht, sondern die Konsole ist praktisch nur ein Visualisierungstool für Ein und Ausgabestreams.
ReadLn liest praktisch einfach nur Daten aus einer Eingabe datei ein, und WriteLn Schriebt daten in eine Ausgabedatei. Die Konsole kümmert sich dann darum Nutzereingaben in die Eingabedatei zu schreiben, und alles was vom Programm in die Ausgabedatei geschrieben wird darzustellen.
Es gibt grundsätzlich erst mal keinen wirklichen Zusammenhang zwischen der Eingabe und Ausgabedatei, sowie dem Status der Konsole, das Einlesen ist komplett unabhängig von dem was du vorher ausgegeben hast, oder was auf der Konsole bisher gedruckt wurde.
Das heist, du musst den Status des Konsolenfensters komplett selbst managen. Erschwerend kommt dabei hinzu das Konsolen normalerweise im Buffered Line Input Modus arbeiten, d.h. du bekommst normalerweise nicht mal einzelne Charactere übermittelt, sondern erst sobald die Zeile vollständig getippt wird. D.h. zwar siehst du in der Konsole was du grade tippst, aber dein Programm weis davon nix bis du enter drückst und alles auf einmal an dein Programm gesendet wird.
Dem gegenüber gibt es den Raw Input Modus, hierbei werden alle Tasten direkt und ungefiltert an dein Programm gesendet, aber dafür reagiert die Konsole nicht auf das was du tippst, d.h. der Nutzer sieht nicht was er eintippt (das muss dein Programm manuell anzeigen).
Kompliziert wird das ganze dann wenn du die CRT Unit benutzt, denn die CRT unit schaltet sich selbst, ungefragt, zwischen dein Programm und die Konsole. Sobald CRT in der Uses Klausel steht, liest ReadLn nicht mehr von der Eingabedatei, sondern von CRT, was intern einen eigenen Buffer von der EIngabedatei zieht. Gleichzeitig schaltet CRT die Konsole immer auf RAW modus, Printed eingaben aber selbständig aus um das Aussehen vom Buffered Modus zu simulieren.
Das verändert das Verhalten der Konsole massiv, vor allem im bezug auf Signal handling, und Input buffering und keyboard management. Das macht es mit der CRT Unit erstaunlich schwer komplexe Konsolenprogramme, wie z.B. eine Shell oder TUI anwendungen o.ä. zu schreiben.
Ich hab vor einigen Jahren mal was mit der CRT unit gemacht: https://github.com/Warfley/LazTextForms
Das TTFEdit z.B. ist eine Edit Artige Komponente für TUIs: https://github.com/Warfley/LazTextForms ... ls.pas#L61
Das gesagt, man kommt sehr schnell an die Grenzen der CRT unit, nicht nur Feature mäßig (sehr reduziertes Featureset, z.B. nur 16 Farben oder so), sondern auch Performancemäßig ist die CRT Unit (grade auf Windows) echt miserabel, deshalb hatte ich irgendwann mal eine eigene Bibliothek geschrieben: https://github.com/Warfley/LazTermUtils
Die praktisch die ganzen Probleme die die CRT Unit aufgrund des zwischenschaltens verursacht zu umgehen, bzw. sie nicht zu verstecken (hier im gegensatz zur CRT unit wird die Konsole nur auf Raw gestellt, wenn man explizit Raw auf True setzt, was das Verhalten der Konsole deutlich berechenbarer macht).
Langer Rede kurzer Sinn: Das was du machen willst ist absolut nicht Trivial, und da kannst du beliebig viel Zeit und Energie rein stecken. TUI Anwendungen zu bauen braucht extrem prezises State Management der Konsole, und es gibt relativ wenig hilfestellungen in form von Bibliotheken und co. Da du die Frage hier in Einsteigerfragen gestellt hast, muss ich sagen, das es leider (ich selbst finde TUI anwendungen genial) kein sehr Einsteigerfreundliches Thema ist
ReadLn liest nicht einfach ein Was auf der Konsole steht, sondern die Konsole ist praktisch nur ein Visualisierungstool für Ein und Ausgabestreams.
ReadLn liest praktisch einfach nur Daten aus einer Eingabe datei ein, und WriteLn Schriebt daten in eine Ausgabedatei. Die Konsole kümmert sich dann darum Nutzereingaben in die Eingabedatei zu schreiben, und alles was vom Programm in die Ausgabedatei geschrieben wird darzustellen.
Es gibt grundsätzlich erst mal keinen wirklichen Zusammenhang zwischen der Eingabe und Ausgabedatei, sowie dem Status der Konsole, das Einlesen ist komplett unabhängig von dem was du vorher ausgegeben hast, oder was auf der Konsole bisher gedruckt wurde.
Das heist, du musst den Status des Konsolenfensters komplett selbst managen. Erschwerend kommt dabei hinzu das Konsolen normalerweise im Buffered Line Input Modus arbeiten, d.h. du bekommst normalerweise nicht mal einzelne Charactere übermittelt, sondern erst sobald die Zeile vollständig getippt wird. D.h. zwar siehst du in der Konsole was du grade tippst, aber dein Programm weis davon nix bis du enter drückst und alles auf einmal an dein Programm gesendet wird.
Dem gegenüber gibt es den Raw Input Modus, hierbei werden alle Tasten direkt und ungefiltert an dein Programm gesendet, aber dafür reagiert die Konsole nicht auf das was du tippst, d.h. der Nutzer sieht nicht was er eintippt (das muss dein Programm manuell anzeigen).
Kompliziert wird das ganze dann wenn du die CRT Unit benutzt, denn die CRT unit schaltet sich selbst, ungefragt, zwischen dein Programm und die Konsole. Sobald CRT in der Uses Klausel steht, liest ReadLn nicht mehr von der Eingabedatei, sondern von CRT, was intern einen eigenen Buffer von der EIngabedatei zieht. Gleichzeitig schaltet CRT die Konsole immer auf RAW modus, Printed eingaben aber selbständig aus um das Aussehen vom Buffered Modus zu simulieren.
Das verändert das Verhalten der Konsole massiv, vor allem im bezug auf Signal handling, und Input buffering und keyboard management. Das macht es mit der CRT Unit erstaunlich schwer komplexe Konsolenprogramme, wie z.B. eine Shell oder TUI anwendungen o.ä. zu schreiben.
Ich hab vor einigen Jahren mal was mit der CRT unit gemacht: https://github.com/Warfley/LazTextForms
Das TTFEdit z.B. ist eine Edit Artige Komponente für TUIs: https://github.com/Warfley/LazTextForms ... ls.pas#L61
Das gesagt, man kommt sehr schnell an die Grenzen der CRT unit, nicht nur Feature mäßig (sehr reduziertes Featureset, z.B. nur 16 Farben oder so), sondern auch Performancemäßig ist die CRT Unit (grade auf Windows) echt miserabel, deshalb hatte ich irgendwann mal eine eigene Bibliothek geschrieben: https://github.com/Warfley/LazTermUtils
Die praktisch die ganzen Probleme die die CRT Unit aufgrund des zwischenschaltens verursacht zu umgehen, bzw. sie nicht zu verstecken (hier im gegensatz zur CRT unit wird die Konsole nur auf Raw gestellt, wenn man explizit Raw auf True setzt, was das Verhalten der Konsole deutlich berechenbarer macht).
Langer Rede kurzer Sinn: Das was du machen willst ist absolut nicht Trivial, und da kannst du beliebig viel Zeit und Energie rein stecken. TUI Anwendungen zu bauen braucht extrem prezises State Management der Konsole, und es gibt relativ wenig hilfestellungen in form von Bibliotheken und co. Da du die Frage hier in Einsteigerfragen gestellt hast, muss ich sagen, das es leider (ich selbst finde TUI anwendungen genial) kein sehr Einsteigerfreundliches Thema ist
-
- Beiträge: 5929
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunc)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Variable in einem Konsolenprogramm korrigieren
Den Cursor kann man mit GotoXY(x,y) beliebig in der Konsole positionieren.Mit write eine Variable auf die Konsole ausgeben, um dann mit den Pfeiltasten und der Backspacetaste die Variable zu korrigieren und sie dann neu einzulesen, also wie bei einem TEdit. Ich krieg aber den Cursor nicht bewegt.
Diese Beispiel ist mal einen Anfang.
Natürlich muss man bei einem Buchstaben "ch" noch in einen String reinpacken.
Code: Alles auswählen
uses
crt;
var
ch: char;
cp: integer;
begin
gotoxy(10, 10);
cp := 10;
repeat
ch := ReadKey;
if ch = #0 then begin // Funktionstaste
ch := ReadKey;
case ch of
#75: begin
Dec(cp);
end;
#77: begin
Inc(cp);
end;
end;
end else if ch > #31 then begin
Write(ch);
Inc(cp);
end;
GotoXY(10, 5);
WriteLn(byte(ch): 5); // Zeigt Taste an
GotoXY(cp, 10);
until ch = #27; // ESC
end.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
Re: Variable in einem Konsolenprogramm korrigieren
